• 《入门级-Cocos2dx4.0 塔防游戏开发》---第十课:游戏中餐单设置


    目录

     一、开发环境

    二、开发内容

    2.1 添加新资源

    2.2 添加游戏餐单层

    三、演示效果

    四、知识点

    4.1 ProgressTimer工具

    4.2 setSwallowTouches


     一、开发环境

    操作系统:UOS1060专业版本。

    cocos2dx:版本4.0

    环境搭建教程:统信UOS下配置安装cocos2dx开发环境

    本课主要内容:

    1. 在游戏过程中的各种道具显示
    2. 在游戏过程中各种信息显示(通关数、剩余血量、金币数量等)

    文章地址:https://arv000.blog.csdn.net/article/details/132736243

    二、开发内容

             开发设计思路如下,我们将游戏界面分为两个主要部分,游戏菜单部分、游戏部分。游戏菜单部分无论在那一关卡几乎不变,因此可以抽象在一个layer里面进行处理,那么不通过的关卡都能复用这个菜单界面就可以了。菜单部分需要分为两节课来讲解,这节课主要内容还是进行布局。以及每个按钮的监听内容方便后面处理,并且后面的课程中会讲解的按钮逻辑。

    2.1 添加新资源

    • 添加资源

    需要添加新资源的内容,因此需要添加新的plist文件到游戏中。在Scene/LoadingScene.cpp文件中的LoadingScene::loadSource()函数中,添加以下代码用来加载新的资源:

    SpriteFrameCache::getInstance()->addSpriteFramesWithFile("ingame_gui-hd.plist");
    
    • 添加跳转游戏场景代码

          上一节课,学习了如何新建游戏难度选择,当用户点击“进入游戏”时需要跳跳转到游戏场景。在ChooseDifficultyScene.cpp文件中找到sprite_start_mode精灵给精灵添加按钮响应函数ChooseDifficultyScene::touchPlayGame。

    1. auto sprite_start_mode = MenuItemSprite::create(Sprite::createWithSpriteFrameName("levelSelect_startMode_0001.png"),
    2. Sprite::createWithSpriteFrameName("levelSelect_startMode_0002.png"),
    3. CC_CALLBACK_1(ChooseDifficultyScene::touchPlayGame,this));

    ChooseDifficultyScene::touchPlayGame内容如下:

    获取当前选中的游戏难度并且,跳转到游戏场景中。

    1. void ChooseDifficultyScene::touchPlayGame(Ref *pSpender)
    2. {
    3. Director::getInstance()->replaceScene(GameScene::createGameScene(getLevel(),getDifficulty()));
    4. }
    • 游戏场景添加

    新建文件Scene/GameScene.cpp、Scene/GameScene.h,这里只是添加了游戏菜单层所以在游戏场景中代码比较简单。

    GameScene.cpp内容如下:

    1. #include "GameScene.h"
    2. #include "../Layer/PlayerStateMenuLayer.h"
    3. Scene *GameScene::createGameScene(int level, int difficulty)
    4. {
    5. auto scene = new GameScene();
    6. if(scene && scene->initGame(level,difficulty)){
    7. scene->autorelease();
    8. return scene;
    9. }
    10. CC_SAFE_FREE(scene);
    11. return nullptr;
    12. }
    13. bool GameScene::initGame(int level, int difficulty)
    14. {
    15. auto playerStateMenuLayer = PlayerStateMenuLayer::create();
    16. addChild(playerStateMenuLayer);
    17. return true;
    18. }

    GameScene.h内容如下:

    1. #ifndef __SCENE_GAME_SCENE_H__
    2. #define __SCENE_GAME_SCENE_H__
    3. #include "cocos2d.h"
    4. USING_NS_CC;
    5. class GameScene : public Scene
    6. {
    7. public:
    8. static Scene *createGameScene(int level,int difficulty);
    9. private:
    10. virtual bool initGame(int level,int difficulty);
    11. };
    12. #endif // __SCENE_GAME_SCENE_H__

    2.2 添加游戏餐单层

            游戏菜单中包括很多共性内容例如:生命值、金币、怪物波数、扩展功能雷石、扩展功能伞扩展功能锦囊(六侠)。

                    新建文件Layer/PlayerStateMenuLayer.cpp、Layer/PlayerStateMenuLayer.h

    Layer/PlayerStateMenuLayer.cpp文件内容:

    1. #include "PlayerStateMenuLayer.h"
    2. bool PlayerStateMenuLayer::init()
    3. {
    4. if( !Layer::init() ){
    5. return false;
    6. }
    7. win_size_ = Director::getInstance()->getWinSize();
    8. initSprite();
    9. initEvent();
    10. return true;
    11. }
    12. void PlayerStateMenuLayer::initSprite()
    13. {
    14. // 显示 生命值,金币,怪物波数的背景
    15. sprite_state_ = Sprite::createWithSpriteFrameName("hud_background.png");
    16. sprite_state_->setAnchorPoint(Point(0,1));
    17. sprite_state_->setPosition(Point(20,win_size_.height - 20 + 100));
    18. addChild(sprite_state_);
    19. // 生命值
    20. label_life_ = Label::createWithTTF("0","fonts/arial.ttf",20);
    21. label_life_->setPosition(Point(sprite_state_->getContentSize().width*0.25,sprite_state_->getContentSize().height*0.75));
    22. sprite_state_->addChild(label_life_);
    23. // 金币值
    24. label_gold_ = Label::createWithTTF("0","fonts/arial.ttf",20);
    25. label_gold_->setPosition(Point(sprite_state_->getContentSize().width*0.75,sprite_state_->getContentSize().height*0.75));
    26. sprite_state_->addChild(label_gold_);
    27. // 当前怪物波数
    28. label_wave_ = Label::createWithTTF("0","fonts/arial.ttf",20);
    29. label_wave_->setPosition(Point(sprite_state_->getContentSize().width*0.5,sprite_state_->getContentSize().height*0.25));
    30. sprite_state_->addChild(label_wave_);
    31. // 暂停按钮
    32. sprite_pause_ = Sprite::createWithSpriteFrameName("hud_buttons_0001.png");
    33. sprite_pause_->setAnchorPoint(Point(1,1));
    34. sprite_pause_->setPosition(Point(win_size_.width -20,win_size_.height - 20 + 100));
    35. addChild(sprite_pause_);
    36. // // 拓展功能:雷石
    37. sprite_thunder_stone_ = Sprite::createWithSpriteFrameName("power_portrait_fireball_0001.png");
    38. sprite_thunder_stone_->setAnchorPoint(Point(0,0));
    39. sprite_thunder_stone_->setPosition(Point(10,-20));
    40. sprite_thunder_stone_->setName("inactive");
    41. addChild(sprite_thunder_stone_,1);
    42. // 拓展功能:伞兵
    43. sprite_paratrooper_ = Sprite::createWithSpriteFrameName("power_portrait_reinforcement_0001.png");
    44. sprite_paratrooper_->setAnchorPoint(Point(0,0));
    45. sprite_paratrooper_->setPosition(Point(120,-20));
    46. sprite_paratrooper_->setName("inactive");
    47. addChild(sprite_paratrooper_,1);
    48. // 拓展功能:锦囊
    49. sprite_pack_ = Sprite::createWithSpriteFrameName("power_portrait_backpack_0001.png");
    50. sprite_pack_->setAnchorPoint(Point(1,0));
    51. sprite_pack_->setPosition(Point(win_size_.width - 10,-20));
    52. sprite_pack_->setName("inactive");
    53. addChild(sprite_pack_,1);
    54. // 锦囊背景
    55. sprite_back_pack_ = Sprite::createWithSpriteFrameName("backPack_hover.png");
    56. sprite_back_pack_->setAnchorPoint(Point(1,0));
    57. sprite_back_pack_->setPosition(Point(win_size_.width - 60,30));
    58. sprite_back_pack_->setVisible(true);
    59. addChild(sprite_back_pack_,-1);
    60. for(int i = 1; i <=6 ; i ++){
    61. int num = 3;
    62. if(num > 0){
    63. stringForSkillFileName = StringUtils::format("backPack_icons_000%d.png",i);
    64. }else{
    65. stringForSkillFileName = StringUtils::format("backPack_icons_off_000%d.png",i+1);
    66. }
    67. sprite_backPack_icons_[i] = Sprite::createWithSpriteFrameName(stringForSkillFileName);
    68. sprite_backPack_icons_[i]->setAnchorPoint(Point(1,0));
    69. sprite_backPack_icons_[i]->setPosition(Point(640 - 85 * i,-20));
    70. sprite_backPack_icons_[i]->setTag(i);
    71. sprite_backPack_icons_[i]->setName(StringUtils::format("shop%d",i));
    72. sprite_back_pack_->addChild(sprite_backPack_icons_[i],0);
    73. auto numLeft = Label::createWithTTF(StringUtils::format("%d",num),"fonts/arial.ttf",20);
    74. numLeft->setPosition(Point(sprite_backPack_icons_[i]->getContentSize().width/4*3,sprite_backPack_icons_[i]->getContentSize().height/4));
    75. numLeft->setTag(101);
    76. sprite_backPack_icons_[i]->addChild(numLeft);
    77. }
    78. // 倒计时涂层
    79. timer_stone_ = ProgressTimer::create(Sprite::createWithSpriteFrameName("power_loading.png"));
    80. timer_stone_->setAnchorPoint(Point(0,0));
    81. timer_stone_->setReverseDirection(true);
    82. timer_stone_->setPosition(Point(10,-20));
    83. timer_stone_->setPercentage(50);
    84. addChild(timer_stone_,1,100);
    85. // 倒计时涂层
    86. timer_paratrooper_ = ProgressTimer::create(Sprite::createWithSpriteFrameName("power_loading.png"));
    87. timer_paratrooper_->setAnchorPoint(Point(0,0));
    88. timer_paratrooper_->setReverseDirection(true);
    89. timer_paratrooper_->setPosition(Point(120,-20));
    90. timer_paratrooper_->setPercentage(100);
    91. addChild(timer_paratrooper_,1,200);
    92. }
    93. void PlayerStateMenuLayer::initEvent()
    94. {
    95. // 添加暂停 按钮的监听。
    96. auto sprite_pause_listener = EventListenerTouchOneByOne::create();
    97. sprite_pause_listener->onTouchBegan = CC_CALLBACK_2(PlayerStateMenuLayer::onTouchBeganSpirtePause,this);
    98. sprite_pause_listener->onTouchEnded = CC_CALLBACK_2(PlayerStateMenuLayer::onTouchEnedSpirtePause,this);
    99. sprite_pause_listener->setSwallowTouches(true);
    100. _eventDispatcher->addEventListenerWithSceneGraphPriority(sprite_pause_listener,sprite_pause_);
    101. // 添加雷石监听
    102. auto sprite_thunder_stone_listener = EventListenerTouchOneByOne::create();
    103. sprite_thunder_stone_listener->onTouchBegan = CC_CALLBACK_2(PlayerStateMenuLayer::onTouchBeganSpriteThunderStone,this);
    104. sprite_thunder_stone_listener->onTouchEnded = CC_CALLBACK_2(PlayerStateMenuLayer::onTouchEnedSSpriteThunderStone,this);
    105. sprite_thunder_stone_listener->setSwallowTouches(true);
    106. _eventDispatcher->addEventListenerWithSceneGraphPriority(sprite_thunder_stone_listener,sprite_thunder_stone_);
    107. // 添加伞兵监听
    108. auto sprite_paratrooper_listener = EventListenerTouchOneByOne::create();
    109. sprite_paratrooper_listener->onTouchBegan = CC_CALLBACK_2(PlayerStateMenuLayer::onTouchBeganSpriteParatrooper,this);
    110. sprite_paratrooper_listener->onTouchEnded = CC_CALLBACK_2(PlayerStateMenuLayer::onTouchBeganSpriteParatrooper,this);
    111. sprite_paratrooper_listener->setSwallowTouches(true);
    112. _eventDispatcher->addEventListenerWithSceneGraphPriority(sprite_paratrooper_listener,sprite_paratrooper_);
    113. // 添加锦囊监听
    114. auto sprite_pack_listener = EventListenerTouchOneByOne::create();
    115. sprite_pack_listener->onTouchBegan = CC_CALLBACK_2(PlayerStateMenuLayer::onTouchBeganSpritePack,this);
    116. sprite_pack_listener->onTouchEnded = CC_CALLBACK_2(PlayerStateMenuLayer::onTouchBeganSpritePack,this);
    117. sprite_pack_listener->setSwallowTouches(true);
    118. _eventDispatcher->addEventListenerWithSceneGraphPriority(sprite_pack_listener,sprite_pack_);
    119. }
    120. bool PlayerStateMenuLayer::onTouchBeganSpirtePause(Touch *touch, Event *event)
    121. {
    122. return true;
    123. }
    124. void PlayerStateMenuLayer::onTouchEnedSpirtePause(Touch *touch, Event *event)
    125. {
    126. }
    127. bool PlayerStateMenuLayer::onTouchBeganSpriteThunderStone(Touch *touch, Event *event)
    128. {
    129. return false;
    130. }
    131. void PlayerStateMenuLayer::onTouchEnedSSpriteThunderStone(Touch *touch, Event *event)
    132. {
    133. }
    134. bool PlayerStateMenuLayer::onTouchBeganSpriteParatrooper(Touch *touch, Event *event)
    135. {
    136. return false;
    137. }
    138. void PlayerStateMenuLayer::onTouchEnedSSpriteParatrooper(Touch *touch, Event *event)
    139. {
    140. }
    141. bool PlayerStateMenuLayer::onTouchBeganSpritePack(Touch *touch, Event *event)
    142. {
    143. return false;
    144. }
    145. void PlayerStateMenuLayer::onTouchEnedSSpritePack(Touch *touch, Event *event)
    146. {
    147. }
    148. void PlayerStateMenuLayer::onEnterTransitionDidFinish()
    149. {
    150. sprite_state_->runAction(MoveBy::create(0.2f,Point(0,-100)));
    151. }

    Layer/PlayerStateMenuLayer.h文件内容:

    1. #ifndef __LAYER_PLAYER_STATE_MENU_LAYER_H__
    2. #define __LAYER_PLAYER_STATE_MENU_LAYER_H__
    3. #include "cocos2d.h"
    4. USING_NS_CC;
    5. class PlayerStateMenuLayer : public Layer
    6. {
    7. public:
    8. virtual bool init();
    9. void initSprite();
    10. void initEvent();
    11. // implement the "static create()" method manually
    12. CREATE_FUNC(PlayerStateMenuLayer)
    13. private:
    14. Size win_size_;
    15. Sprite * sprite_state_;
    16. Sprite * sprite_pause_;
    17. Label *label_life_;
    18. Label* label_gold_;
    19. Label* label_wave_;
    20. Sprite* sprite_thunder_stone_; // 雷石
    21. Sprite* sprite_paratrooper_; // 伞兵
    22. Sprite* sprite_pack_; // 锦囊
    23. Sprite* sprite_back_pack_; // 锦囊背景。六侠背景
    24. // 六侠
    25. Sprite* sprite_backPack_icons_[6];
    26. std::string stringForSkillFileName;
    27. //
    28. ProgressTimer *timer_stone_;
    29. ProgressTimer *timer_paratrooper_;
    30. // ===== 精灵响应函数 =========
    31. // 监听暂停精灵
    32. bool onTouchBeganSpirtePause(Touch* touch,Event *event);
    33. void onTouchEnedSpirtePause(Touch* touch,Event *event);
    34. // 监听雷石精灵
    35. bool onTouchBeganSpriteThunderStone(Touch* touch,Event *event);
    36. void onTouchEnedSSpriteThunderStone(Touch* touch,Event *event);
    37. // 监听伞兵 精灵
    38. bool onTouchBeganSpriteParatrooper(Touch* touch,Event *event);
    39. void onTouchEnedSSpriteParatrooper(Touch* touch,Event *event);
    40. // 监听锦囊 精灵
    41. bool onTouchBeganSpritePack(Touch* touch,Event *event);
    42. void onTouchEnedSSpritePack(Touch* touch,Event *event);
    43. void onEnterTransitionDidFinish();
    44. };
    45. #endif // __LAYER_PLAYER_STATE_MENU_LAYER_H__

    三、演示效果

    四、知识点

    4.1 ProgressTimer工具

    Cocos2d-x 4.0 中的 `ProgressTimer` 是一个用于创建进度条效果的工具类。它允许你根据百分比或比例来显示进度,并且可以用于各种游戏和应用中的加载条、生命值条等。下面是一个详细的例子,以及涉及的知识点。

    ### 示例:创建一个水平进度条

    首先,确保你已经设置好了 Cocos2d-x 4.0 的开发环境。

    1. 创建一个新的 Cocos2d-x 4.0 项目。

    2. 打开你的项目,并在场景中添加一个进度条。

    1. #include "cocos2d.h"
    2. class MyScene : public cocos2d::Scene {
    3. public:
    4.     virtual bool init() override {
    5.         if (!Scene::init()) {
    6.             return false;
    7.         }
    8.         // 创建一个进度条
    9.         auto progress = cocos2d::ProgressTimer::create(cocos2d::Sprite::create("progressbar.png"));
    10.         progress->setType(cocos2d::ProgressTimer::Type::BAR);
    11.         progress->setMidpoint(cocos2d::Vec2(0, 0.5)); // 设置起始点为左边中点
    12.         progress->setBarChangeRate(cocos2d::Vec2(1, 0)); // 设置只在水平方向改变
    13.         progress->setPercentage(50); // 设置初始百分比为 50%
    14.         // 设置进度条位置
    15.         progress->setPosition(cocos2d::Director::getInstance()->getVisibleSize() / 2);
    16.         // 添加进度条到场景
    17.         this->addChild(progress);
    18.         return true;
    19.     }
    20.     CREATE_FUNC(MyScene);
    21. };

    在这个示例中,我们创建了一个水平进度条,通过使用 `ProgressTimer` 来实现。具体说明如下:

    • ProgressTimer::create :函数用于创建 `ProgressTimer` 对象,其中参数是一个 `Sprite` 对象,作为进度条的外观。
    • setType:设置了进度条的类型为 `BAR`,表示水平或垂直的进度条。
    • setMidpoint:设置了进度条的起始点为左边中点。
    • setBarChangeRate: 设置了进度条在水平方向上改变,垂直方向上不改变。
    • setPercentage: 设置了初始百分比为 50%。
    • setPosition: 设置了进度条的位置。

    最后,将进度条添加到场景中。

    3. 创建一个进度条的外观图片("progressbar.png"),并将其放置在项目资源目录下。

    4. 运行项目,你将看到一个水平进度条显示在屏幕中央。

    4.2 setSwallowTouches

            "setSwallowTouches" 是 Cocos2d-x 游戏引擎中的一个方法,通常用于触摸事件的处理。这个方法是 cocos2d::Layer 类的一部分,用于设置是否吞噬(swallow)触摸事件。

            当一个层(Layer)设置了吞噬触摸事件(setSwallowTouches(true)),它将会拦截并处理所有传递给它的触摸事件,阻止这些事件继续传递到底层的层或场景。这通常用于处理触摸事件的优先级,确保在多个重叠的层中只有一个层能够响应触摸事件。

  • 相关阅读:
    近红外II区荧光量子点细胞膜/两亲性不对称双离子苝酰亚胺染料标记细胞膜的制备
    浅谈中小企业的供应商管理
    解决文件传输难题:如何绕过Gitee的100MB上传限制
    MySQL基本命令行的应用
    arm64架构 统信UOS搭建PXE无盘启动Linux系统(麒麟桌面为例)
    2022年湖北省中级工程师职称评审需要注意哪些问题呢?甘建二
    OLED透明拼接屏在乌海湖旅游区的应用探究
    DDS的一点理解
    C#10新特性-全局和隐式usings
    [附源码]计算机毕业设计毕业生就业管理系统Springboot程序
  • 原文地址:https://blog.csdn.net/arv002/article/details/132736243