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

  • 相关阅读:
    使用 yo 命令行向导给 SAP UI5 应用添加一个新的视图
    SAP Fiori Elements 应用的 manifest.json 文件运行时如何被解析的
    SAP UI5 标准应用的多语言支持
    微软 Excel 365 里如何设置下拉菜单和自动高亮成指定颜色
    SAP Fiori Elements 应用里的 Title 显示的内容是从哪里来的
    本地开发好的 SAP Fiori Elements 应用,如何部署到 ABAP 服务器上?
    如何在 Cypress 测试代码中屏蔽(Suppress)来自应用代码报出的错误消息
    教你一招:让集群慢节点无处可藏
    应用架构步入“无服务器”时代 Serverless技术迎来新发展
    MySQL数据库事务隔离性的实现
  • 原文地址:https://www.cnblogs.com/xiaonanxia/p/4959023.html
Copyright © 2011-2022 走看看