mirror of https://github.com/axmolengine/axmol.git
243 lines
7.3 KiB
C++
243 lines
7.3 KiB
C++
#include "Box2dTest.h"
|
|
#include "../testResource.h"
|
|
#include "extensions/cocos-ext.h"
|
|
#include "renderer/CCRenderer.h"
|
|
#include "renderer/CCCustomCommand.h"
|
|
|
|
USING_NS_CC;
|
|
USING_NS_CC_EXT;
|
|
|
|
#define PTM_RATIO 32
|
|
|
|
enum {
|
|
kTagParentNode = 1,
|
|
};
|
|
|
|
Box2DTests::Box2DTests()
|
|
{
|
|
ADD_TEST_CASE(Box2DTest);
|
|
}
|
|
|
|
bool Box2DTest::init()
|
|
{
|
|
if (!TestCase::init())
|
|
{
|
|
return false;
|
|
}
|
|
#if CC_ENABLE_BOX2D_INTEGRATION
|
|
auto dispatcher = Director::getInstance()->getEventDispatcher();
|
|
|
|
auto touchListener = EventListenerTouchAllAtOnce::create();
|
|
touchListener->onTouchesEnded = CC_CALLBACK_2(Box2DTest::onTouchesEnded, this);
|
|
dispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
|
|
|
|
// init physics
|
|
this->initPhysics();
|
|
// create reset button
|
|
this->createResetButton();
|
|
|
|
//Set up sprite
|
|
#if 1
|
|
// Use batch node. Faster
|
|
auto parent = SpriteBatchNode::create("Images/blocks.png", 100);
|
|
_spriteTexture = parent->getTexture();
|
|
#else
|
|
// doesn't use batch node. Slower
|
|
_spriteTexture = Director::getInstance()->getTextureCache()->addImage("Images/blocks.png");
|
|
auto parent = Node::create();
|
|
#endif
|
|
addChild(parent, 0, kTagParentNode);
|
|
|
|
|
|
addNewSpriteAtPosition(VisibleRect::center());
|
|
|
|
auto label = Label::createWithTTF("Tap screen", "fonts/Marker Felt.ttf", 32.0f);
|
|
addChild(label, 0);
|
|
label->setColor(Color3B(0, 0, 255));
|
|
label->setPosition(VisibleRect::center().x, VisibleRect::top().y - 50);
|
|
|
|
scheduleUpdate();
|
|
#else
|
|
auto label = Label::createWithTTF("Should define CC_ENABLE_BOX2D_INTEGRATION=1\n to run this test case",
|
|
"fonts/arial.ttf",
|
|
18);
|
|
auto size = Director::getInstance()->getWinSize();
|
|
label->setPosition(size.width / 2, size.height / 2);
|
|
|
|
addChild(label);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
#if CC_ENABLE_BOX2D_INTEGRATION
|
|
Box2DTest::Box2DTest()
|
|
: _spriteTexture(nullptr)
|
|
, world(nullptr)
|
|
{
|
|
|
|
}
|
|
|
|
Box2DTest::~Box2DTest()
|
|
{
|
|
CC_SAFE_DELETE(world);
|
|
}
|
|
|
|
void Box2DTest::initPhysics()
|
|
{
|
|
b2Vec2 gravity;
|
|
gravity.Set(0.0f, -10.0f);
|
|
world = new b2World(gravity);
|
|
|
|
// Do we want to let bodies sleep?
|
|
world->SetAllowSleeping(true);
|
|
|
|
world->SetContinuousPhysics(true);
|
|
|
|
// Define the ground body.
|
|
b2BodyDef groundBodyDef;
|
|
groundBodyDef.position.Set(0, 0); // bottom-left corner
|
|
|
|
// Call the body factory which allocates memory for the ground body
|
|
// from a pool and creates the ground box shape (also from a pool).
|
|
// The body is also added to the world.
|
|
b2Body* groundBody = world->CreateBody(&groundBodyDef);
|
|
|
|
// Define the ground box shape.
|
|
b2EdgeShape groundBox;
|
|
|
|
// bottom
|
|
groundBox.Set(b2Vec2(VisibleRect::leftBottom().x/PTM_RATIO,VisibleRect::leftBottom().y/PTM_RATIO), b2Vec2(VisibleRect::rightBottom().x/PTM_RATIO,VisibleRect::rightBottom().y/PTM_RATIO));
|
|
groundBody->CreateFixture(&groundBox,0);
|
|
|
|
// top
|
|
groundBox.Set(b2Vec2(VisibleRect::leftTop().x/PTM_RATIO,VisibleRect::leftTop().y/PTM_RATIO), b2Vec2(VisibleRect::rightTop().x/PTM_RATIO,VisibleRect::rightTop().y/PTM_RATIO));
|
|
groundBody->CreateFixture(&groundBox,0);
|
|
|
|
// left
|
|
groundBox.Set(b2Vec2(VisibleRect::leftTop().x/PTM_RATIO,VisibleRect::leftTop().y/PTM_RATIO), b2Vec2(VisibleRect::leftBottom().x/PTM_RATIO,VisibleRect::leftBottom().y/PTM_RATIO));
|
|
groundBody->CreateFixture(&groundBox,0);
|
|
|
|
// right
|
|
groundBox.Set(b2Vec2(VisibleRect::rightBottom().x/PTM_RATIO,VisibleRect::rightBottom().y/PTM_RATIO), b2Vec2(VisibleRect::rightTop().x/PTM_RATIO,VisibleRect::rightTop().y/PTM_RATIO));
|
|
groundBody->CreateFixture(&groundBox,0);
|
|
}
|
|
|
|
void Box2DTest::createResetButton()
|
|
{
|
|
auto reset = MenuItemImage::create("Images/r1.png", "Images/r2.png", [&](Ref *sender) {
|
|
getTestSuite()->restartCurrTest();
|
|
});
|
|
|
|
auto menu = Menu::create(reset, nullptr);
|
|
|
|
menu->setPosition(VisibleRect::bottom().x, VisibleRect::bottom().y + 30);
|
|
this->addChild(menu, -1);
|
|
|
|
}
|
|
|
|
void Box2DTest::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
|
|
{
|
|
//
|
|
// IMPORTANT:
|
|
// This is only for debug purposes
|
|
// It is recommend to disable it
|
|
//
|
|
Scene::draw(renderer, transform, flags);
|
|
|
|
GL::enableVertexAttribs( cocos2d::GL::VERTEX_ATTRIB_FLAG_POSITION );
|
|
Director* director = Director::getInstance();
|
|
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
|
|
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
|
|
|
_modelViewMV = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
|
|
|
_customCommand.init(_globalZOrder);
|
|
_customCommand.func = CC_CALLBACK_0(Box2DTest::onDraw, this);
|
|
renderer->addCommand(&_customCommand);
|
|
|
|
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
|
}
|
|
|
|
void Box2DTest::onDraw()
|
|
{
|
|
Director* director = Director::getInstance();
|
|
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
|
|
|
|
auto oldMV = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
|
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewMV);
|
|
world->DrawDebugData();
|
|
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, oldMV);
|
|
}
|
|
|
|
|
|
void Box2DTest::addNewSpriteAtPosition(Vec2 p)
|
|
{
|
|
CCLOG("Add sprite %0.2f x %02.f",p.x,p.y);
|
|
|
|
// Define the dynamic body.
|
|
//Set up a 1m squared box in the physics world
|
|
b2BodyDef bodyDef;
|
|
bodyDef.type = b2_dynamicBody;
|
|
bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
|
|
|
|
b2Body *body = world->CreateBody(&bodyDef);
|
|
|
|
// Define another box shape for our dynamic body.
|
|
b2PolygonShape dynamicBox;
|
|
dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box
|
|
|
|
// Define the dynamic body fixture.
|
|
b2FixtureDef fixtureDef;
|
|
fixtureDef.shape = &dynamicBox;
|
|
fixtureDef.density = 1.0f;
|
|
fixtureDef.friction = 0.3f;
|
|
body->CreateFixture(&fixtureDef);
|
|
|
|
#if CC_ENABLE_BOX2D_INTEGRATION
|
|
auto parent = this->getChildByTag(kTagParentNode);
|
|
|
|
//We have a 64x64 sprite sheet with 4 different 32x32 images. The following code is
|
|
//just randomly picking one of the images
|
|
int idx = (CCRANDOM_0_1() > .5 ? 0:1);
|
|
int idy = (CCRANDOM_0_1() > .5 ? 0:1);
|
|
auto sprite = PhysicsSprite::createWithTexture(_spriteTexture,Rect(32 * idx,32 * idy,32,32));
|
|
parent->addChild(sprite);
|
|
sprite->setB2Body(body);
|
|
sprite->setPTMRatio(PTM_RATIO);
|
|
sprite->setPosition(cocos2d::Vec2(p.x, p.y));
|
|
#endif
|
|
}
|
|
|
|
void Box2DTest::update(float dt)
|
|
{
|
|
//It is recommended that a fixed time step is used with Box2D for stability
|
|
//of the simulation, however, we are using a variable time step here.
|
|
//You need to make an informed choice, the following URL is useful
|
|
//http://gafferongames.com/game-physics/fix-your-timestep/
|
|
|
|
int velocityIterations = 8;
|
|
int positionIterations = 1;
|
|
|
|
// Instruct the world to perform a single step of simulation. It is
|
|
// generally best to keep the time step and iterations fixed.
|
|
world->Step(dt, velocityIterations, positionIterations);
|
|
}
|
|
|
|
void Box2DTest::onTouchesEnded(const std::vector<Touch*>& touches, Event* event)
|
|
{
|
|
//Add a new body/atlas sprite at the touched location
|
|
|
|
for (auto& touch : touches)
|
|
{
|
|
if(!touch)
|
|
break;
|
|
|
|
auto location = touch->getLocation();
|
|
|
|
addNewSpriteAtPosition( location );
|
|
}
|
|
}
|
|
|
|
#endif
|