根据上一节的教程,我用C++更改了教程,我用的cocos2d-2.0-rc2-x-2.0.1版本,略微有些不同,都是小细节,直接贴上代码
HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
![](/Images/OutliningIndicators/None.gif)
#include <Box2D/Box2D.h>
#include "cocos2d.h"
#include <list>
using std::list;
![](/Images/OutliningIndicators/None.gif)
class MyContact
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
b2Fixture* fixtureA;
b2Fixture* fixtureB;
};
![](/Images/OutliningIndicators/None.gif)
// Contact listener
class MyContactListener : public b2ContactListener
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
// Callbacks for derived classes.
virtual void BeginContact(b2Contact* contact)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (contact)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
MyContact mc;
mc.fixtureA = contact->GetFixtureA();
mc.fixtureB = contact->GetFixtureB();
![](/Images/OutliningIndicators/InBlock.gif)
contact_list.push_back(mc);
}
B2_NOT_USED(contact);
}
virtual void EndContact(b2Contact* contact)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
contact_list.clear();
B2_NOT_USED(contact);
}
virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
B2_NOT_USED(contact);
B2_NOT_USED(oldManifold);
}
virtual void PostSolve(const b2Contact* contact, const b2ContactImpulse* impulse)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
B2_NOT_USED(contact);
B2_NOT_USED(impulse);
}
![](/Images/OutliningIndicators/InBlock.gif)
public:
std::list<MyContact> contact_list;
};
![](/Images/OutliningIndicators/None.gif)
class HelloWorld : public cocos2d::CCLayer
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
HelloWorld();
~HelloWorld();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
![](/Images/OutliningIndicators/InBlock.gif)
// 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);
![](/Images/OutliningIndicators/InBlock.gif)
cocos2d::CCTMXLayer *baseLayer;
![](/Images/OutliningIndicators/InBlock.gif)
// implement the "static node()" method manually
LAYER_CREATE_FUNC(HelloWorld);
![](/Images/OutliningIndicators/InBlock.gif)
private:
// Update per second
void secondUpdate(float dt)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
spawnCat();
}
void tick(float dt);
![](/Images/OutliningIndicators/InBlock.gif)
// spawn a car
void spawnCar();
![](/Images/OutliningIndicators/InBlock.gif)
// spawn a car
void spawnCat();
![](/Images/OutliningIndicators/InBlock.gif)
// Sprite move over call back
void spriteDone(cocos2d::CCNode* sender);
![](/Images/OutliningIndicators/InBlock.gif)
// Add contact b2box for sprite
void addBoxBodyForSprite(cocos2d::CCSprite* sprite);
![](/Images/OutliningIndicators/InBlock.gif)
b2World* world;
MyContactListener* contactListener; // Contact event listener
};
![](/Images/OutliningIndicators/None.gif)
#endif // __HELLOWORLD_SCENE_H__
![](/Images/OutliningIndicators/None.gif)
HelloWorldScene.cpp
#include "HelloWorldScene.h"
![](/Images/OutliningIndicators/None.gif)
USING_NS_CC;
USING_NS_CC_EXT;
using namespace std;
![](/Images/OutliningIndicators/None.gif)
#define TILE_SIZE 32
#define PT_RATIO 32 // 这个数一般定义为: 32.0,在box 世界中 是以 米 为单位的,这里是将坐标兑换为box世界中的米,即除以 PTM_RATIO
![](/Images/OutliningIndicators/None.gif)
//--------------------------------------------
![](/Images/OutliningIndicators/None.gif)
HelloWorld::HelloWorld()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/Images/OutliningIndicators/None.gif)
HelloWorld::~HelloWorld()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
if(world)
delete world;
}
![](/Images/OutliningIndicators/None.gif)
CCScene* HelloWorld::scene()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
![](/Images/OutliningIndicators/InBlock.gif)
// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();
![](/Images/OutliningIndicators/InBlock.gif)
// add layer as a child to scene
scene->addChild(layer);
![](/Images/OutliningIndicators/InBlock.gif)
// return the scene
return scene;
}
![](/Images/OutliningIndicators/None.gif)
enum
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
kTagTileMap = 1,
};
![](/Images/OutliningIndicators/None.gif)
CCLabelTTF* pLabel;
// on "init" you need to initialize your instance
bool HelloWorld::init()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**///////////////////////////////
// 1. super init first
if ( !CCLayer::init() )
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return false;
}
![](/Images/OutliningIndicators/InBlock.gif)
pLabel = CCLabelTTF::create("Collsion", "Arial", 24);
CCSize size = CCDirector::sharedDirector()->getWinSize();
![](/Images/OutliningIndicators/InBlock.gif)
// position the label on the center of the screen
pLabel->setPosition( ccp(size.width / 2, size.height - 50) );
![](/Images/OutliningIndicators/InBlock.gif)
// add the label as a child to this layer
this->addChild(pLabel, 1, 0);
![](/Images/OutliningIndicators/InBlock.gif)
// create physic world
b2Vec2 gravity(0,0);
world = new b2World(gravity);
world->SetAllowSleeping(false);
![](/Images/OutliningIndicators/InBlock.gif)
contactListener = new MyContactListener();
world->SetContactListener(contactListener);
![](/Images/OutliningIndicators/InBlock.gif)
spawnCar();
schedule(schedule_selector(HelloWorld::tick));
schedule(schedule_selector(HelloWorld::secondUpdate), 1.f);
setTouchEnabled(true);
return true;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
void HelloWorld::tick(float dt)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
if (world)
world->Step(dt, 10, 10);
![](/Images/OutliningIndicators/InBlock.gif)
// 基于cocos2d的精灵位置来更新box2d的body位置
for(b2Body* b = world->GetBodyList(); b; b = b->GetNext())
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (b->GetUserData() != NULL)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
CCSprite* sprite = (CCSprite*)b->GetUserData();
if (sprite)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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);
}
}
}
![](/Images/OutliningIndicators/InBlock.gif)
std::list<b2Body*> toDestroy_list;
![](/Images/OutliningIndicators/InBlock.gif)
for( std::list<MyContact>::iterator it = contactListener->contact_list.begin();
it != contactListener->contact_list.end();
++it)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
MyContact& contact = *it;
![](/Images/OutliningIndicators/InBlock.gif)
b2Body* bodyA = contact.fixtureA->GetBody();
b2Body* bodyB = contact.fixtureB->GetBody();
![](/Images/OutliningIndicators/InBlock.gif)
CCSprite* sa = (CCSprite*)bodyA->GetUserData();
CCSprite* sb = (CCSprite*)bodyB->GetUserData();
if (sa && sb)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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())
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if ((*it)->GetUserData() != NULL)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
CCSprite* sprite = (CCSprite*)((*it)->GetUserData());
if (sprite)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
removeChild(sprite, true);
}
world->DestroyBody(*it);
}
![](/Images/OutliningIndicators/InBlock.gif)
++it;
}
![](/Images/OutliningIndicators/InBlock.gif)
toDestroy_list.clear();
}
![](/Images/OutliningIndicators/None.gif)
void HelloWorld::spawnCar()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
CCSprite* car = CCSprite::spriteWithFile("images/car.png");
car->setPosition(ccp(100,100));
![](/Images/OutliningIndicators/InBlock.gif)
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
)));
![](/Images/OutliningIndicators/InBlock.gif)
addBoxBodyForSprite(car);
this->addChild(car, 1, 1);
}
![](/Images/OutliningIndicators/None.gif)
void HelloWorld::spawnCat()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCSprite* cat = CCSprite::spriteWithFile("images/cat.png");
![](/Images/OutliningIndicators/InBlock.gif)
float minY = cat->getContentSize().height/2;
float maxY = winSize.height - cat->getContentSize().height/2;
float y = minY + rand() % (int)(maxY - minY);
![](/Images/OutliningIndicators/InBlock.gif)
float startX = winSize.width + cat->getContentSize().width/2;
float endX = -cat->getContentSize().width/2;
![](/Images/OutliningIndicators/InBlock.gif)
CCPoint startPos = ccp(startX, y);
CCPoint endPos = ccp(endX, y);
![](/Images/OutliningIndicators/InBlock.gif)
cat->setPosition(startPos);
![](/Images/OutliningIndicators/InBlock.gif)
cat->runAction(CCSequence::actions(CCMoveTo::actionWithDuration(10.f, endPos),
CCCallFuncN::actionWithTarget(this, callfuncN_selector(HelloWorld::spriteDone)), NULL));
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
addBoxBodyForSprite(cat);
addChild(cat, 1, 2);
}
![](/Images/OutliningIndicators/None.gif)
void HelloWorld::addBoxBodyForSprite(cocos2d::CCSprite* sprite)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
//PTM_RATIO ,这个数一般定义为: 32.0,在box 世界中 是以 米 为单位的,这里是将坐标兑换为box世界中的米,即除以 PTM_RATIO
![](/Images/OutliningIndicators/InBlock.gif)
// Create physic body for cat
b2PolygonShape polygon;
polygon.SetAsBox((float)sprite->getContentSize().width/PT_RATIO/2, (float)sprite->getContentSize().height/PT_RATIO/2);
![](/Images/OutliningIndicators/InBlock.gif)
b2FixtureDef spriteShapeDef;
spriteShapeDef.shape = &polygon;
spriteShapeDef.density = 10.f;
spriteShapeDef.isSensor = true; // 对象之间有碰撞检测但是又不想让它们有碰撞反应
![](/Images/OutliningIndicators/InBlock.gif)
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position = b2Vec2((float)(sprite->getPosition().x / PT_RATIO),
(float)(sprite->getPosition().y /PT_RATIO));
bd.userData = sprite;
![](/Images/OutliningIndicators/InBlock.gif)
b2Body* spriteBody = world->CreateBody(&bd);
spriteBody->CreateFixture(&spriteShapeDef);
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
void HelloWorld::spriteDone(CCNode* sender)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
// sprites被销毁的时候,我们需要销毁Box2d的body
CCSprite* sprite = dynamic_cast<CCSprite*>(sender);
if (sprite)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
b2Body* spriteBody = NULL;
for(b2Body* b = world->GetBodyList(); b; b=b->GetNext())
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (b->GetUserData() != NULL)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
CCSprite* curSprite = (CCSprite*)b->GetUserData();
if (curSprite == sprite)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
spriteBody = b;
![](/Images/OutliningIndicators/InBlock.gif)
removeChild(sprite, true);
world->DestroyBody(spriteBody);
break;
}
}
![](/Images/OutliningIndicators/InBlock.gif)
//if (spriteBody)
//{
// world->DestroyBody(spriteBody);
//}
![](/Images/OutliningIndicators/InBlock.gif)
// removeChild(sprite, true);
}
}
}
![](/Images/OutliningIndicators/None.gif)
void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
CCSetIterator iter = pTouches->begin();
for (; iter != pTouches->end(); iter++)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
CCTouch* pTouch = (CCTouch*)(*iter);
CCPoint pos = pTouch->locationInView();
pos = CCDirector::sharedDirector()->convertToGL(pos);
![](/Images/OutliningIndicators/InBlock.gif)
}
}
![](/Images/OutliningIndicators/None.gif)
void HelloWorld::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
CCSetIterator iter = pTouches->begin();
for (; iter != pTouches->end(); iter++)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
CCTouch* pTouch = (CCTouch*)(*iter);
CCPoint pos = pTouch->locationInView();
![](/Images/OutliningIndicators/InBlock.gif)
CCPoint touchLocation = pTouch->locationInView();
CCPoint prevLocation = pTouch->previousLocationInView();
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//* touchLocation = CCDirector::sharedDirector()->convertToGL( touchLocation );
prevLocation = CCDirector::sharedDirector()->convertToGL( prevLocation );
CCPoint diff = ccpSub(touchLocation, prevLocation);
CCNode *node = getChildByTag(kTagTileMap);
CCPoint currentPos = node->getPosition();
![](/Images/OutliningIndicators/InBlock.gif)
node->setPosition( ccpAdd(currentPos, diff) )*/;
}
}
![](/Images/OutliningIndicators/None.gif)
void HelloWorld::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
CCSetIterator iter = pTouches->begin();
for (; iter != pTouches->end(); iter++)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
CCTouch* pTouch = (CCTouch*)(*iter);
}
}
![](/Images/OutliningIndicators/None.gif)
void HelloWorld::ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
ccTouchesEnded(pTouches, pEvent);
}
查看源代码
posted on 2012-07-12 15:21
风轻云淡 阅读(9642)
评论(3) 编辑 收藏 引用