根据上一节的教程,我用C++更改了教程,我用的cocos2d-2.0-rc2-x-2.0.1版本,略微有些不同,都是小细节,直接贴上代码
HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include <Box2D/Box2D.h>
#include "cocos2d.h"
#include <list>
using std::list;

class MyContact


{
public:
b2Fixture* fixtureA;
b2Fixture* fixtureB;
};

// Contact listener
class MyContactListener : public b2ContactListener


{
// Callbacks for derived classes.
virtual void BeginContact(b2Contact* contact)

{
if (contact)

{
MyContact mc;
mc.fixtureA = contact->GetFixtureA();
mc.fixtureB = contact->GetFixtureB();

contact_list.push_back(mc);
}
B2_NOT_USED(contact);
}
virtual void EndContact(b2Contact* contact)

{
contact_list.clear();
B2_NOT_USED(contact);
}
virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)

{
B2_NOT_USED(contact);
B2_NOT_USED(oldManifold);
}
virtual void PostSolve(const b2Contact* contact, const b2ContactImpulse* impulse)

{
B2_NOT_USED(contact);
B2_NOT_USED(impulse);
}

public:
std::list<MyContact> contact_list;
};

class HelloWorld : public cocos2d::CCLayer


{
public:
HelloWorld();
~HelloWorld();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();

// there's no 'id' in cpp, so we recommand to return the exactly class pointer
static cocos2d::CCScene* scene();
// a selector callback
void menuCloseCallback(CCObject* pSender);
virtual void ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);
virtual void ccTouchesMoved(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);
virtual void ccTouchesEnded(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);
virtual void ccTouchesCancelled(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);

cocos2d::CCTMXLayer *baseLayer;

// implement the "static node()" method manually
LAYER_CREATE_FUNC(HelloWorld);

private:
// Update per second
void secondUpdate(float dt)

{
spawnCat();
}
void tick(float dt);

// spawn a car
void spawnCar();

// spawn a car
void spawnCat();

// Sprite move over call back
void spriteDone(cocos2d::CCNode* sender);

// Add contact b2box for sprite
void addBoxBodyForSprite(cocos2d::CCSprite* sprite);

b2World* world;
MyContactListener* contactListener; // Contact event listener
};

#endif // __HELLOWORLD_SCENE_H__

HelloWorldScene.cpp
#include "HelloWorldScene.h"

USING_NS_CC;
USING_NS_CC_EXT;
using namespace std;

#define TILE_SIZE 32
#define PT_RATIO 32 // 这个数一般定义为: 32.0,在box 世界中 是以 米 为单位的,这里是将坐标兑换为box世界中的米,即除以 PTM_RATIO

//--------------------------------------------

HelloWorld::HelloWorld()


{

}

HelloWorld::~HelloWorld()


{
if(world)
delete world;
}

CCScene* HelloWorld::scene()


{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();

// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();

// add layer as a child to scene
scene->addChild(layer);

// return the scene
return scene;
}

enum


{
kTagTileMap = 1,
};

CCLabelTTF* pLabel;
// on "init" you need to initialize your instance
bool HelloWorld::init()


{

/**///////////////////////////////
// 1. super init first
if ( !CCLayer::init() )

{
return false;
}

pLabel = CCLabelTTF::create("Collsion", "Arial", 24);
CCSize size = CCDirector::sharedDirector()->getWinSize();

// position the label on the center of the screen
pLabel->setPosition( ccp(size.width / 2, size.height - 50) );

// add the label as a child to this layer
this->addChild(pLabel, 1, 0);

// create physic world
b2Vec2 gravity(0,0);
world = new b2World(gravity);
world->SetAllowSleeping(false);

contactListener = new MyContactListener();
world->SetContactListener(contactListener);

spawnCar();
schedule(schedule_selector(HelloWorld::tick));
schedule(schedule_selector(HelloWorld::secondUpdate), 1.f);
setTouchEnabled(true);
return true;
}


void HelloWorld::tick(float dt)


{
if (world)
world->Step(dt, 10, 10);

// 基于cocos2d的精灵位置来更新box2d的body位置
for(b2Body* b = world->GetBodyList(); b; b = b->GetNext())

{
if (b->GetUserData() != NULL)

{
CCSprite* sprite = (CCSprite*)b->GetUserData();
if (sprite)

{
b2Vec2 pt = b2Vec2((float)(sprite->getPosition().x / PT_RATIO), (float)(sprite->getPosition().y / PT_RATIO));
float angle = (CCFloat)CC_DEGREES_TO_RADIANS(sprite->getRotation());
b->SetTransform(pt, angle);
}
}
}

std::list<b2Body*> toDestroy_list;

for( std::list<MyContact>::iterator it = contactListener->contact_list.begin();
it != contactListener->contact_list.end();
++it)

{
MyContact& contact = *it;

b2Body* bodyA = contact.fixtureA->GetBody();
b2Body* bodyB = contact.fixtureB->GetBody();

CCSprite* sa = (CCSprite*)bodyA->GetUserData();
CCSprite* sb = (CCSprite*)bodyB->GetUserData();
if (sa && sb)

{
if (sa->getTag() == 1 && sb->getTag() == 2)
toDestroy_list.push_back(bodyB);
else if (sa->getTag() == 2 && sa->getTag() == 1)
toDestroy_list.push_back(bodyA);
}
}
// Destroy contact item.
std::list<b2Body*>::iterator it = toDestroy_list.begin();
while(it != toDestroy_list.end())

{
if ((*it)->GetUserData() != NULL)

{
CCSprite* sprite = (CCSprite*)((*it)->GetUserData());
if (sprite)

{
removeChild(sprite, true);
}
world->DestroyBody(*it);
}

++it;
}

toDestroy_list.clear();
}

