Android游戏开发十日通(6)- 太空大战

http://blog.csdn.net/silangquan/article/details/16921035

今天要学习的是coscos2d-x官网索引的一篇初级游戏教程。作为小白的入门,再适合不过了。

资源文件下载

工程源码下载

大师的源码

环境:

lubuntu 13.10 32bit  Android 4.1 cocos2d-x 2.2

下面就一步步来完成。

1.创建工程

创建项目 终端进入 cocos2d-x-2.2/tools/project-creator/ ,执行 ./create_project.py -project SpaceGame -package com.maclab.SpaceGame -language cpp 在 /cocos2d-x-2.2/projects/SpaceGame 中就有创建好的各平台的工程模板。 修改proj.android 下build_native.sh,添加一行指定NDK_ROOT 在eclipse中导入proj.android 工程,记得不要勾Copy to Project into workspace. 如果之前未将 /cocos2d-x-2.2/cocos2dx/platform/android/java 导入,在这里要导入。 创建软链接,终端进入 pro.android,执行命令: ln -s ../Resources ./Resources

在Eclipse中刷新工程,Resources文件夹就出现了。

换一个狂拽酷炫点的图标

将android工程中res文件夹下的icon.png换成这个就可以了。

在项目上右击,run as->android application 一切顺利的话工程就创建好了,如果没法运行,检查cocos2dx是否配置好。

2.拷贝资源文件

将下载好的资源文件挨个拷贝到Resources文件夹中,注意Classes 文件夹不要拷贝,fonts文件夹合并就好。

3.添加一个小飞机 

先将HelloWorldScence.cpp中的

USING_NS_CC;

移动到HelloWorldScence.h中,这样定义成员的时候就不用老加上命名空间了。

首先在HelloWorld.h中添加两个成员:

[html] view plaincopy

  1. private:  
  2.     CCSpriteBatchNode* batchNode;  
  3.     CCSprite* ship;  

然后在init的时候初始化这俩个成员:

[cpp] view plaincopy

  1. batchNode = CCSpriteBatchNode::create("Spritesheets/Sprites.pvr.ccz");  
  2. this->addChild(batchNode);  
  3.    CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("Spritesheets/Sprites.plist");  
  4.    ship = CCSprite::createWithSpriteFrameName("SpaceFlier_sm_1.png");  
  5.    ship->setPosition(ccp(origin.x + visibleSize.width * 0.1,  
  6.                            origin.y + visibleSize.height * 0.5));  
  7.    batchNode->addChild(ship,1);  

分别编译linux版本和android 版本 ,效果如下:

4.添加卷轴滚动的背景

在头文件中继续添加几个相关的private成员:

[cpp] view plaincopy

  1. CCParallaxNode *backgroundNode;    
  2. CCSprite *spacedust1;  
  3. CCSprite *spacedust2;  
  4. CCSprite *planetsunrise;  
  5. CCSprite *galaxy;  
  6. CCSprite *spacialanomaly;  
  7. CCSprite *spacialanomaly2;  

还是在init() 中对它们进行初始化,把整个场景搭建起来:

这里用到了CCParallaxNode类,用它来实现背景,可以加强背景的层次感,在进行背景卷动的时候,可以实现越近的背景卷动得越快,越远越慢。(想想在火车上 向外看窗外的景色)

