Cocos2d Box2D 开发Android下的 Breakout 撞球游戏

来源:互联网 发布:iphone视频软件 编辑:程序博客网 时间:2024/05/16 09:40

网上有文章介绍如何构造 撞球游戏( http://www.raywenderlich.com/28602/intro-to-box2d-with-cocos2d-2-x-tutorial-bouncing-balls )

但是它是基于 Apple, 我通过实践构造了 Android 下项目并成功编译运行


现假设已经生成 Android 下的 Hello World 项目 (可以参见 分析Cocos2d Android 项目的生成和运行)

现在我们通过改写 HelloWorldScene.h, HelloWorldScene.cpp 生成撞球游戏


集成 box2d

Cocos 已经帮我们集成了 Box2D ( cocos2d-2.1rc0-x-2.1.2\external\Box2D ), 并且 build 到 cocos_extension_static, 最终生成的 libgame 会被自动 load, 因此我们直接使用就可以了

就是头文件有些问题, 用下面方法解决

修改Cocos3\proj.android\jni\Android.mk

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes

改为

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes  $(LOCAL_PATH)/../../../external/Box2D


修改文件

(参照 http://www.raywenderlich.com/28602/intro-to-box2d-with-cocos2d-2-x-tutorial-bouncing-balls) 

改动 HelloWorldScene.h

[cpp] view plaincopy
  1. #ifndef __HELLOWORLD_SCENE_H__  
  2. #define __HELLOWORLD_SCENE_H__  
  3.   
  4. #include "cocos2d.h"  
  5. #include "Box2D.h"  
  6. #define PTM_RATIO 32.0  
  7.   
  8.   
  9.   
  10. class HelloWorld : public cocos2d::CCLayer  
  11. {  
  12. public:  
  13.     // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone  
  14.     virtual bool init();    
  15.   
  16.     // there's no 'id' in cpp, so we recommand to return the exactly class pointer  
  17.     static cocos2d::CCScene* scene();  
  18.       
  19.     // a selector callback  
  20.     void menuCloseCallback(CCObject* pSender);  
  21.   
  22.     // implement the "static node()" method manually  
  23.     CREATE_FUNC(HelloWorld);  
  24.       
  25.     b2World *_world;  
  26.     b2Body *_body;  
  27.     cocos2d::CCSprite *_ball;  
  28.   
  29. #endif // __HELLOWORLD_SCENE_H__  

改动 HelloWorldScene.cpp

[cpp] view plaincopy
  1. #include "HelloWorldScene.h"  
  2. #include "SimpleAudioEngine.h"  
  3.   
  4. using namespace cocos2d;  
  5. using namespace CocosDenshion;  
  6.   
  7. CCScene* HelloWorld::scene()  
  8. {  
  9.     // 'scene' is an autorelease object  
  10.     CCScene *scene = CCScene::create();  
  11.       
  12.     // 'layer' is an autorelease object  
  13.     HelloWorld *layer = HelloWorld::create();  
  14.   
  15.     // add layer as a child to scene  
  16.     scene->addChild(layer);  
  17.   
  18.     // return the scene  
  19.     return scene;  
  20. }  
  21.   
  22. // on "init" you need to initialize your instance  
  23. bool HelloWorld::init()  
  24. {  
  25.     //////////////////////////////  
  26.     // 1. super init first  
  27.     if ( !CCLayer::init() )  
  28.     {  
  29.         return false;  
  30.     }  
  31.       
  32.     CCMenuItemImage *pCloseItem = CCMenuItemImage::create(  
  33.     "CloseNormal.png",  
  34.     "CloseSelected.png",  
  35.     this,  
  36.     menu_selector(HelloWorld::menuCloseCallback) );  
  37.     pCloseItem->setPosition( ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20) );  
  38.   
  39.     // create menu, it's an autorelease object  
  40.     CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);  
  41.     pMenu->setPosition( CCPointZero );  
  42.     this->addChild(pMenu, 1);  
  43.   
  44.       
  45.       
  46.     CCSize winSize = CCDirector::sharedDirector()->getWinSize();  
  47.     CCSprite* _ball = CCSprite::create("ball.png");  
  48.     this->addChild(_ball, 0);  
  49.     _ball->setPosition( ccp(100,300) );  
  50.       
  51.       
  52.     b2Vec2 gravity(0.0f, -8.0f);  
  53.     _world = new b2World(gravity);  
  54.   
  55.   
  56.     b2BodyDef groundBodyDef;  
  57.     groundBodyDef.position.Set(0,0);  
  58.   
  59.   
  60.     b2Body *groundBody = _world->CreateBody(&groundBodyDef);  
  61.     b2EdgeShape groundEdge;  
  62.       
  63.     b2FixtureDef boxShapeDef;  
  64.     boxShapeDef.shape = &groundEdge;  
  65.   
  66.     //wall definitions  
  67.     //bottom  
  68.     groundEdge.Set(b2Vec2(0,0), b2Vec2(winSize.width /PTM_RATIO, 0));  
  69.     groundBody->CreateFixture(&boxShapeDef);  
  70.       
  71.     // left  
  72.     groundEdge.Set(b2Vec2(0,0), b2Vec2(0,winSize.height/PTM_RATIO));  
  73.     groundBody->CreateFixture(&boxShapeDef);  
  74.       
  75.     // top  
  76.     groundEdge.Set(b2Vec2(0, winSize.height/PTM_RATIO),  
  77.     b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO));  
  78.     groundBody->CreateFixture(&boxShapeDef);  
  79.   
  80.     // right  
  81.     groundEdge.Set(b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO),  
  82.     b2Vec2(winSize.width/PTM_RATIO, 0));  
  83.     groundBody->CreateFixture(&boxShapeDef);  
  84.       
  85.   
  86.       
  87.     b2BodyDef ballBodyDef;  
  88.     ballBodyDef.type = b2_dynamicBody;  
  89.     ballBodyDef.position.Set(100/PTM_RATIO, 300/PTM_RATIO);  
  90.     ballBodyDef.userData = _ball;  
  91.     _body = _world->CreateBody(&ballBodyDef);  
  92.   
  93.   
  94.     b2CircleShape circle;  
  95.     circle.m_radius = 26.0/PTM_RATIO;  
  96.   
  97.     b2FixtureDef ballShapeDef;  
  98.     ballShapeDef.shape = &circle;  
  99.     ballShapeDef.density = 1.0f;  
  100.     ballShapeDef.friction = 0.2f;  
  101.     ballShapeDef.restitution = 0.8f;  
  102.     _body->CreateFixture(&ballShapeDef);  
  103.       
  104.     schedule(schedule_selector(HelloWorld::tick));    
  105.     //schedule(schedule_selector(HelloWorld::kick), 5);   
  106.   
  107.     CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("background-music-aac.wav"true);  
  108.     return true;  
  109. }  
  110.   
  111. void HelloWorld::menuCloseCallback(CCObject* pSender)  
  112. {  
  113.     CCDirector::sharedDirector()->end();  
  114.   
  115. #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)  
  116.     exit(0);  
  117. #endif  
  118. }  
  119.   
  120. void HelloWorld::tick(float dt)   
  121. {   
  122.   
  123.     _world->Step(dt, 10, 10);  
  124.     for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {      
  125.         if (b->GetUserData() != NULL) {  
  126.             CCSprite *ballData = (CCSprite *)b->GetUserData();  
  127.             ballData->setPosition(ccp(b->GetPosition().x * PTM_RATIO,  
  128.             b->GetPosition().y * PTM_RATIO));  
  129.             ballData->setRotation(-1 * CC_RADIANS_TO_DEGREES(b->GetAngle()));  
  130.         }          
  131.     }  
  132. }     

