Cocos2d-x 酷跑游戏例子

简介: <h2 style="margin:0px 0px 10px; padding:0px; background-color:transparent; font-family:Verdana,'Lucida Grande','Trebuchet MS',Arial,sans-serif; font-weight:500; font-size:1.8em"> <span id="1" sty

1. 效果图

 

 

可以拉到底部看下动态图,鼠标点击屏幕,主角会跳下,遇到间隙或碰上较高建筑就挂了。在空中如果点击鼠标,主角会撑起一把雨伞,会有缓慢降落效果。主角挂的时候,会有主角的帽子升上的动画,不知为什么这个简单的动画看起来是那么的有趣,点睛之笔。

 


2. cocos2d-x 中菜单的使用

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//add menu
     CCSprite * menuItemOn;
     CCSprite * menuItemOff;
     //菜单有两个状态,平时展示的样子和点击的样子
     menuItemOn = CCSprite::createWithSpriteFrameName( "btn_new_on.png" );
     menuItemOff = CCSprite::createWithSpriteFrameName( "btn_new_off.png" );
     //New Game 菜单
     CCMenuItemSprite * starGametItem = CCMenuItemSprite::create(
                                                                 menuItemOff,
                                                                 menuItemOn,
                                                                 this ,
                                                                 //这个最重要,点击菜单调用系统哪个方法
                                                                 menu_selector(GameLayer::startGame));
 
     menuItemOn = CCSprite::createWithSpriteFrameName( "btn_howto_on.png" );
     menuItemOff = CCSprite::createWithSpriteFrameName( "btn_howto_off.png" );
     //How to Play 菜单
     CCMenuItemSprite * howToItem = CCMenuItemSprite::create(
                                                             menuItemOff,
                                                             menuItemOn,
                                                             this ,
                                                             menu_selector(GameLayer::showTutorial));
 
     _mainMenu = CCMenu::create(howToItem, starGametItem, NULL); //创建菜单
     _mainMenu->alignItemsHorizontallyWithPadding(120); //设置两个菜单的水平间距
     _mainMenu->setPosition(ccp(_screenSize.width * 0.5f, _screenSize.height * 0.54));
 
     this ->addChild(_mainMenu, kForeground);

 

3.创建水平移动效果(Parallax)

 

 所谓酷跑游戏,很多时候你会发现主角的位置其实没动,动的都是背景,背景往左移,看起来主角就往右前进了,背景往后退,看起来主角就往前进了,所谓的相对运动。 

 

那么这游戏是如何实现的呢?非常简单。拿背景举例子。下面这代码会放在update函数里执行。

 

 

?
1
2
3
4
5
6
7
8
//背景一直往左移
         _background->setPositionX(_background->getPosition().x - _player->getVector().x * 0.25f);
         float diffx;
         //移完一个宽度时,重新把位置设置为接近0的位置
         if (_background->getPositionX() < -_background->getContentSize().width) {
             diffx = fabs (_background->getPositionX()) - _background->getContentSize().width;
             _background->setPositionX(-diffx);
         }

 

 

这种方式效率可能比较低,但这种是所有平台通用的方式。查看了Cocos2d-x的示例,发现了一个叫ParallaxTest的例子,是可以混合几种东西一起使用动画。下面是官方的例子。

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// create a void node, a parent node
    CCParallaxNode* voidNode = CCParallaxNode::create();
 
    // NOW add the 3 layers to the 'void' node
 
    // background image is moved at a ratio of 0.4x, 0.5y
    voidNode->addChild(background, -1, ccp(0.4f,0.5f), CCPointZero);
 
    // tiles are moved at a ratio of 2.2x, 1.0y
    voidNode->addChild(tilemap, 1, ccp(2.2f,1.0f), ccp(0,-200) );
 
    // top image is moved at a ratio of 3.0x, 2.5y
    voidNode->addChild(cocosImage, 2, ccp(3.0f,2.5f), ccp(200,800) );
 
    // now create some actions that will move the 'void' node
    // and the children of the 'void' node will move at different
    // speed, thus, simulation the 3D environment
    CCActionInterval* goUp = CCMoveBy::create(4, ccp(0,-500) );
    CCActionInterval* goDown = goUp->reverse();
    CCActionInterval* go = CCMoveBy::create(8, ccp(-1000,0) );
    CCActionInterval* goBack = go->reverse();
    CCSequence* seq = CCSequence::create(goUp, go, goDown, goBack, NULL);
    voidNode->runAction( (CCRepeatForever::create(seq) ));
 
    addChild( voidNode );

 