[cpp] view plaincopy

 // 1) Create the CCParallaxNode 
  backgroundNode = CCParallaxNode::create();  
  this->addChild(backgroundNode, -1);  
  
  // 2) Create the sprites will be added to the CCParallaxNode 
  spacedust1 = CCSprite::create("Backgrounds/bg_front_spacedust.png");  
  spacedust2 = CCSprite::create("Backgrounds/bg_front_spacedust.png");  
  planetsunrise = CCSprite::create("Backgrounds/bg_planetsunrise.png");  
  galaxy = CCSprite::create("Backgrounds/bg_galaxy.png");  
  spacialanomaly = CCSprite::create("Backgrounds/bg_spacialanomaly.png");  
  spacialanomaly2 = CCSprite::create("Backgrounds/bg_spacialanomaly2.png");  
  
  // 3) Determine relative movement speeds for space dust and background 
  CCPoint dustSpeed = ccp(0.1, 0.1);  
  CCPoint bgSpeed = ccp(0.05, 0.05);  
  
  // 4) Add children to CCParallaxNode 
  backgroundNode->addChild(spacedust1, 0, dustSpeed, ccp(0,visibleSize.height/2) ); // 2 
  backgroundNode->addChild(spacedust2, 0, dustSpeed, ccp( spacedust1->getContentSize().width,visibleSize.height/2));  
  backgroundNode->addChild(galaxy, -1, bgSpeed, ccp(0, visibleSize.height * 0.7));  
  backgroundNode->addChild(planetsunrise, -1 , bgSpeed, ccp(600, visibleSize.height * 0));  
  backgroundNode->addChild(spacialanomaly, -1, bgSpeed, ccp(900, visibleSize.height * 0.3));  
  backgroundNode->addChild(spacialanomaly2, -1, bgSpeed, ccp(1500, visibleSize.height * 0.9));  

编译运行之后的效果:

5.卷动背景

原理就是每一Frame将背景向后移动一定的距离,也就是背景图片以一定的速度运动。

在头文件中添加update函数,将其声明为似有成员函数,这个函数是会自动调用的。

[cpp] view plaincopy

 private:  
  // scheduled Update  
  void update(float dt);  
 
 函数实现如下: 

[cpp] view plaincopy

 void HelloWorld::update(float dt)  
 {  
     CCPoint backgroundScrollVert = ccp(-1000,0);  
     backgroundNode->setPosition(ccpAdd(backgroundNode->getPosition(), ccpMult(backgroundScrollVert, dt)));  
 }  

在init()中添加一句

[cpp] view plaincopy

  1. this->scheduleUpdate();  

这样背景就会不断地往后走,造成飞机在往前飞的假象,但有个问题,背景跑一会儿之后就不见了,因为没有循环显示。

而CCParallaxNode也没有对应的循环的方法,这里就要自定义类了。这里自定义一个CCParallaxNodeExtras类,继承 CCParallaxNode。主要是添加一个 incrementOffset() 方法,用户实现循环显示。

CCParallaxNodeExtras.h

[cpp] view plaincopy

 #ifndef Cocos2DxFirstIosSample_CCParallaxNodeExtras_h 
 #define Cocos2DxFirstIosSample_CCParallaxNodeExtras_h 
  
 #include "cocos2d.h" 
  
 USING_NS_CC;  
  
 class CCParallaxNodeExtras : public CCParallaxNode {  
  
  public :  
  
  // Need to provide a constructor  
     CCParallaxNodeExtras();  
  
  // just to avoid ugly later cast and also for safety 
  static CCParallaxNodeExtras * node();  
  
  // Facility method (it’s expected to have it soon in COCOS2DX)     
  void incrementOffset(CCPoint offset, CCNode* node);    
 } ;   
  
 #endif 

CCParallaxNodeExtras.cpp

[cpp] view plaincopy

  1. #include "CCParallaxNodeExtras.h" 
  2. // Hack to access CCPointObject (which is not a public class)
  3. class CCPointObject  : CCObject {  
  4.     CC_SYNTHESIZE(CCPoint, m_tRatio, Ratio)  
  5.     CC_SYNTHESIZE(CCPoint, m_tOffset, Offset)  
  6.     CC_SYNTHESIZE(CCNode *, m_pChild, Child)    // weak ref
  7. };  
  8. // Need to provide a constructor 
  9. CCParallaxNodeExtras::CCParallaxNodeExtras() {  
  10.     CCParallaxNode(); // call parent constructor
  11. }  
  12. CCParallaxNodeExtras * CCParallaxNodeExtras::node() {  
  13. return new CCParallaxNodeExtras();         
  14. }  
  15. void CCParallaxNodeExtras::incrementOffset(CCPoint offset,CCNode* node){  
  16. for( unsigned int i = 0; i < m_pParallaxArray->num; i++) {  
  17.         CCPointObject *point = (CCPointObject *)m_pParallaxArray->arr[i];  
  18.         CCNode * curNode = point->getChild();  
  19. if( curNode->isEqual(node) ) {  
  20.             point->setOffset( ccpAdd(point->getOffset(), offset) );  
  21. break;  
  22.         }  
  23.     }  
  24. }  

