感谢大家的鼓励和支持,今天我们学习一下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