cocos引擎类神经猫三消游戏《Rabbit Escape》03让兔子动起来.docx
- 文档编号:18616159
- 上传时间:2023-08-20
- 格式:DOCX
- 页数:16
- 大小:19.40KB
cocos引擎类神经猫三消游戏《Rabbit Escape》03让兔子动起来.docx
《cocos引擎类神经猫三消游戏《Rabbit Escape》03让兔子动起来.docx》由会员分享,可在线阅读,更多相关《cocos引擎类神经猫三消游戏《Rabbit Escape》03让兔子动起来.docx(16页珍藏版)》请在冰点文库上搜索。
cocos引擎类神经猫三消游戏《RabbitEscape》03让兔子动起来
类神经猫三消游戏《RabbitEscape》03:
让兔子动起来
一、前言
经过上一讲的讲解,我们已经可以将UI响应用户的交互操作了(添加石头),但是这都只是在UI界面上的一些操作,今天我们会讲一讲如何创建逻辑层,并将UI层和游戏逻辑层进行联系,以及实现简单的让兔子动起来。
二、创建GameMap
首先在我们项目中要新建一个名叫GameCtrl的类,来管理游戏的逻辑。
.h文件:
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#ifndef __RabbitTech__GameCtrl__
#define __RabbitTech__GameCtrl__
#include
#include
#include
using namespace std;
const int NUM_MAPROWANDCOW = 9; //表示行列数
const int VAL_MAX = 0x0FFFFFFF; //表示最大值
//方向枚举
enum class Dir{
up,
down,
left,
right,
upLeft,
upRight,
downLeft,
downRight,
none
};
//地图矢量
struct Vec{
int hor; //横向
int ver; //纵向
Vec(){
hor = 0;
ver = 0;
}
Vec(int _ver,int _hor){
hor = _hor;
ver = _ver;
}
bool operator == (const Vec& vec ){
return vec.hor==hor&&vec.ver==ver;
}
Vec operator + (const Vec& vec){
return Vec(vec.ver+ver,vec.hor+hor);
}
};
//地图位置
struct Pos{
//是否是障碍;
bool isObt;
//位置信息
Vec vec;
Pos(){
vec.ver = 0;
vec.hor = 0;
isObt = false;
}
Pos(int _ver,int _hor){
vec.ver = _ver;
vec.hor = _hor;
isObt = false;
}
};
class GameCtrl{
public:
GameCtrl();
~GameCtrl();
public:
//添加石头
void addObtacle(int tag);
//移动兔子
int rabbitMove();
private:
//游戏地图
vector
//移动距离
std:
:
unordered_map
std:
:
unordered_map
//初始化地图移动矢量
void initMoveVec();
//初始花地图信息
void initMapInfo();
Vec m_rabbitPos; //兔子的位置
};
#endif /* defined(__RabbitTech__GameCtrl__) */
.cpp文件:
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "GameCtrl.h"
GameCtrl:
:
GameCtrl(){
this->initMoveVec();
this->initMapInfo();
}
void GameCtrl:
:
initMoveVec(){
//创建移动HASH
m_moveVec[(int)Dir:
:
up] = new Vec(-1,0);
m_moveVec[(int)Dir:
:
down] = new Vec(1,0);
m_moveVec[(int)Dir:
:
left] = new Vec(0,-1);
m_moveVec[(int)Dir:
:
right] = new Vec(0,1);
m_moveVec[(int)Dir:
:
upLeft] = new Vec(-1,-1);
m_moveVec[(int)Dir:
:
upRight] = new Vec(-1,1);
m_moveVec[(int)Dir:
:
downLeft] = new Vec(1,-1);
m_moveVec[(int)Dir:
:
downRight]= new Vec(1,1);
//创建映射hash
m_moveDirs[m_moveVec[(int)Dir:
:
up]]=(int)Dir:
:
up;
m_moveDirs[m_moveVec[(int)Dir:
:
down]]=(int)Dir:
:
down;
m_moveDirs[m_moveVec[(int)Dir:
:
left]]=(int)Dir:
:
left;
m_moveDirs[m_moveVec[(int)Dir:
:
right]]=(int)Dir:
:
right;
m_moveDirs[m_moveVec[(int)Dir:
:
upLeft]]=(int)Dir:
:
upLeft;
m_moveDirs[m_moveVec[(int)Dir:
:
upRight]]=(int)Dir:
:
upRight;
m_moveDirs[m_moveVec[(int)Dir:
:
downLeft]]=(int)Dir:
:
downLeft;
m_moveDirs[m_moveVec[(int)Dir:
:
downRight]]=(int)Dir:
:
downRight;
}
void GameCtrl:
:
initMapInfo(){
//初始化地图
for (int i = 0; i vector for (int j = 0; j auto pNewPos = new Pos(i,j); curRow.push_back(pNewPos); } m_gameMap.push_back(curRow); } //初始化兔子信息 m_rabbitPos.hor=m_rabbitPos.ver = NUM_MAPROWANDCOW/2; } void GameCtrl: : addObtacle(int tag){ m_gameMap[tag/NUM_MAPROWANDCOW][tag%NUM_MAPROWANDCOW]->isObt = true; } int GameCtrl: : rabbitMove() { //假设让兔子一直向上 m_rabbitPos=(*m_moveVec[(int)Dir: : up])+m_rabbitPos; return m_rabbitPos.ver*NUM_MAPROWANDCOW+m_rabbitPos.hor; } GameCtrl: : ~GameCtrl(){ //析构地图信息 for (int i = 0; i for (int j = 0; j delete m_gameMap[j]; } } //析构移动矢量 for (auto& it: m_moveVec) { delete it.second; } } PS: 因为整个逻辑控制是脱离Cocos2d-x架构的,为了降低耦合,我没有使用Cocos2d-x的头文件。 玩过《围住神经猫》的童鞋应该都知道,它的地图看起来不是很对称,但是其实可以抽象为一个9X9的矩阵(后面称为GameMap)。 所以该GameMap一共有9*9=81个位置,所以为了表示每一个位置的信息,我抽象出了一个叫Vec(地图矢量)的结构来表示。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 //地图矢量 struct Vec{ int hor; //横向 int ver; //纵向 Vec() { hor = 0; ver = 0; } Vec(int _ver,int _hor) { hor = _hor; ver = _ver; } bool operator == (const Vec& vec ) { return vec.hor==hor&&vec.ver==ver; } Vec operator + (const Vec& vec) { return Vec(vec.ver+ver,vec.hor+hor); } }; 为了在后面的操作方面我重写了它的两个运算符。 而为了进行后面能够存储表示每个位置在A*寻路算法中的各种信息(下次教程会具体介绍),我将它进行了再次的封装。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 //地图位置 struct Pos { //是否是障碍; bool isObt; //位置信息 Vec vec; Pos() { vec.ver = 0; vec.hor = 0; isObt = false; } Pos(int _ver,int _hor) { vec.ver = _ver; vec.hor = _hor; isObt = false; } }; OK,现在可以创建我们的游戏地图了,这里我用了一个的vector来模拟二维的地图。 1 2 3 4 5 6 7 8 9 10 11 12 //游戏地图 vector //初始化地图 for (int i = 0; i vector for (int j = 0; j auto pNewPos = new Pos(i,j); curRow.push_back(pNewPos); } m_gameMap.push_back(curRow); } 如果对vector如何模拟二维动态数组的童鞋,可以XX一下相关内容进行了解。 三、兔子在逻辑层的移动 有些童鞋肯定以为神经猫中的猫一共只有四个移动方向,但是其实事实上仔细观察的话就会发现,其实是有8个方向可以移动的。 所以我做了一个枚举类来表示其移动的方向。 1 2 3 4 5 6 7 8 9 10 11 12 //方向枚举 enum class Dir{ up, down, left, right, upLeft, upRight, downLeft, downRight, none }; 有了方向枚举,怎么能够和地图矢量联系起来呢? 相信如果有点数学基础的童鞋,都应该看得懂这张图。 这就是用二维的数组来模拟平面的点的情况。 如,当前rabbit的Vec(假设为rabbitVec)的话,在rabbit上面一行的up位置的Vec应该为(rabbitVec.ver-1,rabbitVec.hor)。 我们要用个成员变量记录rabbit位置并且进行一开始初始化: 1 2 3 4 Vec m_rabbitPos; //兔子的位置 //初始化兔子信息 m_rabbitPos.hor=m_rabbitPos.ver = NUM_MAPROWANDCOW/2; 一开始将其放在(4,4)的地方,即正中间。 为了以后进行位置变化方便,我这里用了两个hashmap来保存移动的信息。 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 //移动距离 std: : unordered_map std: : unordered_map void GameCtrl: : initMoveVec(){ //创建移动HASH m_moveVec[(int)Dir: : up] = new Vec(-1,0); m_moveVec[(int)Dir: : down] = new Vec(1,0); m_moveVec[(int)Dir: : left] = new Vec(0,-1); m_moveVec[(int)Dir: : right] = new Vec(0,1); m_moveVec[(int)Dir: : upLeft] = new Vec(-1,-1); m_moveVec[(int)Dir: : upRight] = new Vec(-1,1); m_moveVec[(int)Dir: : downLeft] = new Vec(1,-1); m_moveVec[(int)Dir: : downRight]= new Vec(1,1); //创建映射hash m_moveDirs[m_moveVec[(int)Dir: : up]]=(int)Dir: : up; m_moveDirs[m_moveVec[(int)Dir: : down]]=(int)Dir: : down; m_moveDirs[m_moveVec[(int)Dir: : left]]=(int)Dir: : left; m_moveDirs[m_moveVec[(int)Dir: : right]]=(int)Dir: : right; m_moveDirs[m_moveVec[(int)Dir: : upLeft]]=(int)Dir: : upLeft; m_moveDirs[m_moveVec[(int)Dir: : upRight]]=(int)Dir: : upRight; m_moveDirs[m_moveVec[(int)Dir: : downLeft]]=(int)Dir: : downLeft; m_moveDirs[m_moveVec[(int)Dir: : downRight]]=(int)Dir: : downRight; } 一个用于存储移动的Vec,一个用于进行映射(后面会有用到)。 这样操作的话会大大减少代码的复杂度。 四、UI层和逻辑层联系起来 讲了肿么多,你可能会问了,你怎么能将你逻辑层的障碍,兔子和你表现在UI上面的兔子和障碍联系起来了呢? 哈哈哈,这里我主要用到了对逻辑标签tag进行数学中的除和取余操作实现的,看了下面这张图也许你就会懂了。 有了上面的代码,关于添加障碍的代码,也应该可以理解了。 1 2 3 4 void GameCtrl: : addObtacle(int tag) { m_gameMap[tag/NUM_MAPROWANDCOW][tag%NUM_MAPROWANDCOW]->isObt = true; } 而关于UI层的兔子移动是根据逻辑层的兔子移动后Vec中的ver,hor来反推出tag,然后在UI中找到该tag对应的sprite,将兔子移动到相应的sprite的position。 1 2 3 4 5 6 7 8 9 10 11 int GameCtrl: : rabbitMove() { //假设让兔子一直向上 m_rabbitPos=(*m_moveVec[(int)Dir: : up])+m_rabbitPos; return m_rabbitPos.ver*NUM_MAPROWANDCOW+m_rabbitPos.hor; } //rabbit move int moveTag = m_ctrl->rabbitMove(); if(m_pNodes->getChildByTag(moveTag)){ m_pNode_rabbit->runAction(MoveTo: : create(0.1, m_pNodes->getChildByTag(moveTag)->getPosition())); } 这里我们先假设兔子是只能向上移动,下次我会讲解如何根据兔子能够沿着正确的方向进行移动。 最后需要修改一下在HelloWorld中添加我们的控制类GameCtrl,以及修改触摸响应函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private: //游戏逻辑控制 GameCtrl* m_ctrl; bool HelloWorld: : onTouchBeganCallBack(Touch *t, Event* event){ for (auto it =m_pNodes_obstacle.begin();it! =m_pNodes_obstacle.end() ; it++) { if((*it)->getBoundingBox().containsPoint(t->getLocation())&&(! (*it)->isVisible())){ //add obt auto pObt = (*it); pObt->setVisible(true); m_ctrl->addObtacle(pObt->getTag()); //rabbit move int moveTag = m_ctrl->rabbitMove(); if(m_pNodes->getChildByTag(moveTag)){ m_pNode_rabbit->runAction(MoveTo: : create(0.1, m_pNodes->getChildByTag(moveTag)->getPosition())); } break; } } return false; } 别忘了对m_ctrl进行内存管理哦,因为不参与cocos的内存管理,所以需要自己对其进行内存管理。 五、最后说几句 1.因为电脑重装系统了,所以这次上传的东西是用Cocos2d-xv3.4和CocosStudio
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Rabbit Escape cocos引擎类神经猫三消游戏Rabbit Escape03让兔子动起来 cocos 引擎 神经 猫三消 游戏 Rabbit Escape 03 兔子 起来