在这里还定义了一个内部类CCPointObject,关于CC_SYNTHESIZEz这个宏

[cpp] view plaincopy

  1. #define CC_PROPERTY(varType, varName, funName)\ 
  2. protected: varType varName;\   
  3. publicvirtual varType get##funName(void);\   
  4. publicvirtual void set##funName(varType var);  

incrementOffset函数的作用就是将子node移动一个偏移量。

对原HelloWorldScence.cpp进行一定的修改,首先backgroundNode的声明要修改:

[cpp] view plaincopy

  1. CCParallaxNodeExtras *backgroundNode;    

其初始化变为

[cpp] view plaincopy

  1. backgroundNode = CCParallaxNodeExtras::node();  

在update()的最后添加下面的代码作为检测,

[cpp] view plaincopy

 CCArray *spaceDusts = CCArray::arrayWithCapacity(2) ;  
 spaceDusts->addObject(_spacedust1) ;  
 spaceDusts->addObject(_spacedust2) ;  
 for ( int ii = 0  ; ii <spaceDusts->count() ; ii++ ) {  
     CCSprite * spaceDust = (CCSprite *)(spaceDusts->objectAtIndex(ii)) ;  
  float xPosition = _backgroundNode->convertToWorldSpace(spaceDust->getPosition()).x  ;  
  float size = spaceDust->getContentSize().width ;  
  if ( xPosition < -size ) {  
         _backgroundNode->incrementOffset(ccp(spaceDust->getContentSize().width*2,0),spaceDust) ;   
     }                                     
 }  
  
 CCArray *backGrounds = CCArray::arrayWithCapacity(4) ;  
 backGrounds->addObject(_galaxy) ;  
 backGrounds->addObject(_planetsunrise) ;  
 backGrounds->addObject(_spacialanomaly) ;  
 backGrounds->addObject(_spacialanomaly2) ;  
 for ( int ii = 0 ; ii <backGrounds->count() ; ii++ ) {  
     CCSprite * background = (CCSprite *)(backGrounds->objectAtIndex(ii)) ;  
  float xPosition = _backgroundNode->convertToWorldSpace(background->getPosition()).x ;  
  float size = background->getContentSize().width ;  
  if ( xPosition < -size ) {  
         _backgroundNode->incrementOffset(ccp(2000,0),background) ;   
     }  
 }  

修改proj.linux/MakeFile,将新添加的 cpp 索引进来。

[cpp] view plaincopy

  1. SOURCES = main.cpp \  
  2.         ../Classes/AppDelegate.cpp \  
  3.         ../Classes/HelloWorldScene.cpp\  
  4.         ../Classes/CCParallaxNodeExtras.cpp  

编译运行

android版本的编译需要修改proj.android/jni/Android.mk

[cpp] view plaincopy

  1. LOCAL_SRC_FILES := hellocpp/main.cpp \  
  2.                    ../../Classes/AppDelegate.cpp \  
  3.                    ../../Classes/HelloWorldScene.cpp\  
  4.               ../../Classes/CCParallaxNodeExtras.cpp  

5.夜空中最亮的星

我们还可以在场景中添加一些星空的效果,可以用内置的粒子系统来实现,在init() 的后面添加下面的语句:

[cpp] view plaincopy

  1. //Add some stars
  2.     HelloWorld::addChild(CCParticleSystemQuad::create("Particles/Stars1.plist"));  
  3.     HelloWorld::addChild(CCParticleSystemQuad::create("Particles/Stars2.plist"));  
  4.     HelloWorld::addChild(CCParticleSystemQuad::create("Particles/Stars3.plist"));  

编译后运行

6.控制小飞机

这里用到了移动设备的重力传感器。cocos2d-x对加速计进行了封装,我们可以不用关心具体平台api,直接使用抽象后的加速计api就可以了。

首先是要实现基类的关于传感器的虚函数,在头文件中添加:

[cpp] view plaincopy

  1. virtual void didAccelerate(CCAcceleration* pAccelerationValue);  

然后在cpp中添加其实现:

