cocos2dx3.2开发 RPG《Flighting》(四)预先加载与选人界面
来源:互联网 发布:cad for mac 编辑:程序博客网 时间:2024/04/27 23:36
一、前言
假设你已经看懂了前面三节,那么接下来我们就开始进入真正的开发啦~~
二、正文
1、预先加载
首先我们先谈谈预先加载,什么叫预先加载,就是在资源没有被用到的时候就先把资源加载到内存,等要用的时候直接从内存里面获取就好。
这样的好处是当用的时候会省去加载的时间,但是坏处就是占用一部分内存,这是一个时间与空间的选择问题。
游戏一开始进入的是MenuScene
bool MenuScene::init(){preLoadingSomethings();MenuLayer* layer = MenuLayer::create();this->addChild(layer);return true;}
init函数很简单,没有什么特别,需要注意的是preLoadingSomethings函数
void MenuScene::preLoadingSomethings(){std::map<int,HeroMessage> temp = HeroMessageUtil::getInstance()->getHeroMessageMap();for(auto it = temp.begin();it!=temp.end();it++){HeroMessage temp = it->second;std::string png = "BoneAnimate/" + temp.r_png;std::string plist = "BoneAnimate/" + temp.r_plist;std::string EJ = "BoneAnimate/" + temp.r_ExportJson;ArmatureDataManager::getInstance()->addArmatureFileInfo(png,plist,EJ);}std::map<int,MonsterMessage> monTemp = MonsterMessageUtil::getInstance()->getMonsterMessageMap();for(auto it = monTemp.begin();it!=monTemp.end();++it){MonsterMessage temp = it->second;std::string png = "BoneAnimate/" + temp.r_png;std::string plist = "BoneAnimate/" + temp.r_plist;std::string EJ = "BoneAnimate/" + temp.r_ExportJson;ArmatureDataManager::getInstance()->addArmatureFileInfo(png,plist,EJ);}StageMessageUtil::getInstance();}
如果你有看上一节,那么你应该知道XXXMessageUtil是什么东东了。
因为如果要使用骨骼动画,必须先把骨骼动画的资源通过 ArmatureDataManager的addArmatureFileInfo()加载
所以为了以后能够方便地使用骨骼动画,先统一在MenuScene初始化的时候加载。
2、选人界面
好吧,MenuScene跟MenuLayer没有什么其他特别的,就提供了一个开始按钮,转到选人界面ChooseScene
ChooseScene也没有什么,就包含了一个ChooseLayer。
效果图:
下面重点讲ChooseLayer
#ifndef _CHOOSELAYER_H_#define _CHOOSELAYER_H_#include "cocos2d.h"#include "ui/CocosGUI.h"#include "cocostudio/CocoStudio.h"#include "extensions/cocos-ext.h"USING_NS_CC;using namespace cocostudio;using namespace ui;class HeroItem;class ChooseLayer : public Layer{public:virtual bool init();CREATE_FUNC(ChooseLayer);private://加载可选英雄void loadHeroes();//初始化void initHeroMsg();//设置当前英雄void setCurHeroMsg(int index,int heroIndex);//按钮回调函数void startGame(Ref* pSender,ui::TouchEventType type);void leftHero1(Ref* pSender,ui::TouchEventType type);void rightHero1(Ref* pSender,ui::TouchEventType type);void leftHero2(Ref* pSender,ui::TouchEventType type);void rightHero2(Ref* pSender,ui::TouchEventType type);void leftHero3(Ref* pSender,ui::TouchEventType type);void rightHero3(Ref* pSender,ui::TouchEventType type);void backToMenu(Ref* pSender,ui::TouchEventType type);private:std::vector<HeroItem> heroArray;Text* hero_name1;Text* hero_name2;Text* hero_name3;Widget* pNode;int cur_hero1_index;int cur_hero2_index;int cur_hero3_index;Armature* hero1;Armature* hero2;Armature* hero3;};class HeroItem : public Ref{friend class ChooseLayer;public:HeroItem(const std::string& name,const int id,const std::string& resourceName,const int o_x,const int o_y);~HeroItem();private:std::string name;std::string resourceName;int id;int o_x;int o_y;};#endif
注意的是,我这里没有用数组,而是直接用hero1、hero2、hero3这样子的枚举,所以就限定死了只有3个位置。。这是一种笨方法,会出现代码的冗余,在开发中不应该出现,这里懒得修改。。所以请各位不要学习,见谅见谅。
而且这里的布局我也是用cocostudio1.6的,所以你们可能有点看不懂。如果需要补充cocostudio的UI编辑器知识,推荐以下文章
http://cn.cocos2d-x.org/tutorial/show?id=1674
这里我先定义HeroItem结构保存我在选人界面需要用到的信息,其实他就是简化版的HeroMessage(因为在选人界面只用到一部分信息)
而且注意我定义了一个vector<HeroItem>。
下面看各个函数的具体实现:
bool ChooseLayer::init(){pNode = GUIReader::getInstance()->widgetFromJsonFile("UI/ChooseLayerUI.json");this->addChild(pNode,0);Button* enterBtn = (Button*)Helper::seekWidgetByName(pNode,"enterBtn");enterBtn->addTouchEventListener(this,toucheventselector(ChooseLayer::startGame));Button* backBtn = (Button*)Helper::seekWidgetByName(pNode,"backBtn");backBtn->addTouchEventListener(this,toucheventselector(ChooseLayer::backToMenu));Button* leftBtn1 = (Button*)Helper::seekWidgetByName(pNode,"leftBtn1");leftBtn1->addTouchEventListener(this,toucheventselector(ChooseLayer::leftHero1));Button* leftBtn2 = (Button*)Helper::seekWidgetByName(pNode,"leftBtn2");leftBtn2->addTouchEventListener(this,toucheventselector(ChooseLayer::leftHero2));Button* leftBtn3 = (Button*)Helper::seekWidgetByName(pNode,"leftBtn3");leftBtn3->addTouchEventListener(this,toucheventselector(ChooseLayer::leftHero3));Button* rightBtn1 = (Button*)Helper::seekWidgetByName(pNode,"rightBtn1");rightBtn1->addTouchEventListener(this,toucheventselector(ChooseLayer::rightHero1));Button* rightBtn2 = (Button*)Helper::seekWidgetByName(pNode,"rightBtn2");rightBtn2->addTouchEventListener(this,toucheventselector(ChooseLayer::rightHero2));Button* rightBtn3 = (Button*)Helper::seekWidgetByName(pNode,"rightBtn3");rightBtn3->addTouchEventListener(this,toucheventselector(ChooseLayer::rightHero3));initHeroMsg();return true;}init函数就是负责获取按钮,并为按钮绑定回调函数的,至于回调函数的实现等下再说。
注意最后一行调用了initHeroMsg
看initHeroMsg函数之前,先看loadHeroes函数
void ChooseLayer::loadHeroes(){map<int,HeroMessage> temp = HeroMessageUtil::getInstance()->getHeroMessageMap();for(auto it = temp.begin();it!=temp.end();it++){HeroMessage msg = (*it).second;HeroItem item(msg.name,msg.id,msg.r_name,msg.offset_x,msg.offset_y);heroArray.push_back(item);}}loadHeroes函数就是对heroArray的初始化,调用过一次这个函数之后,以后就只需要从heroArray里面拿数据就好了
好的,回过头来看initHeroMsg吧
void ChooseLayer::initHeroMsg(){loadHeroes();hero_name1 = (Text*)Helper::seekWidgetByName(pNode,"heroName1");hero_name2 = (Text*)Helper::seekWidgetByName(pNode,"heroName2");hero_name3 = (Text*)Helper::seekWidgetByName(pNode,"heroName3");cur_hero1_index = 0;cur_hero2_index = 0;cur_hero3_index = 0;hero1 = nullptr;hero2 = nullptr;hero3 = nullptr;setCurHeroMsg(0,1);setCurHeroMsg(0,2);setCurHeroMsg(0,3);}先loadHeroes初始化array
下面的也是对一些变量初始化。
cur_hero1_index表示的是1号位置当前的角色对应array中的位置
setCurHeroMsg(0,1);表示设置1号位置的角色的index为0
具体实现如下:
void ChooseLayer::setCurHeroMsg(int index,int heroIndex){if(index < 0){index = index + heroArray.size();}if(index >= heroArray.size()){index = index - heroArray.size();}switch(heroIndex){case 1:cur_hero1_index = index;hero_name1->setText(heroArray[cur_hero1_index].name);if(hero1)hero1->removeFromParentAndCleanup(true);hero1 = Armature::create(heroArray[cur_hero1_index].resourceName);hero1->setPosition(hero_name1->getPositionX()+heroArray[cur_hero1_index].o_x, hero_name1->getPositionY()+heroArray[cur_hero1_index].o_y);hero1->getAnimation()->play("stand");this->addChild(hero1);break;case 2:cur_hero2_index = index;hero_name2->setText(heroArray[cur_hero2_index].name);if(hero2)hero2->removeFromParentAndCleanup(true);hero2 = Armature::create(heroArray[cur_hero2_index].resourceName);hero2->setPosition(hero_name2->getPositionX()+heroArray[cur_hero2_index].o_x, hero_name2->getPositionY()+heroArray[cur_hero2_index].o_y);hero2->getAnimation()->play("stand");this->addChild(hero2);break;case 3:cur_hero3_index = index;hero_name3->setText(heroArray[cur_hero3_index].name);if(hero3)hero3->removeFromParentAndCleanup(true);hero3 = Armature::create(heroArray[cur_hero3_index].resourceName);hero3->setPosition(hero_name3->getPositionX()+heroArray[cur_hero3_index].o_x, hero_name3->getPositionY()+heroArray[cur_hero3_index].o_y);hero3->getAnimation()->play("stand");this->addChild(hero3);break;default:break;}}第一个参数:index,表示对应heroArray的位置
第二个参数:heroIndex,表示哪一个位置的英雄
一开始先判断index的合法性,这样的实现能够使其达到一种首尾循环的效果。
接着的switch语句是根据英雄的位置,去修改相应的对象,应该不能理解。
PS:再强调一次,我一开始写这个代码的时候图个简单,所以用了枚举的笨方法,大家不要学习,看一看,笑一笑就好。
如果都看懂了最重要的setCurHeroMsg()函数,那么很容易就想到,3对左右选择按钮的实现就可以依靠setCurHeroMsg函数了
void ChooseLayer::leftHero1(Ref* pSender,TouchEventType type){if(type == TouchEventType::TOUCH_EVENT_BEGAN){setCurHeroMsg(cur_hero1_index - 1,1);}}void ChooseLayer::leftHero2(Ref* pSender,TouchEventType type){if(type == TouchEventType::TOUCH_EVENT_BEGAN){setCurHeroMsg(cur_hero2_index - 1,2);}}void ChooseLayer::leftHero3(Ref* pSender,TouchEventType type){if(type == TouchEventType::TOUCH_EVENT_BEGAN){setCurHeroMsg(cur_hero3_index - 1,3);}}void ChooseLayer::rightHero1(Ref* pSender,TouchEventType type){if(type == TouchEventType::TOUCH_EVENT_BEGAN){setCurHeroMsg(cur_hero1_index + 1,1);}}void ChooseLayer::rightHero2(Ref* pSender,TouchEventType type){if(type == TouchEventType::TOUCH_EVENT_BEGAN){setCurHeroMsg(cur_hero2_index + 1,2);}}void ChooseLayer::rightHero3(Ref* pSender,TouchEventType type){if(type == TouchEventType::TOUCH_EVENT_BEGAN){setCurHeroMsg(cur_hero3_index + 1,3);}}
好的,现在就只剩下进入游戏和返回这两个按钮的回调函数没有解释了。
返回按钮很简单
void ChooseLayer::backToMenu(Ref* pSender,TouchEventType type){if(type == TouchEventType::TOUCH_EVENT_ENDED){Director::getInstance()->replaceScene(MenuScene::create());}}其实进入游戏的函数也很简单啦,看不懂没关系,毕竟我们还没有讲战斗场景嘛。哈哈
void ChooseLayer::startGame(Ref* pSender,TouchEventType type){if(type == TouchEventType::TOUCH_EVENT_ENDED){GameScene* scene = GameScene::create();scene->setHeroTeam(HeroMessageUtil::getInstance()->getMessageById(heroArray[cur_hero1_index].id),HeroMessageUtil::getInstance()->getMessageById(heroArray[cur_hero2_index].id),HeroMessageUtil::getInstance()->getMessageById(heroArray[cur_hero3_index].id));scene->setMonsterDeq(StageMessageUtil::getInstance()->getMessageById(3001).monsterDeq);Director::getInstance()->replaceScene(scene);}}
大致的意思就是把当前三个位置的3个信息传到GameScene,由GameScene想干嘛就干嘛去
还有这里默认把id为3001的地图信息(StageMessage)也传到GameScene了,因为当时懒得弄关卡选择器哈哈。关于关卡选择和StageMessage的问题,后面在将战斗场景的时候还会跟大家交代清楚的,现在可以先视而不见吧。
至此,选人界面开发完毕。
我的csdn地址:http://blog.csdn.net/hezijian22
邮箱地址:578690286@qq.com
如有问题或指教,欢迎与我交流,谢谢。
- cocos2dx3.2开发 RPG《Flighting》(四)预先加载与选人界面
- cocos2dx3.2开发 RPG《Flighting》
- cocos2dx3.2开发 RPG《Flighting》(三)从Excel表中加载需要的数据
- cocos2dx3.2开发 RPG《Flighting》(一)基本介绍
- cocos2dx3.2开发 RPG《Flighting》(八)开始战斗
- cocos2dx3.2开发 RPG《Flighting》(九)必不可少的子弹
- cocos2dx3.2开发 RPG《Flighting》(十四)暂停按钮
- cocos2dx3.2开发 RPG《Flighting》(十一)角色分类——英雄与怪物
- cocos2dx3.2开发 RPG《Flighting》(二)骨骼动画介绍及游戏美术资源分享
- cocos2dx3.2开发 RPG《Flighting》(五)只能行走的战斗场景
- cocos2dx3.2开发 RPG《Flighting》(六)角色的状态和控制效果
- cocos2dx3.2开发 RPG《Flighting》(七)回到战斗场景,更新角色的叠放次序
- cocos2dx3.2开发 RPG《Flighting》(十)为角色加上血量条
- cocos2dx3.2开发 RPG《Flighting》(十二)让怪物智能点——怪物仇恨值
- cocos2dx3.2开发 RPG《Flighting》(十三)让英雄炫酷点—技能以及技能效果
- cocos2dx3.2开发 RPG《Flighting》(十五)最后的总结说明,以及源码分享
- 用Java写解谜Rpg-4.加载界面,RPG界面与Player
- cocos2dx3.x《格斗》类游戏加载界面(一)
- OpenCV视频序列操作实例
- 修改mysql 5.1默认安全权限
- ADT在线安装与更新
- poj 3287 -- Catch That Cow (bfs 广搜)
- 程序员的剑之Jan. 19th
- cocos2dx3.2开发 RPG《Flighting》(四)预先加载与选人界面
- Jenkins——构建、集成中的问题
- 【来日复制粘贴】数据透视表分类不同账龄
- JBOSS中的TOMCAT调优
- 主题模型TopicModel:PLSA模型及PLSA的EM推导
- Linux下vsftp配置
- 课程设计2号
- POJ 3254 Corn Fields (状压DP+滚动数组)
- 16.左旋转字符串