axmol/samples/Cpp/TestCpp/Classes/PhysicsTest/PhysicsTest.cpp

396 lines
11 KiB
C++
Raw Normal View History

#include "PhysicsTest.h"
#include "../testResource.h"
USING_NS_CC;
2013-09-29 15:09:53 +08:00
namespace
{
static std::function<Layer*()> createFunctions[] = {
CL(PhysicsDemoLogoSmash),
2013-10-09 17:53:12 +08:00
CL(PhysicsDemoPyramidStack),
CL(PhysicsDemoClickAdd),
};
static int sceneIdx=-1;
#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0]))
2013-09-29 15:09:53 +08:00
static Layer* next()
{
sceneIdx++;
sceneIdx = sceneIdx % MAX_LAYER;
auto layer = (createFunctions[sceneIdx])();
layer->init();
layer->autorelease();
return layer;
}
static Layer* back()
{
sceneIdx--;
int total = MAX_LAYER;
if( sceneIdx < 0 )
sceneIdx += total;
auto layer = (createFunctions[sceneIdx])();
layer->init();
layer->autorelease();
return layer;
}
static Layer* restart()
{
auto layer = (createFunctions[sceneIdx])();
layer->init();
layer->autorelease();
return layer;
}
}
2013-10-09 17:53:12 +08:00
bool PhysicsTestScene::_debugDraw = false;
2013-09-29 15:09:53 +08:00
bool PhysicsTestScene::initTest()
{
#ifdef CC_USE_PHYSICS
2013-10-09 17:53:12 +08:00
if(TestScene::initWithPhysics())
{
this->getPhysicsWorld()->setDebugDraw(_debugDraw);
return true;
}
2013-09-29 15:09:53 +08:00
#else
return TestScene::init();
#endif
return false;
}
void PhysicsTestScene::runThisTest()
{
#ifdef CC_USE_PHYSICS
sceneIdx = -1;
addChild(next());
Director::getInstance()->replaceScene(this);
#else
#endif
}
2013-10-09 17:53:12 +08:00
void PhysicsTestScene::toggleDebug()
{
_debugDraw = !_debugDraw;
getPhysicsWorld()->setDebugDraw(_debugDraw);
}
2013-09-29 15:09:53 +08:00
PhysicsDemo::PhysicsDemo()
: _scene(nullptr)
{
}
PhysicsDemo::~PhysicsDemo()
{
2013-09-29 15:09:53 +08:00
}
std::string PhysicsDemo::title()
{
return "PhysicsTest";
}
std::string PhysicsDemo::subtitle()
{
return "";
}
void PhysicsDemo::restartCallback(Object* sender)
{
auto s = new PhysicsTestScene();
2013-10-09 17:53:12 +08:00
s->initTest();
2013-09-29 15:09:53 +08:00
s->addChild( restart() );
Director::getInstance()->replaceScene(s);
s->release();
}
void PhysicsDemo::nextCallback(Object* sender)
{
auto s = new PhysicsTestScene();
2013-10-09 17:53:12 +08:00
s->initTest();
2013-09-29 15:09:53 +08:00
s->addChild( next() );
Director::getInstance()->replaceScene(s);
s->release();
}
void PhysicsDemo::backCallback(Object* sender)
{
auto s = new PhysicsTestScene();
2013-10-09 17:53:12 +08:00
s->initTest();
2013-09-29 15:09:53 +08:00
s->addChild( back() );
Director::getInstance()->replaceScene(s);
s->release();
}
void PhysicsDemo::onEnter()
{
BaseTest::onEnter();
2013-10-09 17:53:12 +08:00
_scene = dynamic_cast<PhysicsTestScene*>(this->getParent());
_spriteTexture = SpriteBatchNode::create("Images/grossini_dance_atlas.png", 100)->getTexture();
2013-09-29 15:09:53 +08:00
#ifdef CC_USE_PHYSICS
// menu for debug layer
MenuItemFont::setFontSize(18);
2013-09-29 15:09:53 +08:00
auto item = MenuItemFont::create("Toggle debug", CC_CALLBACK_1(PhysicsDemo::toggleDebugCallback, this));
auto menu = Menu::create(item, NULL);
this->addChild(menu);
2013-09-29 15:09:53 +08:00
menu->setPosition(Point(VisibleRect::right().x-50, VisibleRect::top().y-10));
#else
#endif
}
2013-10-09 17:53:12 +08:00
void PhysicsDemo::addGrossiniAtPosition(Point p, float scale/* = 1.0*/)
{
#ifdef CC_USE_PHYSICS
CCLOG("Add sprite %0.2f x %02.f",p.x,p.y);
int posx, posy;
posx = CCRANDOM_0_1() * 200.0f;
posy = CCRANDOM_0_1() * 200.0f;
posx = (posx % 4) * 85;
posy = (posy % 3) * 121;
auto sp = Sprite::createWithTexture(_spriteTexture, Rect(posx, posy, 85, 121));
sp->setScale(scale);
sp->setPhysicsBody(PhysicsBody::createBox(Size(48.0f * scale, 108.0f * scale)));
this->addChild(sp);
sp->setPosition(p);
#endif
}
2013-09-29 15:09:53 +08:00
void PhysicsDemo::toggleDebugCallback(Object* sender)
{
#ifdef CC_USE_PHYSICS
if (_scene != nullptr)
{
2013-10-09 17:53:12 +08:00
_scene->toggleDebug();
2013-09-29 15:09:53 +08:00
}
#endif
}
void PhysicsDemoClickAdd::onEnter()
{
PhysicsDemo::onEnter();
#ifdef CC_USE_PHYSICS
setTouchEnabled(true);
setAccelerometerEnabled(true);
auto node = Node::create();
2013-10-09 17:53:12 +08:00
node->setPhysicsBody(PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size));
node->setPosition(VisibleRect::center());
this->addChild(node);
2013-10-09 17:53:12 +08:00
addGrossiniAtPosition(VisibleRect::center());
#else
auto label = LabelTTF::create("Should define CC_USE_BOX2D or CC_USE_CHIPMUNK\n to run this test case",
"Arial",
18);
auto size = Director::getInstance()->getWinSize();
label->setPosition(Point(size.width/2, size.height/2));
addChild(label);
#endif
}
2013-09-29 15:09:53 +08:00
std::string PhysicsDemoClickAdd::subtitle()
{
2013-09-29 15:09:53 +08:00
return "multi touch to add grossini";
}
2013-09-29 15:09:53 +08:00
void PhysicsDemoClickAdd::onTouchesEnded(const std::vector<Touch*>& touches, Event* event)
{
//Add a new body/atlas sprite at the touched location
for( auto &touch: touches)
{
auto location = touch->getLocation();
2013-10-09 17:53:12 +08:00
addGrossiniAtPosition( location );
}
}
2013-09-29 15:09:53 +08:00
void PhysicsDemoClickAdd::onAcceleration(Acceleration* acc, Event* event)
{
#ifdef CC_USE_PHYSICS
static float prevX=0, prevY=0;
#define kFilterFactor 0.05f
float accelX = (float) acc->x * kFilterFactor + (1- kFilterFactor)*prevX;
float accelY = (float) acc->y * kFilterFactor + (1- kFilterFactor)*prevY;
prevX = accelX;
prevY = accelY;
auto v = Point( accelX, accelY);
v = v * 200;
if(_scene != nullptr)
{
_scene->getPhysicsWorld()->setGravity(v);
}
#endif
}
namespace
{
static const int logo_width = 188;
static const int logo_height = 35;
static const int logo_row_length = 24;
static const char logo_image[] =
{
15,-16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,-64,15,63,-32,-2,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,31,-64,15,127,-125,-1,-128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,127,-64,15,127,15,-1,-64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,-1,-64,15,-2,
31,-1,-64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,-1,-64,0,-4,63,-1,-32,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,1,-1,-64,15,-8,127,-1,-32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,-1,-64,0,-8,-15,-1,-32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,-31,-1,-64,15,-8,-32,
-1,-32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,-15,-1,-64,9,-15,-32,-1,-32,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,31,-15,-1,-64,0,-15,-32,-1,-32,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,63,-7,-1,-64,9,-29,-32,127,-61,-16,63,15,-61,-1,-8,31,-16,15,-8,126,7,-31,
-8,31,-65,-7,-1,-64,9,-29,-32,0,7,-8,127,-97,-25,-1,-2,63,-8,31,-4,-1,15,-13,
-4,63,-1,-3,-1,-64,9,-29,-32,0,7,-8,127,-97,-25,-1,-2,63,-8,31,-4,-1,15,-13,
-2,63,-1,-3,-1,-64,9,-29,-32,0,7,-8,127,-97,-25,-1,-1,63,-4,63,-4,-1,15,-13,
-2,63,-33,-1,-1,-32,9,-25,-32,0,7,-8,127,-97,-25,-1,-1,63,-4,63,-4,-1,15,-13,
-1,63,-33,-1,-1,-16,9,-25,-32,0,7,-8,127,-97,-25,-1,-1,63,-4,63,-4,-1,15,-13,
-1,63,-49,-1,-1,-8,9,-57,-32,0,7,-8,127,-97,-25,-8,-1,63,-2,127,-4,-1,15,-13,
-1,-65,-49,-1,-1,-4,9,-57,-32,0,7,-8,127,-97,-25,-8,-1,63,-2,127,-4,-1,15,-13,
-1,-65,-57,-1,-1,-2,9,-57,-32,0,7,-8,127,-97,-25,-8,-1,63,-2,127,-4,-1,15,-13,
-1,-1,-57,-1,-1,-1,9,-57,-32,0,7,-1,-1,-97,-25,-8,-1,63,-1,-1,-4,-1,15,-13,-1,
-1,-61,-1,-1,-1,-119,-57,-32,0,7,-1,-1,-97,-25,-8,-1,63,-1,-1,-4,-1,15,-13,-1,
-1,-61,-1,-1,-1,-55,-49,-32,0,7,-1,-1,-97,-25,-8,-1,63,-1,-1,-4,-1,15,-13,-1,
-1,-63,-1,-1,-1,-23,-49,-32,127,-57,-1,-1,-97,-25,-1,-1,63,-1,-1,-4,-1,15,-13,
-1,-1,-63,-1,-1,-1,-16,-49,-32,-1,-25,-1,-1,-97,-25,-1,-1,63,-33,-5,-4,-1,15,
-13,-1,-1,-64,-1,-9,-1,-7,-49,-32,-1,-25,-8,127,-97,-25,-1,-1,63,-33,-5,-4,-1,
15,-13,-1,-1,-64,-1,-13,-1,-32,-49,-32,-1,-25,-8,127,-97,-25,-1,-2,63,-49,-13,
-4,-1,15,-13,-1,-1,-64,127,-7,-1,-119,-17,-15,-1,-25,-8,127,-97,-25,-1,-2,63,
-49,-13,-4,-1,15,-13,-3,-1,-64,127,-8,-2,15,-17,-1,-1,-25,-8,127,-97,-25,-1,
-8,63,-49,-13,-4,-1,15,-13,-3,-1,-64,63,-4,120,0,-17,-1,-1,-25,-8,127,-97,-25,
-8,0,63,-57,-29,-4,-1,15,-13,-4,-1,-64,63,-4,0,15,-17,-1,-1,-25,-8,127,-97,
-25,-8,0,63,-57,-29,-4,-1,-1,-13,-4,-1,-64,31,-2,0,0,103,-1,-1,-57,-8,127,-97,
-25,-8,0,63,-57,-29,-4,-1,-1,-13,-4,127,-64,31,-2,0,15,103,-1,-1,-57,-8,127,
-97,-25,-8,0,63,-61,-61,-4,127,-1,-29,-4,127,-64,15,-8,0,0,55,-1,-1,-121,-8,
127,-97,-25,-8,0,63,-61,-61,-4,127,-1,-29,-4,63,-64,15,-32,0,0,23,-1,-2,3,-16,
63,15,-61,-16,0,31,-127,-127,-8,31,-1,-127,-8,31,-128,7,-128,0,0};
static inline int get_pixel(int x, int y)
{
return (logo_image[(x>>3) + y*logo_row_length]>>(~x&0x7)) & 1;
}
#define RAND_MAX 0x7fffffff
static inline float frand(void)
{
return rand()/RAND_MAX;
}
}
Node* PhysicsDemoLogoSmash::makeBall(float x, float y)
{
2013-10-09 17:53:12 +08:00
auto ball = Sprite::create("Images/ball.png");
ball->setScale(0.1);
2013-10-09 17:53:12 +08:00
auto body = PhysicsBody::createCircle(0.95, PhysicsMaterial(1, 0, 0));
body->setMass(1.0);
body->setAngularDamping(PHYSICS_INFINITY);
//body->setDynamic(false);
ball->setPhysicsBody(body);
ball->setPosition(Point(x, y));
return ball;
}
void PhysicsDemoLogoSmash::onEnter()
{
PhysicsDemo::onEnter();
_scene->getPhysicsWorld()->setGravity(Point(0, 0));
//addChild(makeBall(200, 200));
for (int y = 0; y < logo_height; ++y)
{
for (int x = 0; x < logo_width; ++x)
{
if (get_pixel(x, y))
{
float x_jitter = 0.05*frand();
float y_jitter = 0.05*frand();
addChild(makeBall(2*(x - logo_width/2 + x_jitter) + VisibleRect::getVisibleRect().size.width/2,
2*(logo_height-y + y_jitter) + VisibleRect::getVisibleRect().size.height/2 - logo_height/2));
}
}
}
2013-10-09 17:53:12 +08:00
auto bullet = Sprite::create("Images/ball.png");
bullet->setScale(0.5);
2013-10-09 17:53:12 +08:00
auto body = PhysicsBody::createCircle(8, PhysicsMaterial(PHYSICS_INFINITY, 0, 0));
body->setVelocity(Point(400, 0));
bullet->setPhysicsBody(body);
bullet->setPosition(Point(-1000, VisibleRect::getVisibleRect().size.height/2));
addChild(bullet);
}
std::string PhysicsDemoLogoSmash::title()
{
return "Logo Smash";
2013-10-09 17:53:12 +08:00
}
void PhysicsDemoPyramidStack::onEnter()
{
PhysicsDemo::onEnter();
auto node = Node::create();
node->setPhysicsBody(PhysicsBody::createEdgeSegment(VisibleRect::leftBottom() + Point(0, 50), VisibleRect::rightBottom() + Point(0, 50)));
this->addChild(node);
auto ball = Sprite::create("Images/ball.png");
ball->setScale(1);
ball->setPhysicsBody(PhysicsBody::createCircle(10));
ball->setPosition(VisibleRect::bottom() + Point(0, 60));
this->addChild(ball);
for(int i=0; i<14; i++){
for(int j=0; j<=i; j++){
addGrossiniAtPosition(VisibleRect::bottom() + Point((i/2 - j) * 11, (14 - i) * 23 + 100), 0.2);
}
}
}
std::string PhysicsDemoPyramidStack::title()
{
return "Pyramid Stack";
}
void PhysicsDemoPlink::onEnter()
{
PhysicsDemo::onEnter();
}
std::string PhysicsDemoPlink::title()
{
return "Plink";
2013-09-29 15:09:53 +08:00
}