改写《魔塔》后篇02:添加怪物动画
怪物在地图上的位置是不变的,但它们都有对应的原地站立时的动画。大家可能想到使用前面创建的动画管理器来创建动画模板,然后播放各个怪物精灵的动画。这样做没错,但是想想就觉得麻烦:如果有100种怪物的话,难道要定义100个动画模板吗?答案是否定的。那么该如何实现怪物原地站立的动画呢?从提供的怪物图片素材可以发现:每个怪物的动作由4帧动画组成,且每帧尺寸一致,都正好是一个图块的大小。是否可以定时地更新怪物对应的图块,从而产生动画的效果?结论是可以。cocos2d-x工程下test项目中的TMXReadWriteTest例子演示了如何动态改变TileMap上的图块,以及用定时器不停地重复更新图块的工作。关键代码如下:
//创建定时器,反复更新图块
schedule(schedule_selector(TMXReadWriteTest::repaintWithGID), 2.0f);void TMXReadWriteTest::repaintWithGID(float dt)
{//获取TileMap地图对象CCTMXTiledMap* map = (CCTMXTiledMap*)getChildByTag(kTagTileMap);//获取第0层CCTMXLayer *layer = (CCTMXLayer*)map->getChildByTag(0);CCSize s = layer->getLayerSize();//遍历一行for( int x=0; x<s.width;x++) {//倒数第二行int y = (int)s.height-1;//获取指定位置当前的图块IDunsigned int tmpgid = layer->tileGIDAt( ccp((float)x, (float)y) );//更新指定位置的图块IDlayer->setTileGID(tmpgid+1, ccp((float)x, (float)y));}
}
明白了上面的代码我们就对实现怪物动画有清晰的思路了:创建一个定时器,在定时器中遍历所有怪物,令其图块ID加一,如果动画完成,则将图块ID置回初始的数值。
下面请大家思考一下如何遍历所有怪物呢?由于遍历方法需要在定时器中调用,就必须尽可能优化其速度。TestCpp中的例子使用了二维数组的遍历。但设想一下,如果地图很大,遍历起来会很耗时。另外,怪物的分布是稀疏的,二维数组中的大部分元素都有可能为空。所以直接在定时器中遍历地图上的每个格子是不明智的。
那么我们可以在地图初始化完毕后,先做一个预处理:将每个怪物的方位,初始时的图块ID存放到一个数组中。然后在定时器中遍历这个数组就可以了。
首先创建一个Enemy类,用于存放怪物的方位和初始的图块ID,将来还会存放怪物的属性等信息:
#ifndef __ENEMY_H__
#define __ENEMY_H__#include "cocos2d.h"using namespace cocos2d;class Enemy:public CCObject
{
public:Enemy(void);~Enemy(void);//怪物在TileMap上的方位CCPoint position;//怪物的图块IDint startGID;
};#endif
然后修改GameMap的初始化方法,遍历TileMap上的所有怪物,生成Enemy对象,添加到一个CCArray中。随后启动一个定时器,每隔0.2s更新一次怪物动画。首先在GameMap.h里面声明一个变量,即怪物层,添加代码“CC_PROPERTY_READONLY(CCTMXLayer*,enemyLayer,EnemyLayer);”,然后在“protected:”下面添加需要用到的数组和方法,代码如下:
//Enemy数组
CCArray* enemyArray;//更新怪物图块
void updateEnemyAnimation(float dt);
接下来在GameMap.cpp文件里面实现怪物层的getter方法:
//返回怪物层
CCTMXLayer *GameMap::getEnemyLayer()
{return enemyLayer;
}
现在我们可以修改初始化方法了,修改后的代码如下:
//TiledMap额外的初始化方法
void GameMap::extraInit()
{//开启各个图层的纹理抗锯齿enableAnitiAliasForEachLayer();//初始化地板层和墙壁层对象floorLayer=this->layerNamed("floor");wallLayer=this->layerNamed("wall");//获取怪物层enemyLayer=this->layerNamed("enemy");CCSize s=enemyLayer->getLayerSize();enemyArray=CCArray::create();//遍历enemy层,将存在的怪物保存到数组中for(int x=0;x<s.width;x++){for(int y=0;y<s.height;y++){int gid=enemyLayer->tileGIDAt(ccp(x,y));if(gid!=0){Enemy* enemy=new Enemy();//保存怪物坐标enemy->position=ccp(x,y);//保存怪物起始的图块IDenemy->startGID=gid;//添加怪物对象到数组enemyArray->addObject(enemy);}}}//别忘了retain()enemyArray->retain();//用于更新敌人动画schedule(schedule_selector(GameMap::updateEnemyAnimation),0.2f);
}
在updateEnemyAnimation中,需要遍历enemyArray,并计算下一帧对应的图块ID,具体代码如下:
//更新怪物的图块
void GameMap::updateEnemyAnimation(float dt)
{//遍历保存所有怪物对象的数组CCObject* pObject;Enemy* enemy;CCARRAY_FOREACH(enemyArray,pObject){enemy=(Enemy*)pObject;if(enemy!=NULL){//获取怪物当前的图块IDint gid=enemyLayer->tileGIDAt(enemy->position);gid++;//如果结束,设置为起始图块IDif(gid-enemy->startGID>3){gid=enemy->startGID;}//给怪物设置新的图块enemyLayer->setTileGID(gid,enemy->position);}else{break;}}
}
还有,别忘了写Enemy.cpp文件,它要对.h里面声明的构造函数和析构函数进行实现,代码如下:
#include "Enemy.h"Enemy::Enemy(void)
{
}Enemy::~Enemy(void)
{
}
现在我们编译运行,发现地图上的怪物们都动起来了。注意,在GameMap的析构方法里要释放enemyArray和定时器:
//析构函数
GameMap::~GameMap(void)
{this->unscheduleAllSelectors();enemyArray->release();
}
改写《魔塔》后篇02:添加怪物动画相关推荐
- 改写《魔塔》后篇01:在地图上绘制怪物
目前我们的勇士只能在空旷的地图上来回乱转,既不能与怪物进行战斗,也无法拾取物品,也不能和NPC对话等.这一篇的目的就是向游戏内添加更多的元素,丰富游戏内容,增加可玩性. 魔塔的地图上充满了强弱不一的怪 ...
- unity人物旋转移动代码_游戏诞生之日02 - 美术篇 快速制作人物动画
在上一篇<游戏诞生之日01 - 美术篇 快速搭建和渲染游戏的第一个场景>里,我们得到了一个静态渲染的游戏场景. 接下来我们需要加入人物动画,为游戏注入活力. 第五块拼图 - 动画素材从哪里 ...
- 【翻译】西川善司的「实验做出的游戏图形」「GUILTY GEAR Xrd -SIGN-」中实现的「纯卡通动画的实时3D图形」的秘密,后篇...
http://www.4gamer.net/games/216/G021678/20140714079/ 连载第2回的本回, Arc System Works开发的格斗游戏「GUILTY GEAR ...
- ASP.NET自定义控件组件开发 第三章 为控件添加事件 后篇
第三章 为控件添加事件 后篇 前一篇文章只是简单的说了下事件,但是大家应该方法,在ASP.NET自定义控件中只是简单那么定义事件是行不 通.如果大家开发的是WinForm中的事件,之前的定义可能没有什 ...
- Android添加item动画,RecyclerView基础篇-Item添加动画
Android_Banner.jpg 简介 本节中我们介绍下给RecyclerView中的Item添加动画. 添加的动画,分为,在打开列表时有Item的展示动画,当滑动的时候没有动画 和打开列表滑动时 ...
- android长按加入购物车,《Android APP可能有的东西》之UI篇:加入购物车动画
很多电商app的加入购物车的动作会要求加上动画效果:飞进购物车,想来也合理,在listview界面时商品快速加入购物车,一直toast用户加入成功好像不太正常,所以添加一个动画,用户自然就懂了,而且也 ...
- python深浅拷贝 面试_Python面试宝典之基础篇-02
原标题:Python面试宝典之基础篇-02 我觉得你如果正在找工作,我的Python面试宝典几期教程,你一定得花时间看完了! 题目006:说说Python中的浅拷贝和深拷贝. 点评:这个题目本身出现的 ...
- 【Agni-s Philosophy】使用的图形技术解说(后篇)Volume渲染和粒子处理
在2012年11月举办的[SQUARE ENIX 开放会议 2012]的第2天,进行了新世代游戏引擎[Luminous Studio]制作的实时技术演示作品[Agni's Philosophy]中使用 ...
- 尚硅谷 宋红康 JVM教程_01_内存与垃圾回收篇——02
本系列相关链接 尚硅谷 宋红康 JVM教程_01_内存与垃圾回收篇--01 (20210103-20210110) https://blog.csdn.net/wei198621/article/de ...
最新文章
- Eclipse注释模板 注释快捷键
- 推荐给大家看的设计书
- 7999元大疆最新无人机,支持第一人称视角极速拍摄,网友:不是航拍,是直接起飞...
- oracle tax 中国税,oracle_TAX_税基础设置操作手册.doc
- Linux 调优方案, 修改最大连接数(ulimit命令)
- php怎么实现md5加密,php如何进行md5加密
- Oracle数据库管理系统:大数据的备份
- http1.0 http1.1 http2 之间的区别
- 表必须要有主键吗_玄关隔断什么材质好?玄关隔断必须要做吗?
- Flutter进阶—实现动画效果(九)
- mysql交换分区_对MySQL交换分区的实践
- 通信系统仿真中的几个能量归一化问题
- 一粒云盘发布v3.5版本
- 华为服务器系统图标,服务器图标
- python nlpir_Python 中文分词 NLPIR 快速搭建
- 疫情下,嵌入式er该怎么进行职业规划,难点在哪?
- thinkphp5地址的获取和修改接口过程
- 【论文笔记_知识蒸馏_目标检测_2022】Decoupled Knowledge Distillation
- 驾校学员信息管理系统
- # 2gether 在一起 # 一份生日Party邀请函待查收
热门文章
- Python实现小游戏--2048
- Qt 如何改变图标颜色
- 【原创】Newlife.XCode的常见功能使用(一)查询与数据初始化
- Redis 4.0.11配置说明
- 【IEEE_Verilog-12.4】generate的用法
- 电子学会 2019年12月 青少年软件编程Python编程等级考试一级真题解析(选择题+判断题)
- Python绘制基尼系数图
- 基于JAVA社区留守儿童帮扶系统演示录像2020计算机毕业设计源码+数据库+lw文档+系统+部署
- PKUWC2019 赛前模拟赛总结
- Tensorflow(2.0+) 对五类医学图像进行分类