[cpp] view plaincopy

 void HelloWorld::didAccelerate(CCAcceleration* pAccelerationValue) {  
   #define KFILTERINGFACTOR 0.1 
   #define KRESTACCELX -0.6      
   #define KMAXDIFFY 0.2 
   #define KMAXDIFFX 0.1 
  
  double rollingX = 0.0;  
  double rollingY = 0.0;  
  
  // Cocos2DX inverts X and Y accelerometer depending on device orientation 
  // in landscape mode right x=-y and y=x !!! (Strange and confusing choice) 
  //exchange value 
  float tmp;  
   tmp = pAccelerationValue->x;  
   pAccelerationValue->x = pAccelerationValue->y;  
   pAccelerationValue->y = tmp;  
  
   rollingX = (pAccelerationValue->x * KFILTERINGFACTOR);  
   rollingY = (pAccelerationValue->y * KFILTERINGFACTOR);  
  float accelX = pAccelerationValue->x - rollingX;  
  float accelY = pAccelerationValue->y - rollingY;  
   CCSize winSize = CCDirector::sharedDirector()->getWinSize();  
  float accelDiffx = accelX - KRESTACCELX;  
  float accelDiffy = accelY;  
  float accelFractionx = accelDiffx / KMAXDIFFX;  
  float accelFractiony = accelDiffy / KMAXDIFFY;  
   shipPointsPerSecY = 0.5 * winSize.height * accelFractionx;  
   shipPointsPerSecX = 0.5 * winSize.width * accelFractiony;  
 }  

这个函数在每次检测到传感器的信息之后就会回调,传回一个CCAcceleration对象,这里只要x方向的值就可以了。注意这里还对传感器的值进行了一定的处理,让小飞机有一种飞行的感觉,同时速度是和屏幕大小对应的,算是多设备匹配的一个trick。

接下来在update() 中更行飞船的位置,在后面添加下面的代码:

[cpp] view plaincopy

  1. CCSize winSize = CCDirector::sharedDirector()->getWinSize();  
  2. float maxY = winSize.height - ship->getContentSize().height/2;  
  3. float minY = ship->getContentSize().height/2;  
  4. float maxX = winSize.width - ship->getContentSize().width/2;  
  5. float minX = ship->getContentSize().width/2;  
  6. float diffy = (shipPointsPerSecY * dt);  
  7. float diffx = (shipPointsPerSecX * dt);  
  8. float newY = ship->getPosition().y + diffy;  
  9. float newX = ship->getPosition().x + diffx;  
  10. newY = MIN(MAX(newY, minY), maxY);  
  11. newX = MIN(MAX(newX, minX), maxX);  
  12. ship->setPosition(ccp(newX, newY));  

最后就是启动传感器的检测了,在init()中添加:

[cpp] view plaincopy

  1. this->setAccelerometerEnabled(true);   这个功能只能在真机中测试。

7.添加小行星

在HelloWorld.h中添加几个私有成员变量,

[cpp] view plaincopy

  1. CCArray* asteroids;  
  2. int nextAsteroid;  
  3. float nextAsteroidSpawn;  

第一个用来存储小行星,第二个用来索引,第三个用来记录小行星出现的间隔时间。

添加几个public辅助函数:

[cpp] view plaincopy

 //For get random float value 
 float randomValueBetween(float low, float high);  
  
 //Set visibility of Node 
 void setInvisible(CCNode * node);  
  
 //Get millisecs current sys-time 
 float getTimeTick();  

在init()中对成员进行初始化:

[cpp] view plaincopy

 //init asteroids 
 asteroids = new CCArray();  
 //Store asteroids 
 for(int i = 0; i < 15; ++i) {  
     CCSprite *asteroid = CCSprite::createWithSpriteFrameName("asteroid.png");  
     asteroid->setVisible(false);  
     batchNode->addChild(asteroid);  
     asteroids->addObject(asteroid);  
 }  
 nextAsteroid = 0;  
 nextAsteroidSpawn = 0.0;  

接下来是函数的实现,都比较简单。

[cpp] view plaincopy

 float HelloWorld::randomValueBetween(float low, float high) {  
  return (((float) 2 * rand() / 0xFFFFFFFFu) * (high - low)) + low;  
 }  
  
 float HelloWorld::getTimeTick() {  
     timeval time;  
     gettimeofday(&time, NULL);  
     unsigned long millisecs = (time.tv_sec * 1000) + (time.tv_usec/1000);  
  return (float) millisecs;  
 }  
  
  
  
 void HelloWorld::setInvisible(CCNode * node) {  
     node->setVisible(false);  
 }  