void HelloWorld::spawnCar()


{
CCSprite* car = CCSprite::spriteWithFile("images/car.png");
car->setPosition(ccp(100,100));

car->runAction(CCRepeatForever::actionWithAction((CCActionInterval*)CCSequence::actions(
CCMoveTo::actionWithDuration(1.0f, ccp(300,100)),
CCMoveTo::actionWithDuration(1.0f, ccp(200,200)),
CCMoveTo::actionWithDuration(1.0f, ccp(100,100)),
NULL
)));

addBoxBodyForSprite(car);
this->addChild(car, 1, 1);
}

void HelloWorld::spawnCat()


{
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCSprite* cat = CCSprite::spriteWithFile("images/cat.png");

float minY = cat->getContentSize().height/2;
float maxY = winSize.height - cat->getContentSize().height/2;
float y = minY + rand() % (int)(maxY - minY);

float startX = winSize.width + cat->getContentSize().width/2;
float endX = -cat->getContentSize().width/2;

CCPoint startPos = ccp(startX, y);
CCPoint endPos = ccp(endX, y);

cat->setPosition(startPos);

cat->runAction(CCSequence::actions(CCMoveTo::actionWithDuration(10.f, endPos),
CCCallFuncN::actionWithTarget(this, callfuncN_selector(HelloWorld::spriteDone)), NULL));


addBoxBodyForSprite(cat);
addChild(cat, 1, 2);
}

void HelloWorld::addBoxBodyForSprite(cocos2d::CCSprite* sprite)


{
//PTM_RATIO ,这个数一般定义为: 32.0,在box 世界中 是以 米 为单位的,这里是将坐标兑换为box世界中的米,即除以 PTM_RATIO

// Create physic body for cat
b2PolygonShape polygon;
polygon.SetAsBox((float)sprite->getContentSize().width/PT_RATIO/2, (float)sprite->getContentSize().height/PT_RATIO/2);

b2FixtureDef spriteShapeDef;
spriteShapeDef.shape = &polygon;
spriteShapeDef.density = 10.f;
spriteShapeDef.isSensor = true; // 对象之间有碰撞检测但是又不想让它们有碰撞反应

b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position = b2Vec2((float)(sprite->getPosition().x / PT_RATIO),
(float)(sprite->getPosition().y /PT_RATIO));
bd.userData = sprite;

b2Body* spriteBody = world->CreateBody(&bd);
spriteBody->CreateFixture(&spriteShapeDef);
}



void HelloWorld::spriteDone(CCNode* sender)


{
// sprites被销毁的时候,我们需要销毁Box2d的body
CCSprite* sprite = dynamic_cast<CCSprite*>(sender);
if (sprite)

{
b2Body* spriteBody = NULL;
for(b2Body* b = world->GetBodyList(); b; b=b->GetNext())

{
if (b->GetUserData() != NULL)

{
CCSprite* curSprite = (CCSprite*)b->GetUserData();
if (curSprite == sprite)

{
spriteBody = b;

removeChild(sprite, true);
world->DestroyBody(spriteBody);
break;
}
}

//if (spriteBody)
//{
// world->DestroyBody(spriteBody);
//}

// removeChild(sprite, true);
}
}
}

void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)


{
CCSetIterator iter = pTouches->begin();
for (; iter != pTouches->end(); iter++)

{
CCTouch* pTouch = (CCTouch*)(*iter);
CCPoint pos = pTouch->locationInView();
pos = CCDirector::sharedDirector()->convertToGL(pos);

}
}

void HelloWorld::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)


{
CCSetIterator iter = pTouches->begin();
for (; iter != pTouches->end(); iter++)

{
CCTouch* pTouch = (CCTouch*)(*iter);
CCPoint pos = pTouch->locationInView();

CCPoint touchLocation = pTouch->locationInView();
CCPoint prevLocation = pTouch->previousLocationInView();

/**//* touchLocation = CCDirector::sharedDirector()->convertToGL( touchLocation );
prevLocation = CCDirector::sharedDirector()->convertToGL( prevLocation );
CCPoint diff = ccpSub(touchLocation, prevLocation);
CCNode *node = getChildByTag(kTagTileMap);
CCPoint currentPos = node->getPosition();

node->setPosition( ccpAdd(currentPos, diff) )*/;
}
}

void HelloWorld::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)


{
CCSetIterator iter = pTouches->begin();
for (; iter != pTouches->end(); iter++)

{
CCTouch* pTouch = (CCTouch*)(*iter);
}
}

void HelloWorld::ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent)


{
ccTouchesEnded(pTouches, pEvent);
}
查看源代码
posted on 2012-07-12 15:21
风轻云淡 阅读(9680)
评论(3) 编辑 收藏 引用