| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- #include "oxygine-framework.h"
- #include "Box2D/Box2D.h"
- #include "Box2DDebugDraw.h"
- using namespace oxygine;
- //it is our resources
- //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
- Resources gameResources;
- //DECLARE_SMART is helper, it does forward declaration and declares intrusive_ptr typedef for your class
- DECLARE_SMART(MainActor, spMainActor);
- const float SCALE = 100.0f;
- b2Vec2 convert(const Vector2& pos)
- {
- return b2Vec2(pos.x / SCALE, pos.y / SCALE);
- }
- Vector2 convert(const b2Vec2& pos)
- {
- return Vector2(pos.x * SCALE, pos.y * SCALE);
- }
- DECLARE_SMART(Circle, spCircle);
- class Circle : public Sprite
- {
- public:
- Circle(b2World* world, const Vector2& pos, float scale = 1)
- {
- setResAnim(gameResources.getResAnim("circle"));
- setAnchor(Vector2(0.5f, 0.5f));
- setTouchChildrenEnabled(false);
- b2BodyDef bodyDef;
- bodyDef.type = b2_dynamicBody;
- bodyDef.position = convert(pos);
- b2Body* body = world->CreateBody(&bodyDef);
- setUserData(body);
- setScale(scale);
- b2CircleShape shape;
- shape.m_radius = getWidth() / SCALE / 2 * scale;
- b2FixtureDef fixtureDef;
- fixtureDef.shape = &shape;
- fixtureDef.density = 1.0f;
- fixtureDef.friction = 0.3f;
- body->CreateFixture(&fixtureDef);
- body->SetUserData(this);
- }
- };
- DECLARE_SMART(Static, spStatic);
- class Static : public Box9Sprite
- {
- public:
- Static(b2World* world, const RectF& rc)
- {
- //setHorizontalMode(Box9Sprite::TILING_FULL);
- //setVerticalMode(Box9Sprite::TILING_FULL);
- setResAnim(gameResources.getResAnim("pen"));
- setSize(rc.getSize());
- setPosition(rc.getLeftTop());
- setAnchor(Vector2(0.5f, 0.5f));
- b2BodyDef groundBodyDef;
- groundBodyDef.position = convert(getPosition());
- b2Body* groundBody = world->CreateBody(&groundBodyDef);
- b2PolygonShape groundBox;
- b2Vec2 sz = convert(getSize() / 2);
- groundBox.SetAsBox(sz.x, sz.y);
- groundBody->CreateFixture(&groundBox, 0.0f);
- }
- };
- class MainActor: public Actor
- {
- public:
- b2World* _world;
- spBox2DDraw _debugDraw;
- MainActor(): _world(0)
- {
- setSize(getStage()->getSize());
- spButton btn = new Button;
- btn->setX(getWidth() - btn->getWidth() - 3);
- btn->setY(3);
- btn->attachTo(this);
- btn->addEventListener(TouchEvent::CLICK, CLOSURE(this, &MainActor::showHideDebug));
- addEventListener(TouchEvent::CLICK, CLOSURE(this, &MainActor::click));
- _world = new b2World(b2Vec2(0, 10));
- spStatic ground = new Static(_world, RectF(getWidth() / 2, getHeight() - 10, getWidth() - 100, 30));
- addChild(ground);
- spCircle circle = new Circle(_world, getSize() / 2, 1);
- addChild(circle);
- }
- void doUpdate(const UpdateState& us)
- {
- //in real project you should make steps with fixed dt, check box2d documentation
- _world->Step(us.dt / 1000.0f, 6, 2);
- //update each body position on display
- b2Body* body = _world->GetBodyList();
- while (body)
- {
- Actor* actor = (Actor*)body->GetUserData();
- b2Body* next = body->GetNext();
- if (actor)
- {
- const b2Vec2& pos = body->GetPosition();
- actor->setPosition(convert(pos));
- actor->setRotation(body->GetAngle());
- //remove fallen bodies
- if (actor->getY() > getHeight() + 50)
- {
- body->SetUserData(0);
- _world->DestroyBody(body);
- actor->detach();
- }
- }
- body = next;
- }
- }
- void showHideDebug(Event* event)
- {
- TouchEvent* te = safeCast<TouchEvent*>(event);
- te->stopsImmediatePropagation = true;
- if (_debugDraw)
- {
- _debugDraw->detach();
- _debugDraw = 0;
- return;
- }
- _debugDraw = new Box2DDraw;
- _debugDraw->SetFlags(b2Draw::e_shapeBit | b2Draw::e_jointBit | b2Draw::e_pairBit | b2Draw::e_centerOfMassBit);
- _debugDraw->attachTo(this);
- _debugDraw->setWorld(SCALE, _world);
- _debugDraw->setPriority(1);
- }
- void click(Event* event)
- {
- TouchEvent* te = safeCast<TouchEvent*>(event);
- if (event->target.get() == this)
- {
- spCircle circle = new Circle(_world, te->localPosition);
- circle->attachTo(this);
- }
- if (event->target->getUserData())
- {
- //shot to circle
- spActor actor = safeSpCast<Actor>(event->target);
- b2Body* body = (b2Body*)actor->getUserData();
- Vector2 dir = actor->getPosition() - te->localPosition;
- dir = dir / dir.length() * body->GetMass() * 200;
- body->ApplyForceToCenter(b2Vec2(dir.x, dir.y), true);
- spSprite sprite = new Sprite();
- sprite->setResAnim(gameResources.getResAnim("shot"));
- Vector2 local = actor->parent2local(te->localPosition);
- sprite->setPosition(local);
- sprite->setAnchor(Vector2(0.5f, 0.5f));
- sprite->attachTo(actor);
- }
- }
- };
- void example_preinit()
- {
- }
- void example_init()
- {
- //load xml file with resources definition
- gameResources.loadXML("res.xml");
- //lets create our client code simple actor
- //prefix 'sp' here means it is intrusive Smart Pointer
- //it would be deleted automatically when you lost ref to it
- spMainActor actor = new MainActor;
- //and add it to Stage as child
- getStage()->addChild(actor);
- }
- void example_destroy()
- {
- gameResources.free();
- }
- void example_update()
- {
- }
|