example.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include "oxygine-framework.h"
  2. #include "Box2D/Box2D.h"
  3. #include "Box2DDebugDraw.h"
  4. using namespace oxygine;
  5. //it is our resources
  6. //in real project you would have more than one Resources declarations. It is important on mobile devices with limited memory and you would load/unload them
  7. Resources gameResources;
  8. //DECLARE_SMART is helper, it does forward declaration and declares intrusive_ptr typedef for your class
  9. DECLARE_SMART(MainActor, spMainActor);
  10. const float SCALE = 100.0f;
  11. b2Vec2 convert(const Vector2& pos)
  12. {
  13. return b2Vec2(pos.x / SCALE, pos.y / SCALE);
  14. }
  15. Vector2 convert(const b2Vec2& pos)
  16. {
  17. return Vector2(pos.x * SCALE, pos.y * SCALE);
  18. }
  19. DECLARE_SMART(Circle, spCircle);
  20. class Circle : public Sprite
  21. {
  22. public:
  23. Circle(b2World* world, const Vector2& pos, float scale = 1)
  24. {
  25. setResAnim(gameResources.getResAnim("circle"));
  26. setAnchor(Vector2(0.5f, 0.5f));
  27. setTouchChildrenEnabled(false);
  28. b2BodyDef bodyDef;
  29. bodyDef.type = b2_dynamicBody;
  30. bodyDef.position = convert(pos);
  31. b2Body* body = world->CreateBody(&bodyDef);
  32. setUserData(body);
  33. setScale(scale);
  34. b2CircleShape shape;
  35. shape.m_radius = getWidth() / SCALE / 2 * scale;
  36. b2FixtureDef fixtureDef;
  37. fixtureDef.shape = &shape;
  38. fixtureDef.density = 1.0f;
  39. fixtureDef.friction = 0.3f;
  40. body->CreateFixture(&fixtureDef);
  41. body->SetUserData(this);
  42. }
  43. };
  44. DECLARE_SMART(Static, spStatic);
  45. class Static : public Box9Sprite
  46. {
  47. public:
  48. Static(b2World* world, const RectF& rc)
  49. {
  50. //setHorizontalMode(Box9Sprite::TILING_FULL);
  51. //setVerticalMode(Box9Sprite::TILING_FULL);
  52. setResAnim(gameResources.getResAnim("pen"));
  53. setSize(rc.getSize());
  54. setPosition(rc.getLeftTop());
  55. setAnchor(Vector2(0.5f, 0.5f));
  56. b2BodyDef groundBodyDef;
  57. groundBodyDef.position = convert(getPosition());
  58. b2Body* groundBody = world->CreateBody(&groundBodyDef);
  59. b2PolygonShape groundBox;
  60. b2Vec2 sz = convert(getSize() / 2);
  61. groundBox.SetAsBox(sz.x, sz.y);
  62. groundBody->CreateFixture(&groundBox, 0.0f);
  63. }
  64. };
  65. class MainActor: public Actor
  66. {
  67. public:
  68. b2World* _world;
  69. spBox2DDraw _debugDraw;
  70. MainActor(): _world(0)
  71. {
  72. setSize(getStage()->getSize());
  73. spButton btn = new Button;
  74. btn->setX(getWidth() - btn->getWidth() - 3);
  75. btn->setY(3);
  76. btn->attachTo(this);
  77. btn->addEventListener(TouchEvent::CLICK, CLOSURE(this, &MainActor::showHideDebug));
  78. addEventListener(TouchEvent::CLICK, CLOSURE(this, &MainActor::click));
  79. _world = new b2World(b2Vec2(0, 10));
  80. spStatic ground = new Static(_world, RectF(getWidth() / 2, getHeight() - 10, getWidth() - 100, 30));
  81. addChild(ground);
  82. spCircle circle = new Circle(_world, getSize() / 2, 1);
  83. addChild(circle);
  84. }
  85. void doUpdate(const UpdateState& us)
  86. {
  87. //in real project you should make steps with fixed dt, check box2d documentation
  88. _world->Step(us.dt / 1000.0f, 6, 2);
  89. //update each body position on display
  90. b2Body* body = _world->GetBodyList();
  91. while (body)
  92. {
  93. Actor* actor = (Actor*)body->GetUserData();
  94. b2Body* next = body->GetNext();
  95. if (actor)
  96. {
  97. const b2Vec2& pos = body->GetPosition();
  98. actor->setPosition(convert(pos));
  99. actor->setRotation(body->GetAngle());
  100. //remove fallen bodies
  101. if (actor->getY() > getHeight() + 50)
  102. {
  103. body->SetUserData(0);
  104. _world->DestroyBody(body);
  105. actor->detach();
  106. }
  107. }
  108. body = next;
  109. }
  110. }
  111. void showHideDebug(Event* event)
  112. {
  113. TouchEvent* te = safeCast<TouchEvent*>(event);
  114. te->stopsImmediatePropagation = true;
  115. if (_debugDraw)
  116. {
  117. _debugDraw->detach();
  118. _debugDraw = 0;
  119. return;
  120. }
  121. _debugDraw = new Box2DDraw;
  122. _debugDraw->SetFlags(b2Draw::e_shapeBit | b2Draw::e_jointBit | b2Draw::e_pairBit | b2Draw::e_centerOfMassBit);
  123. _debugDraw->attachTo(this);
  124. _debugDraw->setWorld(SCALE, _world);
  125. _debugDraw->setPriority(1);
  126. }
  127. void click(Event* event)
  128. {
  129. TouchEvent* te = safeCast<TouchEvent*>(event);
  130. if (event->target.get() == this)
  131. {
  132. spCircle circle = new Circle(_world, te->localPosition);
  133. circle->attachTo(this);
  134. }
  135. if (event->target->getUserData())
  136. {
  137. //shot to circle
  138. spActor actor = safeSpCast<Actor>(event->target);
  139. b2Body* body = (b2Body*)actor->getUserData();
  140. Vector2 dir = actor->getPosition() - te->localPosition;
  141. dir = dir / dir.length() * body->GetMass() * 200;
  142. body->ApplyForceToCenter(b2Vec2(dir.x, dir.y), true);
  143. spSprite sprite = new Sprite();
  144. sprite->setResAnim(gameResources.getResAnim("shot"));
  145. Vector2 local = actor->parent2local(te->localPosition);
  146. sprite->setPosition(local);
  147. sprite->setAnchor(Vector2(0.5f, 0.5f));
  148. sprite->attachTo(actor);
  149. }
  150. }
  151. };
  152. void example_preinit()
  153. {
  154. }
  155. void example_init()
  156. {
  157. //load xml file with resources definition
  158. gameResources.loadXML("res.xml");
  159. //lets create our client code simple actor
  160. //prefix 'sp' here means it is intrusive Smart Pointer
  161. //it would be deleted automatically when you lost ref to it
  162. spMainActor actor = new MainActor;
  163. //and add it to Stage as child
  164. getStage()->addChild(actor);
  165. }
  166. void example_destroy()
  167. {
  168. gameResources.free();
  169. }
  170. void example_update()
  171. {
  172. }