有一个塔防游戏里面有几种可以操控移动的英雄还有炮塔箭塔法师塔兵营之类的lol防御塔塔还有几种法术,

转过路角忽然发现,3岁的儿子已在路口等着自己回来。
在0℃的江苏无锡街头,环卫工用双手疏通下水道。
声明:本文由入驻搜狐公众平台的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。
  《皇家守卫军》(《Kingdom Rush》,以下简称KR)是由IRONHIDE公司于2011年发布的一款TD游戏,至今有原作及前线和起源两款续作。该游戏一经发布就受到了玩家方面的广泛好评,其开创的一些模式也被后来的很多作品所借鉴。
  为什么一款在手机平台上连同数据包在内总共不超过600M的TD游戏令人如此神往,笔者将在以下几个方面分析。
  一、游戏画面
  画面风格
  KR不同于2011年前由于安卓系统的不断升级而开始追求画面以及声音效果的其他游戏,该游戏的画面风格力求节俭,不论是人物的造型还是场景的设计,其画风均是精简而不失细致。这在当时普遍开始追求3D甚至写实画风的游戏的衬托下使得玩家眼前一亮。区别于其他游戏的风格可以有效的抓住玩家的好奇心理,从而在吸引玩家方面起到的相当大的作用。
  然而如果光是简洁的画风并不能长期吸引玩家的注意力,长时间面对简洁而没有变化的画风只会消磨掉玩家的好奇心,继而使得玩家在游戏的外观上面产生厌烦而放弃游戏。KR的画面风格简洁却也不失丰富,三代的游戏平均每代都有着三到四个大的场景风格,从沙漠到雪山,从丛林到地下。每当玩家开始熟络这一个风格的地图的时候,下一关却又来到了迥然不同的世界,这样的画面不断给玩家带来新奇的体验,也不断提升着玩家对于游戏的期待:下一个场景是什么?下一个场景里又会有什么新奇的东西?这一切都在吸引着玩家前去探索。
  场景互动
  同时,KR的画面进随着剧情的进展,每一个关卡前的等待界面都会有关于本关的一小段介绍。玩家出于好奇的心理在读完剧情之后开始游戏,然后在本关的场景中找到与剧情相照应的物品。这会提升玩家的代入感,并给予玩家心理上的满足感。而且场景中的物品并不统统是摆设,除了一些物品基本的触碰反馈以外,还有其他的东西会在游戏本体中产生影响。
