zoukankan      html  css  js  c++  java
  • cocos2d3.0跑酷代码讲解和源码

    最近在网上看到一个跑酷代码的例子,写的很不错,连接如下

    http://www.waitingfy.com/archives/783

    现在我把他精简了一下,去除了一些比较简单的特效,着重保留了主角的跳跃动作,墙壁的循环展示,碰撞检测

    我写了一个cocos2d3.0 c++版本和cocos2d-lua版本,具体的原理可以参考一下代码,因为只是精简版,代码可能有些不足,希望大家多多指正

     源码地址:

    http://files.cnblogs.com/files/xiaonanxia/RunSource_cppAndlua.zip

    原文的相关内容如下:

     


    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.动态图

  • 相关阅读:
    2014年3月新鲜出炉的最佳 JavaScript 工具库
    开发者不容错过的10款免费JavaScript游戏引擎
    创建Android环境并且安装cordova
    程序员技术练级攻略
    android sdk更新后出现please update ADT to the latest version的解决方法
    Linux cscope命令
    UltraISO制作系统ISO镜像
    Windows Live Writer 使用指南
    C语言访问网页
    Linux minicom命令
  • 原文地址:https://www.cnblogs.com/xiaonanxia/p/4959023.html
Copyright © 2011-2022 走看看