| | 2 | #include <iostream> |
| | 3 | #include <ode/ode.h> |
| | 4 | |
| | 5 | using namespace std; |
| | 6 | |
| | 7 | |
| | 8 | //see below for example |
| | 9 | #define ENTLEAF(CLASS, CLASSID, CLASSNAME) \ |
| | 10 | virtual uint16_t get_classid() { return Ent::CLASSID; };\ |
| | 11 | virtual const std::string get_classname() { return CLASSNAME; }; \ |
| | 12 | static Ent* create(Game *game, uint16_t entid) { return new CLASS(game, entid); }; |
| | 13 | |
| | 14 | //always declare constructor as protected! |
| | 15 | #define ENTLEAFCON(CLASS, PARENT) \ |
| | 16 | CLASS(Game *game, uint16_t entid) : PARENT(game, entid) {}; |
| | 17 | |
| | 18 | class Game; |
| 23 | | class Obj : public Ent { |
| 24 | | protected: |
| 25 | | Obj(uint16_t entid) : Ent(entid) {}; |
| | 42 | |
| | 43 | class Game { |
| | 44 | private: |
| | 45 | map<uint16_t, Ent::createfct> id2ent; |
| | 46 | map<uint16_t, Ent*> ents; |
| | 47 | uint16_t entcnt; |
| | 48 | public: |
| | 49 | Game(); |
| | 50 | virtual Ent *entcreate(uint16_t classid) { |
| | 51 | Ent::createfct createfct=id2ent[classid]; |
| | 52 | if (!createfct) { |
| | 53 | cout << classid << "No createfct! earth-shaking exception would be thrown in production code!" << endl; |
| | 54 | } |
| | 55 | Ent *ent = createfct(this, entcnt); |
| | 56 | if (!ent) { |
| | 57 | cout << entcnt << "No ent! earth-shaking exception would be thrown in production code!" << endl; |
| | 58 | } |
| | 59 | ents[entcnt++]=ent; |
| | 60 | return ent; |
| | 61 | }; |
| | 62 | |
| | 63 | virtual void entdelete(uint16_t entid) { |
| | 64 | Ent *ent=ents[entid]; |
| | 65 | if (!ent) { |
| | 66 | cout << entcnt << "No ent! earth-shaking exception would be thrown in production code!" << endl; |
| | 67 | } |
| | 68 | ents.erase(entid); |
| | 69 | delete ent; |
| | 70 | }; |
| | 71 | |
| | 72 | template <class CLASS> CLASS * entcreate(uint16_t classid) { |
| | 73 | CLASS *ent=dynamic_cast<CLASS *>(entcreate(classid)); |
| | 74 | if (!ent) { |
| | 75 | cout << classid << "No createfct! earth-shaking exception would be thrown in production code!" << endl; |
| | 76 | } |
| | 77 | return ent; |
| | 78 | }; |
| | 79 | |
| | 80 | virtual ~Game() {}; //needed in order to do dynamic_cast<ODEGame *>(Game *) |
| 39 | | Pad(uint16_t entid) : Box(entid) {}; |
| 40 | | public: |
| 41 | | virtual uint16_t get_classid() { return Ent::Pad; }; |
| 42 | | virtual const std::string get_classname() { return "Pad"; }; |
| 43 | | static Ent* create(uint16_t entid) { return new Pad(entid); }; |
| | 95 | ODEEnt(Game *game, uint16_t entid) : Ent(game, entid) { |
| | 96 | odegame = dynamic_cast<ODEGame*>(game); |
| | 97 | if (!odegame) { |
| | 98 | //throw earth-shaking exception (since we've been cheated!!!) |
| | 99 | cout << "earth-shaking exception would be thrown in production code!" << endl; |
| | 100 | } |
| | 101 | }; |
| | 102 | ODEGame *getodegame() { return odegame; }; |
| 46 | | #define ENTLEAF(CLASS, CLASSID, CLASSNAME) \ |
| 47 | | virtual uint16_t get_classid() { return Ent::CLASSID; };\ |
| 48 | | virtual const std::string get_classname() { return CLASSNAME; }; \ |
| 49 | | static Ent* create(uint16_t entid) { return new CLASS(entid); }; |
| 50 | | |
| 51 | | //now this is shorter (!): |
| 52 | | class Sphere : public Ent { |
| | 105 | //example of non-leaf Ent (note the dGeom* parameter for constructor) |
| | 106 | class ODEBody : public ODEEnt { |
| | 107 | private: |
| | 108 | dBody body; |
| | 109 | dGeom *geom; |
| 54 | | Sphere(uint16_t entid) : Ent(entid) {}; |
| 55 | | public: |
| 56 | | ENTLEAF(Sphere, Sphere, "Sphere"); |
| | 111 | ODEBody(Game *game, uint16_t entid, dGeom *_geom) : ODEEnt(game, entid) { |
| | 112 | body.create(getodegame()->world); |
| | 113 | body.setData(this); |
| | 114 | geom = _geom; |
| | 115 | if (!geom) { //we only allow Bodys with a geometry |
| | 116 | //throw earth-shaking exception (since we've been cheated!!!) |
| | 117 | cout << entid << "earth-shaking exception would be thrown in production code!" << endl; |
| | 118 | } |
| | 119 | getodegame()->space.add(*geom); |
| | 120 | }; |
| | 121 | template <class GEOM> GEOM *getgeom() { |
| | 122 | return static_cast<GEOM *>(geom); //no way to check since dGeom isnt polymorphic |
| | 123 | } |
| | 124 | //TODO: |
| | 125 | void setposition(dReal x) {}; |
| | 135 | |
| | 136 | class ODEPad : public ODEBox { |
| | 137 | protected: |
| | 138 | ENTLEAFCON(ODEPad, ODEBox); |
| | 139 | public: |
| | 140 | ENTLEAF(ODEPad, Pad, "Pad"); |
| | 141 | }; |
| | 142 | |
| | 143 | class ODESphere : public ODEBody { |
| | 144 | protected: |
| | 145 | ODESphere(Game *game, uint16_t entid) : ODEBody(game, entid, new dSphere(1.0)) {}; |
| | 146 | public: |
| | 147 | ENTLEAF(ODESphere, Sphere, "Sphere"); |
| | 148 | void setradius(dReal r) { getgeom<dSphere>()->setRadius(r); }; |
| | 149 | dReal getradius() { return getgeom<dSphere>()->getRadius(); }; |
| | 150 | }; |
| | 151 | |
| | 152 | class ODEPBall : public ODESphere { |
| | 153 | protected: |
| | 154 | ENTLEAFCON(ODEPBall, ODESphere); |
| | 155 | public: |
| | 156 | ENTLEAF(ODEPBall, PlayerBall, "PlayerBall"); |
| | 157 | }; |