(上图是个野蛮人草屋,可以买兵)
  比如我在洞穴里看到一条龙,这条龙看守着宝藏。玩家在好奇心的驱动下点击了一下龙,然后惊奇的发现:龙飞起来了!然后看见龙身下的宝藏,又点击了一下,哇!加钱啦!这些让玩家提前能有有所预料,最后又能够成为现实的场景互动进一步提升了玩家的心理满足感,同时也增加了游戏的趣味性与难度。
  (笔者曾经因为点钱点high了结果漏过了一票怪然后gg......)
  还有一些场景提示着玩家可能出现的隐藏路线,让玩家可以提前防范。
  总体来说,KR的画面风格及场景互动是该游戏得以成功的一个重要因素,简洁的画面以及多样的触发事件为游戏增色许多。
  二、关卡设置
  教学关卡
  KR的教学关卡的设计采用了开放式的提示,即并不强硬的要求玩家在某一位置放置一个怎样的防御塔。同时在画面的左边的竖排以TIPS的方式对各种防御塔的作用进行介绍,让玩家初步了解防御塔的功能。
  相比于较为容易令人厌烦的强制性的新手引导,开放式的教学更能够提高玩家的新奇感和探索的欲望,使得玩家能够更好的融入游戏的环境中。而对于开放式教学容易使得新手玩家不得要领的弊端,游戏也通过了出色的路线布置进行了弥补。
  游戏开始时为玩家解锁了三种防御塔:箭塔,法师塔和兵营。尽管玩家从名字以及以往的游戏体验上能够大致了解兵营是出兵建筑而箭塔和法师塔是攻击建筑,但是还是疑惑于其具体用法。这时玩家就会在地图上将两个防御塔放在一起进行对比。然后在之后的防御中玩家就会发现兵营是用来阻拦敌军的而箭塔是快速输出。而教学关的建造位置排布使得两个箭塔的攻击范围和防守范围得以重叠,这样让玩家不至于因为建错塔而在第一关就失败从而产生挫败感。
  而在之后用到法师塔和炮塔的时候,第一波怪物往往是适合这两种防御塔攻击的类型(高护甲,数量多血量低)。这样玩家就会不自觉的对新解锁的防御塔进行关注,同时在心中产生对防御塔适合对应怪物的观念,从而在不知不觉中完成新手引导的过程。
  进阶关卡
  度过了新手引导阶段后,玩家开始进入游戏的主体。玩家开始试图对之前的各种防御塔进行组合。然而在防御塔的高阶分支出现之前,各个防御塔的攻击模式都和之前的相同,区别只在于攻击速度和攻击力上。这在已经让玩家烂熟于心,那么如何能在游戏进行的过程中给予玩家更多的引导以及新奇的体验呢?
  首先是行进路线的设定。KR中怪物行进的路线虽然是固定的,但却不是唯一的。游戏中通常是两到三个方向出兵,而终点的设计也有多个。这扩大了游戏的防守范围,增加了游戏的难度,同时丰富了游戏内容。
  其次是天赋系统及英雄等级。TD游戏的难度通常是不可逆的,传统TD游戏中怪物的强度,解锁的防御塔,怪物的波数和行走路线都是固定的。玩家通常无法通过提高自己的应对策略以外的方法来降低游戏难度,这是TD游戏劝退玩家的一大原因。而在KR中,英雄的等级并非是一成不变的,他的等级会随着身边怪物的死亡而提升,而等级可以带来更高的属性和更多的技能,并且在游戏关卡失败或是退出后这些经验值不会消失。这样就可以使得玩家可以通过英雄等级的提升来降低游戏的难度。这样在游戏设定的三个难度档次上又赋予了游戏难度以弹性,从而不会让玩家长期卡在某一关中。
  天赋系统也是同样,随着游戏的推进,玩家可以解锁更多的天赋以提升自己的能力。关于天赋系统,在之后的分析中会详细讲。
  第三,场景路线的加入。回到之前所说的场景的话题:本游戏中有很多场景的互动,具体的来说就是场景建筑以及场景中一些物品的作用以及隐藏的道路。游戏中多处采用该类型的手法以保持玩家对游戏的新鲜感及探索欲望。同时,这些隐藏的要素也起到了多样化增加游戏难度的作用。
  高级关卡
  等到玩家解锁了每种防御塔的两个高阶分支之后,游戏就进行到了高潮阶段。属性的变化,技能的配置以及防御塔的选择和搭配使得游戏的丰富度提升了一个档次。进行到这个阶段之后游戏的总体难度趋于平缓,怪物的属性和波束的增长变慢。游戏的难度开始主要体现在怪物的行动路线以及配置上。这样的设计使得玩家不在纠结于防御塔的强弱,而是开始思考多样化的应对策略,提高了玩家对于游戏的探索度,同时也使得玩家在通关之后获得更多的成就感――这次的关卡我又搭配对了!
  相较于上一个阶段,这个阶段在于新鲜感上有了更多的提升,配合天赋以及英雄的多样化,很容易让玩家们领会到这个游戏的魅力所在。
  三、游戏主要元素
  防御塔
  作为TD游戏的核心元素,防御塔的设定往往决定了一款游戏的生死,而KR在这方面做得恰到好处。
  通常的TD游戏,其防御塔的升级体现在什么方面?攻击力和攻击速度(范围)的增长(通常是线性)。更进一步的可能增加一些伤害变为范围性的改变。而在KR中,这样的改变被多元化了。玩家可能并不能很好的适应每一种防御塔,他们可能苦于箭塔的破甲能力,法师塔的伤害溢出,炮塔的缓慢攻速以及兵营的毫无卵用(笑)。在这时,玩家发现他们可以把箭塔升级成法术攻击,让炮塔召唤怪物,让法师塔快速攻击,让兵营里的士兵能够对空。每种防御塔多样化的发展模式使得各种玩家都能够找到适合自己的发展方向,一改传统TD游戏中防御塔一成不变的模式。
  而在防御塔的技能方面,伤害,限制,增幅,秒杀。多样的技能配合多种的伤害模式使得战场更加丰富。
  同时,如之前所说,场景建筑所构成的防御塔在本游戏中随处可见,一个场景中的防御塔(通常是兵营)为游戏提供了更多的游戏策略,同时也让玩家看到了更多的游戏元素。场景建筑中的士兵不同于玩家兵营的士兵,他们有不同的属性,以及多样的技能。玩家在自身防御塔和场景建筑的升级上的抉择也间接提升了游戏难度。
  KR在怪物的设计上也是多种多样,从基本的各种护甲,速度,攻击力等基础属性的怪物,到拥有强化,治疗,复活,伤害等多样化的怪物。怪物的多样性使得防御塔的多样性有了用武之地。玩家面对的不再是各种数值上增长而本身毫无变化的模板化的怪物,而是需要多种防御塔限制和削弱的需要策略应对的敌人,这种对于策略的要求正好迎合了TD游戏爱好者对于游戏内容的要求。
  同时boss怪物的设定也非常用心,boss怪物不是普通怪物的强化版,而是有诸多新奇而唯一特性的强大敌人。玩家在面对boss的时候的感受与其他怪物大有不同,而击败boss的成就感和新奇感也会是普通怪物的几倍。
  英雄和天赋
  天赋系统可以说是整个KR的核心内容。虽然天赋系统在KR之前早已有之,但KR天赋系统区别于其他TD游戏的天赋系统的地方就在于:它不是单纯的增加防御塔的属性,而是给予防御塔各种各样的特性,以达到让防御塔多样化的目的。
  让我们看一下KR的天赋树:前三行是传统的基础属性的提升,而后三行就是特性的提升了,比如箭塔的暴击,法师塔的虚弱等,这些天赋使得玩家在使用各种防御塔的时候更加得心应手。同时,KR的天赋系统可以自由重置和修改,这也让玩家在面对不同关卡的时候除了思考防御塔的位置及经济的分配外还要考虑到天赋的分配,增加了很多过关的方法。
  然而,多样化的能力提升并不意味着对传统属性的放弃。玩家需要的是能力的提升而不是将防御塔们变成一个个马戏团。在KR中,天赋树是无法点满的,玩家最多让两种防御塔展现出所有的特性,代价就是其他防御塔孱弱的表现。而一两个特性对于游戏的提升并没有效果,所以回到最初,KR天赋树的前三排都是非常硬性的增加防御塔的数值,这让玩家在对某一天赋投入少量的星数之后也能够得到可以看得到的回报,这点是非常聪明的设计。
  英雄也是同样,尽管这样的设计似乎是从魔兽的塔防那里借鉴的?但是不得不说KR的英雄系统也是相当的到位。不同英雄的不同技能使得玩家在每种游戏风格上都能找到自己适合的英雄。同时,英雄的等级也在调控着游戏的难度,这个在之前就说过了。
  多样化,这个词笔者多次提到。多样化是KR最大的魅力所在,也是它受到玩家好评的主要原因。它使得KR摆脱了传统TD游戏仅有数值和路线变动的枯燥乏味,给玩家更多的选择空间和游戏体验,这铸就了KR的成功。
  区别于传统的TD游戏,KR的魔法不再是救民于水火(或许也是这样?不过没那么强了。)KR的魔法更加依赖于天赋的增幅,如果不点天赋的话,KR的魔法更像是给玩家补漏或者增加经济的一种手段。而且即使天赋点在了魔法上,也经常砸不死几个......
  魔法的设计反映出了KR的设计者想要传达给玩家的信息:策略的重要性。这也是KR对新人玩家少数的不友好的几点。
  四、剧情与表现
  虽然剧情不是TD游戏的核心内容,但正如《阴阳师》制作组的话所说:并不想让剧情成为短板。
  KR三代均有相当不错的剧情,每一关的介绍上都紧随着剧情的发展,关卡的设计上也贴合这剧情的走向。你可以在丛林中解锁精灵弓箭手的游侠箭塔,也可以在法师塔接受大法师的帮助。
  同时,在boss关卡都会有小小的演出,场景风格的切换也会有小短漫来告诉你原因。优秀的表现手法和并不枯燥的剧情使得玩家有更强的代入感,玩起来也更加的有乐趣。
  以上是本人对于《皇家守卫军》这款游戏的一些分析,新手试文,望众位大神给予指正。
  点击一下
  立即阅读相关好文章