4. 如何随机?

 

 游戏有时候就是需要很多随机情况,看下主角脚下的房子,有不同的颜色,有不同的高度,宽度,房子之间的间隙也不一定地出现。可能随机数是一个解决方案,这里用了一个更加有趣的方案,给定几组数组,然后对这数组进行洗牌。用一个index对数组取数,到尾了再回到0,进行洗牌。这种方式我想了下可以更好的控制难度。下面是建筑物高度的例子。

?
1
2
3
4
5
6
7
8
9
10
int heights[] = {0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,2,2,2,3,3,3,3,3,3,4}; //可控制的难度,建筑物的高度
vector< int > _blockHeights (heights, heights + sizeof (heights) / sizeof ( int ));
random_shuffle(_blockHeights.begin(), _blockHeights.end()); //洗牌
int blockHeight = _blockHeights[_currentHeightIndex];
_currentHeightIndex++; //以后每次移动index来访问数组中每个元素。
 
    if (_currentHeightIndex == _blockHeights.size()) { //是数组最后一个元素是,回到第一个元素,重新洗牌
                 _currentHeightIndex = 0;
                 random_shuffle(_blockHeights.begin(), _blockHeights.end()); //重新洗牌              
   }

 


5.碰撞检测

 

 这没有用到box2d物理引擎,碰撞就需要自己来写了,非常简单,在游戏中主角只有跟下面的房子又碰撞,碰撞又只有分两种:

  1. 主角在上面随着重力加速度的存在,自由落体时,跟下面的房子相碰。
  2. 主角迎面碰上一个高的房子。

碰撞结果分两种:

  1. 主角掉下跟房子相碰时,不再往下降,房子看起来像一个实体。
  2. 主角迎面碰上一个高的房子时,主角产生一个向后退的效果。

主角是一个矩形,房子也是一个矩形,两种相碰就容易了。

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
for (i = 0; i < count; i++) {
 
         block = (Block *) _blocks->objectAtIndex(i);
         if (block->getType() == kBlockGap) continue ;
 
         //if within x, check y (bottom collision),检测上下碰撞
         if (player->right() >= this ->getPositionX() + block->left()
             && player->left() <= this ->getPositionX() + block->right()) {
 
             if (player->bottom() >= block->top() && player->next_bottom() <= block->top()
                 && player->top() > block->top()) {
                 player->setNextPosition(ccp(player->getNextPosition().x, block->top() + player->getHeight())); //碰撞完更改位置在block上面
                 player->setVector ( ccp(player->getVector().x, 0) ); //碰撞完没有Y轴上的加速度
                 player->setRotation(0.0);
                 inAir = false ;
                 break ;
             }
 
         }
     }
 
     for (i = 0; i < count; i++) {
         block = (Block *) _blocks->objectAtIndex(i);
         if (block->getType() == kBlockGap) continue ;
 
         //now if within y, check x (side collision)左右碰撞
         if ((player->bottom() < block->top() && player->top() > block->bottom())
             || (player->next_bottom() < block->top() && player->next_top() > block->bottom())) {
 
                 if (player->right() >= this ->getPositionX() + block->getPositionX()
                     && player->left() < this ->getPositionX() + block->getPositionX()) {
 
                         player->setPositionX( this ->getPositionX() + block->getPositionX() - player->getWidth() * 0.5f );
                         player->setNextPosition(ccp( this ->getPositionX() + block->getPositionX() - player->getWidth() * 0.5f, player->getNextPosition().y));
                         player->setVector ( ccp(player->getVector().x * -0.5f, player->getVector().y) );
                         if (player->bottom() + player->getHeight() * 0.2f < block->top()) {
                             player->setState(kPlayerDying);
                             return ;
 
                         }
 
                         break ;
                 }
         }
     }

 


6.动态图

 

7.代码下载(请用7z解压)

 

 http://www.waitingfy.com/?attachment_id=787

 


8.参考书目

《Cocos2d-X by Example Beginner’s Guide》

相关文章
|
JavaScript Android开发 C++
【Cocos2d-x】开发基础-第一个Cocos2d-x游戏
【Cocos2d-x】开发基础-第一个Cocos2d-x游戏
232 0
|
图形学
Unity 3D游戏-塔防类游戏源码:重要方法和功能的实现
Unity-塔防游戏源码 本文提供全流程,中文翻译。Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) ...
1921 0
|
前端开发 图形学
Unity 3D游戏-贪吃蛇类游戏源码:重要方法和功能的实现
贪吃蛇类游戏源码 本文提供全流程,中文翻译。Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) ...
2210 0
|
图形学
Unity 3D游戏-见缝插针源码
Unity见缝插针功能实现 本文提供全流程,中文翻译。Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) ...
1642 0