感谢大家的鼓励和支持,今天我们学习一下box2d物理引擎.
不了解cocos2dx基本概念的朋友,请移步
http://blog.csdn.net/s_xing/article/details/18557631。
转载请注明出处http://blog.csdn.net/s_xing/article/details/20165097
感觉直接看代码太枯燥的,请关注视频讲解
更新:高清avi视频和源代码已经提供下载:
百度网盘:http://pan.baidu.com/s/1ELk78 里面的进阶篇。
今天一共讲了五堂课,学习的是老外的一个游戏。原文地址:http://www.raywenderlich.com/28602/intro-to-box2d-with-cocos2d-2-x-tutorial-bouncing-balls。源代码如下
1. 主场景
#include "HelloWorldScene.h"
#include "Box2dUtils.h"
#include "MyContactListener.h"
#include "GameOverScense.h"
#include "SimpleAudioEngine.h"
USING_NS_CC;
#define PTM_RATIO 32.0f
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;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
CCSize screenSize = CCDirector::sharedDirector()->getVisibleSize();
CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
// 创建球的cocos2d图形
_ballSprite = CCSprite::create("ball.png");
_ballSprite->setPosition(ccp(39, 300));
this->addChild(_ballSprite);
_paddleSprite = CCSprite::create("paddle.png");
_paddleSprite->setPosition(ccp(120, 50));
this->addChild(_paddleSprite);
// 创建box2d世界
_world = new b2World(b2Vec2(0, 0));
// 创建球
_ball = Box2dUtils::createDynamicBody(_ballSprite->getPositionX() / PTM_RATIO,
_ballSprite->getPositionY() / PTM_RATIO,
_ballSprite,
_world);
b2CircleShape circle;
circle.m_radius = _ballSprite->getContentSize().width / 2 / PTM_RATIO;
Box2dUtils::createFixture(&circle,
10, 0, 1.0, _ball);
_ball->ApplyLinearImpulse(_ball->GetMass() * b2Vec2(11, 22),
_ball->GetWorldCenter());
// 添加底座
_paddle = Box2dUtils::createDynamicBody(_paddleSprite->getPositionX() / PTM_RATIO,
_paddleSprite->getPositionY() / PTM_RATIO,
_paddleSprite,
_world);
b2PolygonShape boxShape;
boxShape.SetAsBox(_paddleSprite->getContentSize().width / 2.0f / PTM_RATIO,
_paddleSprite->getContentSize().height / 2.0f / PTM_RATIO);
Box2dUtils::createFixture(&boxShape,
8, 0, 0.5, _paddle);
// 添加目标 被打击的砖块
const int padding = 10;
float offsetX = 150.0f;
for (int i = 0; i < 4; i ++){
CCSprite* block = CCSprite::create("block.png");
block->setPosition(ccp(offsetX, 400.0));
block->setTag(3);
this->addChild(block);
//物理 实体
b2Body* blockBody = Box2dUtils::createDynamicBody(offsetX/ PTM_RATIO,
400 / PTM_RATIO,
block,
_world);
b2PolygonShape blockBox;
blockBox.SetAsBox(block->getContentSize().width / 2.0f / PTM_RATIO,
block->getContentSize().height / 2.0f / PTM_RATIO);
Box2dUtils::createFixture(&blockBox,
10.0f, 0.0f, 0.2f, blockBody);
offsetX += (padding + block->getContentSize().width);
}
// 创建4面墙
// b2BodyDef -->b2Body
b2BodyDef groundBodyDef;
groundBodyDef.type = b2_staticBody;
groundBodyDef.position.Set(0, 0); // 相当于cocos2d 中的锚点
_groundBody = _world->CreateBody(&groundBodyDef);
// b2FixtureDef -->b2Fixture
b2EdgeShape groundShape;
groundShape.Set(b2Vec2(0, 0), b2Vec2(screenSize.width / PTM_RATIO, 0));
b2FixtureDef groundFixDef;
groundFixDef.shape = &groundShape;
groundFixDef.friction = 0.9f;
_bottom = _groundBody->CreateFixture(&groundFixDef);
// 创建左面 墙
b2EdgeShape leftWall;
leftWall.Set(b2Vec2(0, 0), b2Vec2(0, screenSize.height / PTM_RATIO));
groundFixDef.shape = &leftWall;
_groundBody->CreateFixture(&groundFixDef);
// 创建右面的墙
b2EdgeShape rightWall;
rightWall.Set(b2Vec2(screenSize.width / PTM_RATIO, 0),
b2Vec2(screenSize.width / PTM_RATIO, screenSize.height / PTM_RATIO));
groundFixDef.shape = &rightWall;
_groundBody->CreateFixture(&groundFixDef);
// 创建 顶部
b2EdgeShape top;
top.Set(b2Vec2(0, screenSize.height / PTM_RATIO),
b2Vec2(screenSize.width / PTM_RATIO, screenSize.height / PTM_RATIO));
groundFixDef.shape = ⊤
_groundBody->CreateFixture(&groundFixDef);
this->scheduleUpdate();
// 实现 指哪打哪 鼠标拖动到哪里 指定的物体移动到哪里
// box2d joint 关节
this->setTouchEnabled(true);
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
_mouseJoint = NULL;
// 平移关节 限制底座 只能水平方向移动
b2PrismaticJointDef primaticJointDef;
primaticJointDef.Initialize(_world->CreateBody(new b2BodyDef),
_paddle,
_paddle->GetWorldCenter(),
b2Vec2(3.0, 0));
_world->CreateJoint(&primaticJointDef);
listener = new MyContactListener;
_world->SetContactListener(listener);
_score = 0;
CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("background-music-aac.WAV", true);
return true;
}
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){
CCPoint touchPos = pTouch->getLocation();
b2Vec2 touchPhysicsPos(touchPos.x / PTM_RATIO,touchPos.y / PTM_RATIO);
b2Fixture* paddleFix = _paddle->GetFixtureList(); //得到底座的 fixture ---包含了形状信息
/*CCRect paddleRect; // 在cocos2d 世界中判断
paddleRect.containsPoint(touchPos);*/
if (paddleFix->TestPoint(touchPhysicsPos)){ //触摸点在paddle的范围内 在物理世界中判断
// 鼠标关节 鼠标控制我们的底座 applyLinearImpulse
b2MouseJointDef mouseJointDef;
mouseJointDef.bodyA = _world->CreateBody(new b2BodyDef);
mouseJointDef.bodyB = _paddle;
mouseJointDef.maxForce = 1000.0 * _paddle->GetMass();
mouseJointDef.target = touchPhysicsPos; //设置物体的目标位置
_mouseJoint = (b2MouseJoint*)_world->CreateJoint(&mouseJointDef);
//CCLog("touch began true.\n");
return true;// 该 touch 代理上的ccTouchMoved ccTouchEnded 会得到执行
}
CCLog("touch began false.\n");
return false; // 该 touch 代理上的ccTouchMoved ccTouchEnded 不会得到执行
}
void HelloWorld::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent){
if (_mouseJoint)
{
CCPoint touchPos = pTouch->getLocation();
b2Vec2 touchPhysicsPos(touchPos.x / PTM_RATIO,touchPos.y / PTM_RATIO);
_mouseJoint->SetTarget(touchPhysicsPos);//设置物体的目标位置
}
//CCLog("touch ccTouchMoved func.\n");
}
void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent){
if (_mouseJoint){
_world->DestroyJoint(_mouseJoint);
_mouseJoint = NULL;
}
//CCLog("touch ccTouchEnded func.\n");
}
int _getTagForBody(b2Body* body){
if (body->GetUserData()){
CCSprite* sp = (CCSprite*) body->GetUserData();
return sp->getTag();
}
return -1;
}
void HelloWorld::update(float delta){
_world->Step(delta, 6, 6);
for(b2Body* body = _world->GetBodyList(); body != NULL; body = body->GetNext()){
if (body->GetUserData()){
CCSprite* sp = (CCSprite*)body->GetUserData();
if (sp == _ballSprite){ // 限制球速
b2Vec2 spped = body->GetLinearVelocity();
if (spped.LengthSquared() > 200){
body->SetLinearDamping(0.9); //设置 减震之后 持续生效
}
else if (spped.LengthSquared() <200){
body->SetLinearDamping(0.0); //设置 减震之后 持续生效
if (spped.LengthSquared() < 60){
body->ApplyLinearImpulse(body->GetMass() * 5.0 * spped,
body->GetWorldCenter());
}
}
}
sp->setPosition(ccp(body->GetPosition().x * PTM_RATIO,
body->GetPosition().y *PTM_RATIO));
}
}
b2Body* bodyToDestroy = NULL;
vector<MyContactPeer>::iterator it;
for (it = listener->_contacts.begin();
it != listener->_contacts.end();
it ++){
MyContactPeer curContact = *it;
b2Body* bodyA = curContact.fixA->GetBody();
b2Body* bodyB = curContact.fixB->GetBody();
int tagA, tagB;
tagA = _getTagForBody(bodyA);
tagB = _getTagForBody(bodyB);
// 小球和地面碰撞 失败
if (bodyA == _ball && curContact.fixB == _bottom){
//CCLog("fail");
CCDirector::sharedDirector()->replaceScene(GameOverScene::scenseWithWin(false));
}
else if (bodyB == _ball && curContact.fixA == _bottom){
//CCLog("fail");
CCDirector::sharedDirector()->replaceScene(GameOverScene::scenseWithWin(false));
}
else if (bodyA == _ball && 3 == tagB){
//CCLog("kill block");
bodyToDestroy = bodyB;
}
else if (bodyB == _ball && 3 == tagA){
//CCLog("kill block");
//CCLog("kill block");
bodyToDestroy = bodyA;
}
}
if (bodyToDestroy){
((CCSprite*)bodyToDestroy->GetUserData())->removeFromParentAndCleanup(true);
_world->DestroyBody(bodyToDestroy);
_score ++;
CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("blip.WAV");
CCLog("_score is %d", _score);
if (_score >= 4){
CCDirector::sharedDirector()->replaceScene(GameOverScene::scenseWithWin(true));
}
}
}
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
#else
CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
#endif
}
转载注明出处:http://blog.csdn.net/s_xing/article/details/20836727
csdn不给力,文章长度限制,所以请大家跳到续篇-- http://blog.csdn.net/s_xing/article/details/20836693