example.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. class MainActor: public Actor
  20. {
  21. public:
  22. b2World *_world;
  23. spBox2DDraw _debugDraw;
  24. MainActor():_world(0)
  25. {
  26. setSize(getRoot()->getSize());
  27. spButton btn = new Button;
  28. btn->setResAnim(gameResources.getResAnim("button"));
  29. btn->setX(getWidth() - btn->getWidth());
  30. btn->attachTo(this);
  31. btn->addEventListener(TouchEvent::CLICK, CLOSURE(this, &MainActor::showHideDebug));
  32. addEventListener(TouchEvent::CLICK, CLOSURE(this, &MainActor::displayClicked));
  33. _world = new b2World(b2Vec2(0, 10), false);
  34. b2BodyDef groundBodyDef;
  35. groundBodyDef.position = convert(Vector2(getWidth()/2, getHeight() - 10));
  36. b2Body* groundBody = _world->CreateBody(&groundBodyDef);
  37. b2PolygonShape groundBox;
  38. groundBox.SetAsBox((getWidth() - 100)/2/SCALE, 10/SCALE);
  39. groundBody->CreateFixture(&groundBox, 0.0f);
  40. }
  41. void doUpdate(const UpdateState &us)
  42. {
  43. //in real project you should make steps with fixed dt, check box2d documentation
  44. _world->Step(us.dt / 1000.0f, 6, 2);
  45. //update each body position on display
  46. b2Body *body = _world->GetBodyList();
  47. while(body)
  48. {
  49. Actor *actor = (Actor *)body->GetUserData();
  50. b2Body *next = body->GetNext();
  51. if (actor)
  52. {
  53. const b2Vec2& pos = body->GetPosition();
  54. actor->setPosition(convert(pos));
  55. actor->setRotation(body->GetAngle());
  56. //remove fallen bodies
  57. if (actor->getY() > getHeight() + 50)
  58. {
  59. body->SetUserData(0);
  60. _world->DestroyBody(body);
  61. actor->detach();
  62. }
  63. }
  64. body = next;
  65. }
  66. }
  67. void showHideDebug(Event *event)
  68. {
  69. TouchEvent *te = safeCast<TouchEvent*>(event);
  70. te->stopsImmediatePropagation = true;
  71. if (_debugDraw)
  72. {
  73. _debugDraw->detach();
  74. _debugDraw = 0;
  75. return;
  76. }
  77. _debugDraw = new Box2DDraw;
  78. _debugDraw->SetFlags(b2Draw::e_shapeBit | b2Draw::e_jointBit | b2Draw::e_pairBit | b2Draw::e_centerOfMassBit);
  79. _debugDraw->attachTo(this);
  80. _debugDraw->setWorld(SCALE, _world);
  81. _debugDraw->setPriority(1);
  82. }
  83. void circleClicked(Event *event)
  84. {
  85. TouchEvent *te = safeCast<TouchEvent*>(event);
  86. te->stopImmediatePropagation();
  87. spActor actor = safeSpCast<Actor>(event->currentTarget);
  88. b2Body *body = (b2Body *)actor->getUserData();
  89. Vector2 dir = actor->getPosition() - actor->local2global(te->localPosition);
  90. dir = dir / dir.length() * body->GetMass() * 200;
  91. body->ApplyForceToCenter(b2Vec2(dir.x, dir.y));
  92. //show click pos
  93. spSprite sprite = new Sprite();
  94. sprite->setResAnim(gameResources.getResAnim("circle"));
  95. sprite->setColor(Color(0xff00ffff));
  96. sprite->setScale(0.2f);
  97. sprite->setPosition(te->localPosition);
  98. sprite->setAnchor(Vector2(0.5f, 0.5f));
  99. sprite->attachTo(actor);
  100. }
  101. void displayClicked(Event *event)
  102. {
  103. TouchEvent *te = safeCast<TouchEvent*>(event);
  104. spSprite sprite = new Sprite();
  105. sprite->setResAnim(gameResources.getResAnim("circle"));
  106. sprite->attachTo(this);
  107. sprite->setAnchor(Vector2(0.5f, 0.5f));
  108. sprite->setPosition(te->localPosition);
  109. sprite->setInputChildrenEnabled(false);
  110. sprite->addEventListener(TouchEvent::CLICK, CLOSURE(this, &MainActor::circleClicked));
  111. b2BodyDef bodyDef;
  112. bodyDef.type = b2_dynamicBody;
  113. bodyDef.position = convert(te->localPosition);
  114. b2Body *body = _world->CreateBody(&bodyDef);
  115. sprite->setUserData(body);
  116. float scale = (rand()%5)/10.0f + 0.5f;
  117. sprite->setScale(scale);
  118. b2CircleShape shape;
  119. shape.m_radius = sprite->getWidth() / SCALE / 2 * scale;
  120. b2FixtureDef fixtureDef;
  121. fixtureDef.shape = &shape;
  122. fixtureDef.density = 1.0f;
  123. fixtureDef.friction = 0.3f;
  124. body->CreateFixture(&fixtureDef);
  125. body->SetUserData(sprite.get());
  126. }
  127. };
  128. void example_preinit()
  129. {
  130. }
  131. void example_init()
  132. {
  133. //load xml file with resources definition
  134. gameResources.loadXML("res.xml");
  135. //lets create our client code simple actor
  136. //prefix 'sp' here means it is intrusive Smart Pointer
  137. //it would be deleted automatically when you lost ref to it
  138. spMainActor actor = new MainActor;
  139. //and add it to RootActor as child
  140. getRoot()->addChild(actor);
  141. }
  142. void example_destroy()
  143. {
  144. gameResources.free();
  145. }
  146. void example_update()
  147. {
  148. }