复制资源文件

把这些文件放到  you_project\Resources 下面


ball.png 我贴在下面, 别的文件都可以在 cocos2d-2.1rc0-x-2.1.2/samples/Cpp/SimpleGame 下找到



生成程序

先用NDK ./build_native.sh 编译重新生成 libgame.so

而后在 eclipse 重新生成 .apk, 并安装到设备上



你现在得到一个自动四处碰撞但却会慢慢停下来的球, 同时会播放背景音乐


加入触摸互动

HelloWorldScene.h 加入

[cpp] view plaincopy
  1. class HelloWorld : public cocos2d::CCLayer {  
  2. ...  
  3.     void kick();   
  4.     void registerWithTouchDispatcher();  
  5.     void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);};  
  6. ...  
  7. }  


HelloWorldScene.cpp

[cpp] view plaincopy
  1. void HelloWorld::kick()   
  2. {  
  3.     b2Vec2 force = b2Vec2(30, 30);  
  4.     _body->ApplyLinearImpulse(force,_body->GetPosition());  
  5.       
  6. }  
  7.   
  8.   
  9. void HelloWorld::registerWithTouchDispatcher()  
  10. {  
  11.     // CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this,0,true);  
  12.     CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this,0);  
  13. }  
  14.   
  15. void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)  
  16. {  
  17.     // Choose one of the touches to work with  
  18.     CCTouch* touch = (CCTouch*)( touches->anyObject() );  
  19.     CCPoint location = touch->getLocation();  
  20.   
  21.     CCLog("++++++++after  x:%f, y:%f", location.x, location.y);  
  22.     kick();  
  23. }  

还要在  bool HelloWorld::init() enable touch

this->setTouchEnabled(true);


以后你每次触摸屏幕, 球将会强力弹一次.


最后你得到一个有音乐,有互动,画面平滑的简单游戏.
0 0
原创粉丝点击