最后在update()中更新小行星:

[cpp] view plaincopy

 //Set asteroids 
 float curTimeMillis = getTimeTick();  
 if (curTimeMillis > nextAsteroidSpawn) {  
  
  float randMillisecs = randomValueBetween(0.20,1.0) * 1000;  
     nextAsteroidSpawn = randMillisecs + curTimeMillis;  
  
  float randY = randomValueBetween(0.0,winSize.height);  
  float randDuration = randomValueBetween(2.0,10.0);  
  
     CCSprite *asteroid = (CCSprite *)asteroids->objectAtIndex(nextAsteroid);  
     nextAsteroid++;  
  
  if (nextAsteroid >= (int)asteroids->count())  
         nextAsteroid = 0;  
  
     asteroid->stopAllActions();  
     asteroid->setPosition( ccp(winSize.width+asteroid->getContentSize().width/2, randY));  
     asteroid->setVisible(true);  
     asteroid->runAction(CCSequence::create(CCMoveBy::create(randDuration, ccp(-winSize.width-asteroid->getContentSize().width, 0)), CCCallFuncN::create(this, callfuncN_selector(HelloWorld::setInvisible)), NULL // DO NOT FORGET TO TERMINATE WITH NULL (unexpected in C++) 
      ));  
 }  

编译运行。

8.发射激光

和小行星的添加类似,首先修改头文件

[cpp] view plaincopy

  1. CCArray* shipLasers;  
  2. int nextShipLaser;  

在init中初始化:

[cpp] view plaincopy

 //init lasers 
    shipLasers = new CCArray();  
  for(int i = 0; i < 5; ++i)  
    {  
        CCSprite *shipLaser = CCSprite::createWithSpriteFrameName("laserbeam_blue.png");  
        shipLaser->setVisible(false);  
        batchNode->addChild(shipLaser);  
        shipLasers->addObject(shipLaser);  
    }  
  this->setTouchEnabled(true);  
    nextShipLaser = 0;  

9.简单的碰撞检测

这里的碰撞检测包括两个部分:激光和小行星的碰撞,飞机和小行星的碰撞。

首先添加一个私有成员,用于记录飞机的生命值。

[cpp] view plaincopy

  1. int  lives;  

在init()添加对其的初始化:

[cpp] view plaincopy

  1. lives = 3;  

在update()中添加检测的操作:

[cpp] view plaincopy

 //Collision Detection 
  //Asteroids 
  CCObject* asteroid;  
  CCObject* shipLaser;  
  CCARRAY_FOREACH(asteroids, asteroid){  
  if (!((CCSprite *) asteroid)->isVisible() )  
  continue;  
      CCARRAY_FOREACH(shipLasers, shipLaser){  
  if (!((CCSprite *) shipLaser)->isVisible())  
  continue;  
  if (((CCSprite *) shipLaser)->boundingBox().intersectsRect(((CCSprite *)asteroid)->boundingBox()) ) {  
              ((CCSprite *)shipLaser)->setVisible(false);  
              ((CCSprite *)asteroid)->setVisible(false);  
  continue;  
          }  
      }  
  if (ship->boundingBox().intersectsRect(((CCSprite *)asteroid)->boundingBox()) ) {  
          ((CCSprite *)asteroid)->setVisible(false);  
          ship->runAction( CCBlink::create(1.0, 9));  
          lives--;  
      }  
  }  

运行的效果是子弹或者飞船碰到小行星,小行星都会消失,飞船的话会闪动。

10.终止游戏

理论上当飞机生命没有的时候,游戏就要结束了。

这里游戏的胜利条件是坚持了60s,失败条件是飞机被撞击了三次。

添加一个枚举声明,表示游戏结束的原因:

[cpp] view plaincopy

  1. typedef enum {  
  2.   WIN,  
  3.   LOSE  
  4. } EndReason;  

添加私有成员:

[cpp] view plaincopy

  1. double gameOverTime;  
  2. bool gameOver;  