》谈贪婪设计丨丨
核心设计分析
  近期热文
欢迎举报抄袭、转载、暴力色情及含有欺诈和虚假信息的不良文章。
请先登录再操作
请先登录再操作
微信扫一扫分享至朋友圈
搜狐公众平台官方账号
生活时尚&搭配博主 /生活时尚自媒体 /时尚类书籍作者
搜狐网教育频道官方账号
全球最大华文占星网站-专业研究星座命理及测算服务机构
主演:黄晓明/陈乔恩/乔任梁/谢君豪/吕佳容/戚迹
主演:陈晓/陈妍希/张馨予/杨明娜/毛晓彤/孙耀琦
主演:陈键锋/李依晓/张迪/郑亦桐/张明明/何彦霓
主演:尚格?云顿/乔?弗拉尼甘/Bianca Bree
主演:艾斯?库珀/ 查宁?塔图姆/ 乔纳?希尔
baby14岁写真曝光
李冰冰向成龙撒娇争宠
李湘遭闺蜜曝光旧爱
美女模特教老板走秀
曝搬砖男神奇葩择偶观
柳岩被迫成赚钱工具
大屁小P虐心恋
匆匆那年大结局
乔杉遭粉丝骚扰
男闺蜜的尴尬初夜
客服热线:86-10-
客服邮箱:Cocos2d-x 3.x开发塔防游戏《王国保卫战》04:防御塔
招聘信息:
上篇讲到地图,本文就直接从塔防游戏的最根本的”塔“来讲起吧!首先我们定义一个防御塔的基类BaseTower&class&BaseTower:&public&Sprite我们要先确定一个塔所具备的属性,这些可以根据自己所设计的游戏需要来自行定义,例如:CC_SYNTHESIZE(TowerType,&towerType,&TowerType);&//类型&&
CC_SYNTHESIZE(Terrain*,&myTerrain,&MyTerrain);&&//建造点&&
CC_SYNTHESIZE(std::string,&towerName,&TowerName);&//名称&&
CC_SYNTHESIZE(int,&level,&Level);//等级&&
CC_SYNTHESIZE(float,&scope,&Scope);//范围&&
CC_SYNTHESIZE(float,&nextScope,&NextScope);//升级后范围&&
CC_SYNTHESIZE(float,&rate,&Rate);//攻击速度&&
CC_SYNTHESIZE(int,&force,&Force);//攻击力&&
CC_SYNTHESIZE(int,&updateMoney,&UpdateMoney);//升级所需金钱&&
CC_SYNTHESIZE(int,&buildMoney,&BuildMoney);//售出时返还金钱然后定义一些可能出现的公共方法,在不同的防御塔子类中实现:public:&&
&&virtual&void&updateTower(){};//升级防御塔(基础升级)&&
&&virtual&void&sellTower();//售卖防御塔&&
&&virtual&void&removeTower();//移除防御塔&&
&&virtual&bool&init();//初始化防御塔&&
&&virtual&void&showTowerInfo();//显示防御塔信息&&
&&virtual&void&update1(){};//两种升级方向&&
&&virtual&void&update2(){};&&
&&virtual&void&setRallyPoint(Point&point){};//兵营塔的设置集结点&&
protected:&&&
&&virtual&void&checkNearestMonster();//检测附近敌人&&
&&BaseMonster*&nearestM&&//附近的敌人&&
&&bool&onTouchBegan(Touch&*touch,&Event&*event);&&
&&void&onTouchEnded(Touch*&touch,&Event*&event);&&
&&virtual&void&showUpdateMenu(){};//显示升级选项&&
&&virtual&void&hideUpdateMenu();//隐藏&&
&&Sprite*&//该塔的建造点&&
&&void&setListener();//设置某些监听事件每个防御塔会有自己的shoot(float dt)之类的方法(根据防御塔类型不同而不同),通过schedule(schedule_selector(BaseTower::shoot), 0.5f);定时调用,此时的0.5f就和防御塔的攻击速率有关,越短,攻击速度越快。防御塔攻击敌人的思路参考了《》这篇文章,感谢作者。每次防御塔执行自己的shoot方法时,首先执行CheckNearestMonster来检测附近是否存在可以攻击的敌人void&BaseTower::checkNearestMonster()&&
&&&&auto&instance&=&GameManager::getInstance();&&
&&&&auto&monsterVector&=&instance->monsterV//全局Vector变量,用来存储当前关卡的敌人&&
&&&&auto&currMinDistant&=&this->&&&
&&&&nearestMonster&=&NULL;&&
&&&&for(int&i&=&0;&i&getParent()->getPosition().getDistance(monster->baseSprite->getPosition());//算坐标距离&&
&&&&if&(distance&getAttackByTower())&{&//当在塔的范围内,且怪物可以被攻击(某些地下怪物只有钻出地面可以被攻击)&&
&&&&&&&&currMinDistant&=&//设置最小距离,找到最近的怪物&&&&
&&&&&&&&nearestMonster&=&
}&}}其中计算距离的时候有个getParent()是因为每个防御塔是建造在一个Terrain精灵类上面,这样的好处是1原版游戏在建造点建造防御塔时,可以看到建造点扔在防御塔下面,2即使防御塔被卖掉,建造点扔在,不用重新去生成,方便管理(我是这么设计的...)然后就是关键的shoot方法了,炮塔,弓箭塔,法师塔的原理基本一样,只是攻击的动画和轨迹计算不同而已,只有兵营塔略微不同,这些都将在下一章讲解。。。通过setLinstener()给防御塔设置触摸时间:void&BaseTower::setListener()&&
&&auto&listener&=&EventListenerTouchOneByOne::create();&&
&&listener->onTouchBegan&=&CC_CALLBACK_2(BaseTower::onTouchBegan,&this);&&
&&listener->onTouchEnded&=&CC_CALLBACK_2(BaseTower::onTouchEnded,&this);&&
&&_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,terrain);&&
}对触摸事件进行相应处理:不拦截Touchbool&BaseTower::onTouchBegan(Touch&*touch,&Event&*event)&&
&&&&return&&&
void&BaseTower::onTouchEnded(Touch*&touch,&Event*&event)&&
&&&&auto&target&=&static_cast(event->getCurrentTarget());&&
&&&&Point&locationInNode&=&target->convertTouchToNodeSpace(touch);&&
&&&&Size&size&=&target->getContentSize();&&
&&&&Rect&rect&=&Rect(0,&0,&size.width,&size.height);&&
&&&&if&(rect.containsPoint(locationInNode))//当触摸点在防御塔内(即点击防御塔,目前只能通过此方法来判断是否点击防御塔)&&
&&&&{&&&&&
&&&&&&static_cast(this->getParent()->getParent())->playerState->showTowerInfo(getTowerType());//调用父父布局(BaseMap)的PlayState层,显示防御塔信息&&
&&&&&&if(isUpdateMenuShown)//如果防御塔升级界面已经显示,则隐藏,某种显示&&
&&&&&&&&hideUpdateMenu();&&
&&&&&&}else{&&
&&&&&&&&showUpdateMenu();&&
&&&&}else{//触摸点在外面则隐藏防御塔升级界面&&
&&&&&&hideUpdateMenu();&&
}首先我们先观察下这个游戏的箭塔:这个游戏的箭塔都是拥有两个弓箭手。以初级塔为例,左右两边分别有两个弓箭手,可以攻击不同的目标,并且同时只有一个弓箭手在攻击。根据这个特性我们写一个BaseArrowTower:class&BaseArrowTower:&public&BaseTower&&
&&&&public:&&
&&&&protected:&&
&&&&Sprite*&shooter_1;//弓箭手1号&&
&&&&Sprite*&shooter_2;//弓箭手2号&&
&&&&Sprite*&towerB//塔&&
&&&&int&shootT//弓箭手标记&&
&&&&void&initTower(int&level);//初始化弓箭塔&&
&&&&void&addTerrain();//添加塔坯子(就是那个都是塔下面那个都是弓箭的地面,不同地图有不同的坯子~)&&
&&&&virtual&Bullet*&ArrowTowerBullet();//生成弓箭&&
&&&&virtual&void&shoot(float&dt);//射!&&
};现在让我们看下防御塔建造过程:1.选择建造类型2.执行建造动画(进度条,冒烟等)3.去除动画精灵,添加防御塔4.开始攻击同样用1级箭塔举例class&SimpleArrowTowerlvl1:&public&BaseArrowTower&&
&&&&public:&&
&&&&bool&init();//初始化&&
&&&&&&&&CREATE_FUNC(SimpleArrowTowerlvl1);&&
&&&&void&updateTower();//升级&&
&&&&void&showUpdateMenu();//显示升级菜单&&
&&&&Bullet*&ArrowTowerBullet();//生成弓箭&&
&&&&private:&&
&&&&void&buildingAnimation();//开始建造动画&&
&&&&void&buildingSmokeAnimation(float&dt);&&
};其中init()函数会由BaseArrowTower中的CREATE_FUNC宏自动执行,在init()中依次初始化各个参数,并且执行建造动画buildingAnimation其中建造动画就是添加进度条、建造动画精灵等动作:void&SimpleArrowTowerlvl1::buildingAnimation()&&
&&&&auto&building&=&Sprite::create();&&
&&&&auto&constructing&=&Sprite::createWithSpriteFrameName("tower_constructing_0004.png");&&
&&&&auto&hpBgSprite&=&Sprite::createWithSpriteFrameName("buildbar_bg.png");&&
&&&&hpBgSprite->setPosition(Point(constructing->getContentSize().width&/&2,&constructing->getContentSize().height&/2+10));&&
&&&&auto&hpBar&=&ProgressTimer::create(Sprite::createWithSpriteFrameName("buildbar.png"));&&
&&&&hpBar->setType(ProgressTimer::Type::BAR);&&
&&&&hpBar->setMidpoint(Point(0,&0.5f));&&
&&&&hpBar->setBarChangeRate(Point(1,&0));&&
&&&&hpBar->setPercentage(0);&&
&&&&hpBar->setPosition(Point(hpBgSprite->getContentSize().width&/&2,&hpBgSprite->getContentSize().height&/&2&));&&
&&&&hpBgSprite->addChild(hpBar);&&
&&&&constructing->addChild(hpBgSprite);&&
&&&&building->addChild(constructing);&&
&&&&addChild(building);&&
&&&&hpBar->runAction(Sequence::create(ProgressTo::create(0.5f,&100)&&
&&&&,&CallFuncN::create(CC_CALLBACK_0(Sprite::removeFromParent,&building))&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&,&NULL));&&
&&&&scheduleOnce(schedule_selector(SimpleArrowTowerlvl1::buildingSmokeAnimation),0.5f);&&
}hpBar->runAction(Sequence::create(ProgressTo::create(0.5f, 100), CallFuncN::create(CC_CALLBACK_0(Sprite::removeFromParent, building)), NULL));是执行一个动画序列,首先是执行进度条的动画,时间0.5秒,从0-100,再执行removeFromParent将建造动画精灵移除。再延迟0.5S执行scheduleOnce(schedule_selector(SimpleArrowTowerlvl1::buildingSmokeAnimation),0.5f);执行一个冒烟动画然后将塔添加进去(当然这里也可以写到上面的动画序列当中)void&SimpleArrowTowerlvl1::buildingSmokeAnimation(float&dt)&&
&&&&auto&smoke&=&Sprite::createWithSpriteFrameName("effect_buildSmoke_0001.png");&&
&&&&addChild(smoke,99);&&
&&&&smoke->runAction(Sequence::create(&&
&&&&&&&&Animate::create(AnimationCache::getInstance()->getAnimation("build_smoke")),&&
&&&&&&&&CallFuncN::create(CC_CALLBACK_0(Sprite::removeFromParent,&smoke)),&&
&&&&&&&&NULL));&&
&&&&SoundManager::playArcherReady();&&
&&&&initTower(1);&&
&&&&setListener();&&
&&&&schedule(schedule_selector(SimpleArrowTowerlvl1::shoot),&1.0f);&&
}并在1S后开始执行shoot攻击敌人:void&BaseArrowTower::shoot(float&dt)&&
&&&&auto&instance&=&GameManager::getInstance();&&
&&&&checkNearestMonster();&&
&&&&char&temp1[20];&&&
&&&&sprintf(temp1,&"level%d_shoot_down",&level);&&&
&&&&char&temp2[20];&&&
&&&&sprintf(temp2,&"level%d_shoot_top",&level);//根据等级生成图片名,保存临时变量&&
&&&&if(nearestMonster!=NULL&&&&nearestMonster->getCurrHp()&>&0&)&&
&&&&auto&currBullet&=&ArrowTowerBullet();&&
&&&&Point&shootVector&=&nearestMonster->baseSprite->getPosition()&-&this->getParent()->getPosition();
&&&&//怪物精灵是在地图上添加的,而塔的父精灵才是在地图上添加的,所以要统一标准计算&&
&&&&//计算防御塔与敌人之间的角度&&
&&&&float&startAngle&=&currBullet->getRotation();&&
&&&&float&endAngle&=&0;&&
&&&&auto&pVectr&=&currBullet->getPosition()-shootV&&
&&&&&&&&float&angleRadians=atan(pVectr.y/pVectr.x);&&
&&&&&&&&float&angleDegrees&=&CC_RADIANS_TO_DEGREES(angleRadians);&&
&&&&&&&&&&
&&&&if(shootVector.x&-&currBullet->getPosition().xsetPosition(Point(0,30));//子弹设置在弓箭手所在位置&&&&
&&&&&&&&shooter_1->setFlippedX(true);//X轴翻转,即面向左边&&
&&&&&&&&if(shootVector.y&-&currBullet->getPosition().yrunAction(Animate::create(AnimationCache::getInstance()->getAnimation(temp1)));&&
&&&&&&&&}else{&&
&&&&&&&&&&&&shooter_1->runAction(Animate::create(AnimationCache::getInstance()->getAnimation(temp2)));&&
&&&&&&&&}&&
&&&&&&&&&&&&shootTag&=&2;&&
&&&&&&&&}&&
&&&&&&&&&&&&else//轮到2号弓箭手&&
&&&&&&&&{&&
&&&&&&&&&&&&currBullet->setPosition(Point(10,30));&&&&&&&&&
&&&&&&&&&&&&shooter_2->setFlippedX(true);&&
&&&&&&&&&&&&if(shootVector.y&-&currBullet->getPosition().yrunAction(Animate::create(AnimationCache::getInstance()->getAnimation(temp1)));&&
&&&&&&&&&&&&}else{&&
&&&&&&&&&&&&shooter_2->runAction(Animate::create(AnimationCache::getInstance()->getAnimation(temp2)));&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&shootTag&=&1;&&
&&&&&&&&&&&&}&&
&&&&&&&&}else//敌人在右边,其他同上&&
&&&&&&&&{&&
&&&&&&&&&&&&startAngle&=&startAngle&-&abs(angleDegrees);&&
&&&&&&&&&&&&endAngle&=&270;&&
&&&&&&&&&&&&if(shootTag&==&1)&&
&&&&&&&&&&&&{&&
&&&&&&&&&&&&currBullet->setPosition(Point(0,30));&&&&&&&&&&
&&&&&&&&&&&&shooter_1->setFlippedX(false);&&
&&&&&&&&&&&&if(shootVector.y&-&currBullet->getPosition().yrunAction(Animate::create(AnimationCache::getInstance()->getAnimation(temp1)));&&
&&&&&&&&&&&&}else{&&
&&&&&&&&&&&&&&&&shooter_1->runAction(Animate::create(AnimationCache::getInstance()->getAnimation(temp2)));&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&shootTag&=&2;&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&else&&
&&&&&&&&&&&&{&&
&&&&&&&&&&&&currBullet->setPosition(Point(10,30));&&&&&&&&&
&&&&&&&&&&&&shooter_2->setFlippedX(false);&&
&&&&&&&&&&&&if(shootVector.y&-&currBullet->getPosition().yrunAction(Animate::create(AnimationCache::getInstance()->getAnimation(temp1)));&&
&&&&&&&&&&&&}else{&&
&&&&&&&&&&&&&&&&shooter_2->runAction(Animate::create(AnimationCache::getInstance()->getAnimation(temp2)));&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&shootTag&=&1;&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&&&&&//贝叶斯弧线&&
&&&&&&&&ccBezierConfig&&&
&&&&&&&&if(shootTag&==&1)//播放射箭音效&&
&&&&&&&&&&&&SoundManager::playArrowShoot1();&&
&&&&&&&&else&&
&&&&&&&&&&&&SoundManager::playArrowShoot2();&&
&&&&&&&&//计算贝叶斯曲线的两个控制点&&
&&&&&&&&bezier.controlPoint_1&=&Point(currBullet->getPosition().x,currBullet->getPosition().y+200);&&&
&&&&&&&&bezier.controlPoint_2&=&Point(shootVector.x,shootVector.y+200);;&&&
&&&&&&&&bezier.endPosition&=&shootV&&
&&&&&&&&auto&action&=&Spawn::create(BezierTo::create(0.5f,&bezier),RotateTo::create(0.5f,endAngle),NULL);&&
&&&&&&&&//攻击动画传递弓箭&&
&&&&&&&&currBullet->setBulletAction(action);&&
&&&&&&&&currBullet->shoot();&&
&&&&&&&&currBullet&=&NULL;&&
}根据角度使用ccBezierConfig类来生成BezierTo移动动画,是一个弧线,具体内容百度的到然后用Spwan将BezierTo与弓箭旋转动画合成为一个action,将action传递给子弹类,由子弹类具体执行,为何不在塔类中执行,将在子弹章节中讲解。执行子弹类的shoot,攻击动画完成。推荐阅读:
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量6196点击量4498点击量3643点击量3608点击量3282点击量2862点击量2792点击量2729点击量2643
&2016 Chukong Technologies,Inc.
京公网安备89}

我要回帖

更多关于 英雄联盟防御塔 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信