Cocos2d-X Box2D的使用实例
1、PhysicsSprite类
(1)PhysicsSprite.h
#include
#include "Box2D/Box2D.h"
#include "cocos2d.h"
USING_NS_CC;
class PhysicsSprite:publicCCSprite
{
public:
PhysicsSprite();
void setPhysicsBody(b2Body *boddy);
int hp;//血量
private:
b2Body * m_pBody;
};
(2)PhysicsSprite.cpp
#include "PhysicsSprite.h"
PhysicsSprite::PhysicsSprite():m_pBody(NULL)
{
//0与1之间的随机数
int idx=(CCRANDOM_0_1()>0.5?0:1);
int idy=(CCRANDOM_0_1()>0.5?0:1);
this->initWithFile("blocks.png",CCRectMake(32*idx, 32*idy, 32, 32));
hp=5;
}
void PhysicsSprite::setPhysicsBody(b2Body *boddy)
{
m_pBody=boddy;
}
2、MyContactListener
(1)MyContactListener.h
#include
#include "cocos2d.h"
#include "Box2D.h"
USING_NS_CC;
class MyContactListener:publicb2ContactListener
{
public:
CCLayer *_layer;
b2World *_world;
MyContactListener();
~MyContactListener();
MyContactListener(b2World *w,CCLayer *c);
virtual void BeginContact(b2Contact* contact) ;
virtual void EndContact(b2Contact* contact) ;
virtual void PreSolve(b2Contact* contact,const b2Manifold* oldManifold);
virtual void PostSolve(b2Contact* contact,const b2ContactImpulse* impulse);
};
(2)MyContactListener.cpp
#include "MyContactListener.h"
#include "PhysicsSprite.h"
MyContactListener::MyContactListener()
{
}
MyContactListener::~MyContactListener()
{
}
MyContactListener::MyContactListener(b2World *w,CCLayer *c)
{
_world=w;
_layer=c;
}
//两个物体重叠时
void MyContactListener::BeginContact(b2Contact* contact)
{
CCLog("BeginContact!");
}
//两个物体分离时
void MyContactListener::EndContact(b2Contact* contact)
{
CCLog("EndContact!");
}
void MyContactListener::PreSolve(b2Contact* contact,const b2Manifold* oldManifold)
{
CCLog("PreSolve!");
}
void MyContactListener::PostSolve(b2Contact* contact,const b2ContactImpulse* impulse)
{
CCLog("PostSolve!");
float force=impulse->normalImpulses[0];
if(force>2)
{
PhysicsSprite *spriteA=(PhysicsSprite *)contact->GetFixtureA()->GetBody()->GetUserData();
PhysicsSprite *spriteB=(PhysicsSprite *)contact->GetFixtureB()->GetBody()->GetUserData();
if(spriteA && spriteB)
{
spriteA->hp--;
spriteB->hp--;
}
}
}
3、b2World
(1)b2World.h
#include
#include "Box2D.h"
#include "cocos2d.h"
USING_NS_CC;
class World:public CCLayer
{
public:
virtual bool init();
static CCScene *scene();
CREATE_FUNC(World);
void update(float dt);
void initPhysical();
void addNewSpriteAtPosition(CCPoint position);
virtual bool ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent);
virtual void ccTouchMoved(CCTouch *pTouch,CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent);
CCLabelTTF *label1;
CCLabelTTF *label2;
private:
b2World *world;
};
(2)b2World.cpp
#include "b2World.h"
#include "PhysicsSprite.h"
#include "MyContactListener.h"
CCScene *World::scene()
{
CCScene *scene=CCScene::create();
World *w=World::create();
scene->addChild(w);
return scene;
}
bool World::init()
{
if(!CCLayer::init())
{
return false;
}
//CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
label1=CCLabelTTF::create("0","Arial", 30);
label1->setPosition(ccp(240,160));
this->addChild(label1);
initPhysical();
MyContactListener *listener=newMyContactListener(world,this);
world->SetContactListener(listener);
this->setTouchEnabled(true);
this->setTouchMode(kCCTouchesOneByOne);
this->scheduleUpdate();
return true;
}
void World::update(float dt)
{
int velocityIteration=8;//8次速度
int positionIteration=1;//一次位置
world->Step(dt, velocityIteration, positionIteration);
b2Body *b=world->GetBodyList();
while(b)
{
b2Body *p=b;
b=b->GetNext();
if(p->GetUserData() !=NULL)
{
PhysicsSprite *myActor=(PhysicsSprite *)p->GetUserData();
if(myActor->hp<0)
{
myActor->removeFromParent();
world->DestroyBody(p);
}
myActor->setPosition(CCPointMake(p->GetPosition().x*32, p->GetPosition().y*32));
myActor->setRotation(-1*CC_RADIANS_TO_DEGREES(p->GetAngle()));
}
}
/*
for(b2Body *b=world->GetBodyList();b;b->GetNext() )
{
if(b->GetUserData() != NULL)
{
PhysicsSprite *myActor=(PhysicsSprite *)b->GetUserData();
if(myActor->hp<0)
{
myActor->removeFromParent();
world->DestroyBody(b);
}
myActor->setPosition(CCPointMake(b->GetPosition().x*32, b->GetPosition().y*32));
myActor->setRotation(-1*CC_RADIANS_TO_DEGREES(b->GetAngle()));
}
}
*/
}
//初始化
void World::initPhysical()
{
CCSize winSize=CCDirector::sharedDirector()->getWinSize();
b2Vec2 gravity;//设置重力(结构体)
gravity.Set(0.0f, -10.0f);
//创建世界
world=new b2World(gravity);
world->SetAllowSleeping(true);//设置睡眠
world->SetContinuousPhysics(true);//设置连续碰撞
//创建刚体(结构体)
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0.0f,0.0f);
b2Body *groundBody=world->CreateBody(&groundBodyDef);
//创建形状(结构体)
b2EdgeShape groundBox;
//bottom
groundBox.Set(b2Vec2(0,0), b2Vec2(winSize.width/32,0));
groundBody->CreateFixture(&groundBox,0);
//top
groundBox.Set(b2Vec2(0, winSize.height/32),b2Vec2(winSize.width/32,winSize.height/32));
groundBody->CreateFixture(&groundBox,0);
//left
groundBox.Set(b2Vec2(0,0), b2Vec2(0,winSize.height/32));
groundBody->CreateFixture(&groundBox,0);
//right
groundBox.Set(b2Vec2(winSize.width/32,0), b2Vec2(winSize.width/32,winSize.height/32));
groundBody->CreateFixture(&groundBox,0);//填充
}
void World::addNewSpriteAtPosition(CCPoint position)
{
PhysicsSprite *sprite=newPhysicsSprite();
sprite->setPosition(position);
this->addChild(sprite);
b2BodyDef bodyDef;//创建刚体
bodyDef.type=b2_dynamicBody;//设置类型
bodyDef.position.Set(position.x/32, position.y/32);
bodyDef.userData=sprite;//刚体与精灵链接
b2Body *body=world->CreateBody(&bodyDef);
b2PolygonShape dynamicBox;//多边形
dynamicBox.SetAsBox(0.5f,0.5f);//指定形状为长方形
b2FixtureDef fixtureDef;//关联
fixtureDef.shape=&dynamicBox;//形状
fixtureDef.density=10.0f;//密度
fixtureDef.friction=0.0f;//摩擦
fixtureDef.restitution=1.0f;//恢复
body->CreateFixture(&fixtureDef);//刚体创建夹具
sprite->setPhysicsBody(body);
}
bool World::ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent)
{
return true;
}
void World::ccTouchMoved(CCTouch *pTouch,CCEvent *pEvent)
{
}
void World::ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent)
{
this->addNewSpriteAtPosition(pTouch->getLocation());
}
注意:
1、b2BodyDef与b2FixtureDef的区别:
//b2BodyDef是用来存放刚体在世界中的数据,比如position(x,y) , angle 等等属性。
// b2FixtureDef则是用来存放刚体自身的数据,比如shape(polygonShape,等等),density,friction等等属性。
2、step方法要传递三个参数,dt,velocityIterations, positionIterations:
即world->Step(dt, velocityIteration, positionIteration):
dt,时步。通常建议设置为1/60,这样的话你的fps最好也设置到60。但是我发现更好的办法就是把timeStep设置为fps的倒数即可。如果你的fps是30,那么就设置为1/30。
(1)velocityIterations,速度迭代
(2) positionIterations,位置迭代: 这两个值通常建议设置为10,更低的迭代值会让你牺牲一些准确性,相反的为你的程序提升一部分性能。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
暂时没有评论,来抢沙发吧~