还有两个相关的public 方法:

[cpp] view plaincopy

  1. //Called when game ended
  2. void endScene(EndReason endReason);  
  3. //Restart game
  4. void restartTapped();  

实现如下:

[cpp] view plaincopy

 void HelloWorld::restartTapped() {  
     CCDirector::sharedDirector()->replaceScene  
     (CCTransitionZoomFlipX::create(0.5, this->scene()));  
  // reschedule 
  this->scheduleUpdate();  
 }  
  
 void HelloWorld::endScene( EndReason endReason ) {  
  if (gameOver)  
  return;  
     gameOver = true;  
  
     CCSize winSize = CCDirector::sharedDirector()->getWinSize();  
  char message[10] = "You Win";  
  if ( endReason == LOSE)  
         strcpy(message,"You Lose");  
     CCLabelBMFont * label ;  
     label = CCLabelBMFont::create(message, "fonts/Arial.fnt");  
     label->setScale(0.1);  
     label->setPosition(ccp(winSize.width/2 , winSize.height*0.6));  
  this->addChild(label);  
  
     CCLabelBMFont * restartLabel;  
     strcpy(message,"Restart");  
     restartLabel = CCLabelBMFont::create(message, "fonts/Arial.fnt");  
     CCMenuItemLabel *restartItem = CCMenuItemLabel::create(restartLabel, this, menu_selector(HelloWorld::restartTapped) );  
     restartItem->setScale(0.1);  
     restartItem->setPosition( ccp(winSize.width/2, winSize.height*0.4));  
  
     CCMenu *menu = CCMenu::create(restartItem, NULL);  
     menu->setPosition(CCPointZero);  
  this->addChild(menu);  
  
  // clear label and menu 
     restartItem->runAction(CCScaleTo::create(0.5, 1.0));  
     label ->runAction(CCScaleTo::create(0.5, 1.0));  
  // Terminate update callback 
  this->unscheduleUpdate();  
 }  

当游戏结束的时候,调用endScence方法现实结束提示的文字和按钮,可以选择重新再来,调用restartTapped.

运行效果如下:

11.来点音效

游戏中的音效可以为游戏添色不少。

首先将苹果的caf格式转换成android支持的wav.终端cd到工程目录下的 Resources/Sounds ,执行下面的命令(事先装好ffmpeg)

ffmpeg -i SpaceGame.caf SpaceGame.wav ffmpeg -i explosion_large.caf explosion_large.wav ffmpeg -i  laser_ship.caf laser_ship.wav

顺利的话Sounds文件夹下面就生成了转好码的音频文件了。

在HelloWorld.h 中添加头文件和命名空间:

[cpp] view plaincopy

  1. #include "SimpleAudioEngine.h"
  2. using namespace CocosDenshion;  

在init() 中加入对音效的初始化,这里播放背景乐,同时预加载小行星爆炸的音效和发射激光的音效。

[cpp] view plaincopy

  1. SimpleAudioEngine::sharedEngine()->playBackgroundMusic("SpaceGame.wav",true);  
  2. SimpleAudioEngine::sharedEngine()->preloadEffect("explosion_large.wav");  
  3. SimpleAudioEngine::sharedEngine()->preloadEffect("laser_ship.wav");  

在碰撞检测中对应位置加入

[cpp] view plaincopy

  1. SimpleAudioEngine::sharedEngine()->playEffect("Sounds/explosion_large.wav");  

播放爆炸的声音。

在触摸函数中添加

[cpp] view plaincopy

  1. SimpleAudioEngine::sharedEngine()->playEffect("Sounds/laser_ship.wav");  

播放发射激光的声音。

发现linux版本不能正常编译,报错:

fatal error: SimpleAudioEngine.h: No such file or directory compilation terminated.

修改proj.linux/MakeFile

[plain] view plaincopy

  1. EXECUTABLE = SpaceGame  
  2. INCLUDES = -I.. -I../Classes \  
  3.                 -I$(COCOS_ROOT)/CocosDenshion/include  
  4. SOURCES = main.cpp \  
  5.         ../Classes/AppDelegate.cpp \  
  6.         ../Classes/HelloWorldScene.cpp\  
  7.         ../Classes/CCParallaxNodeExtras.cpp  
  8. COCOS_ROOT = ../../..  
  9. include $(COCOS_ROOT)/cocos2dx/proj.linux/cocos2dx.mk  
  10. SHAREDLIBS += -lcocos2d -lcocosdenshion  
  11. COCOS_LIBS = $(LIB_DIR)/libcocos2d.so  
  12. $(TARGET): $(OBJECTS) $(STATICLIBS) $(COCOS_LIBS) $(CORE_MAKEFILE_LIST)  
  13.     @mkdir -p $(@D)  
  14.     $(LOG_LINK)$(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ $(SHAREDLIBS) $(STATICLIBS)  
  15. $(OBJ_DIR)/%.o: %.cpp $(CORE_MAKEFILE_LIST)  
  16.     @mkdir -p $(@D)  
  17.     $(LOG_CXX)$(CXX) $(CXXFLAGS) $(INCLUDES) $(DEFINES) $(VISIBILITY) -c $< -o $@  
  18. $(OBJ_DIR)/%.o: ../%.cpp $(CORE_MAKEFILE_LIST)  
  19.     @mkdir -p $(@D)  
  20.     $(LOG_CXX)$(CXX) $(CXXFLAGS) $(INCLUDES) $(DEFINES) $(VISIBILITY) -c $< -o $@  

主要是搜索路径和库的链接。然后linux版本就可以编译了。

android版本直接编译运行即可。

到此为止,已经基本完成了一个声色俱全的移动平台游戏了~

To be continue

可以做的还有很多,比如

1.给飞机添加血量的显示;

2.添加爆炸的动画;

3.添加敌机;

4.遭遇大boss

...

参考

Cocos2D-X Tutorial for iOS and Android: Space Game

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏GIS讲堂

Openlayers2中统计图的实现

在前文中,介绍了Arcgis for js和Openlayers3中统计图的实现,在本文,书接上文,介绍在Openlayers2中,统计图的实现。

1233
来自专栏PPV课数据科学社区

【学习】七天搞定SAS(一):数据的导入、数据结构

标题有些噱头,不过这里的重点是: speak SAS in 7days。也就是说,知识是现成的,我这里只是要学会如何讲这门语言,而不是如何边学SAS边学模型。顺...

2855
来自专栏Hongten

pygame系列_箭刺Elephant游戏_源码下载

http://www.pygame.org/docs/tut/chimp/ChimpLineByLine.html

1344
来自专栏杨建荣的学习笔记

10g升级至11g需要考虑的参数优化(29天)

10g升级至11g除了需要做一个详尽的计划, 需要采集10g系统的负载情况,做一个整体的把握,在升级之后,再做负载分析。 保证不会出现大的问题,sql的执行计划...

3475
来自专栏施炯的IoT开发专栏

//build->//learn->//publish

在今年的Build大会上,微软发布了Windows Phone 8.1,以及universal Windows apps开发策略。在接下来的两个月中,会有两个全...

19810
来自专栏菩提树下的杨过

ExtJs学习笔记(3)_GridPanel[XML做数据源]

这一节,将学习到除了用JSON做GridPanel的数据源外,还可以使用XML 一。静态示例 1.xml文件内容: <?xml version="1.0...

2188
来自专栏转载gongluck的CSDN博客

拉丁猪文字游戏

拉丁猪文字游戏——这是一个英语语言游戏。基本规则是将一个英语单词的第一个辅音音素的字母移动到词尾并且加上后缀-ay(譬如“banana”会变成“anana-ba...

40310
来自专栏菩提树下的杨过

Silverlight Telerik控件学习:GridView双向绑定

做过WinForm数据库开发的人,一定有类似经历:DataGrid绑定后,如果允许行编辑,数据一顿修改后,想批量保存修改后的结果,通常是将DataGrid的所有...

2235
来自专栏ascii0x03的安全笔记

IE的BHO通过IHTMLDocument2接口获得网页源代码

参考了凤之焚的专栏:http://blog.csdn.net/lion_wing/article/details/769742 但是他的源码有些问题,即IHTM...

3405
来自专栏数据结构与算法

BZOJ3262: 陌上花开(cdq分治)

第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。

1252

扫码关注云+社区