僵尸也是分类的,比如什么普通僵尸啊,铁桶僵尸啊之类的,所以我们要写一个僵尸的基类,叫做ZombiesBase,僵尸基类包含了僵尸都共同拥有的一些属性,僵尸的属性也比较多,有类型zombiesType,总血量totalHP,当前血量currentHP等等,僵尸也有各种动作,比如走路,吃植物,头掉下来等动画,所以基类要写一个播放动画的函数palyAnim,僵尸会随机从五条道路的其中一条出现,我们在前面的地图编辑器中以及创建了五个对象组,每个对象组中有两个对象,代表着僵尸的其实位置和终点位置,所以我们再写一个僵尸的move函数,让其从起始点走到终点,并回调结束游戏结束函数, 具体代码实现如下:
-- 僵尸基类
local scheduler = require(cc.PACKAGE_NAME .. ".scheduler")
local ZombiesBase = class("ZombiesBase",function()
return display.newNode()
end)
function ZombiesBase:ctor(type)
-- 僵尸类型
self.zombiesType=type
-- 总血量
self.totalHP=0
-- 当前血量
self.currentHP=0
-- 攻击力
self.attackValue=0
-- 速度
self.speed=0
-- 是否掉了头
self.isLoseHead=false
-- 僵尸前进的终点
self.endPos=nil
-- 道路所在行数
self.row=-1
-- 根据类型创建僵尸图片所在路径
self.path=string.format("zombies/zombies_%d/",self.zombiesType)
-- 创建僵尸
self.zombies=display.newSprite(string.format(self.path.."walk/z_%d_01.png",self.zombiesType))
:align(display.LEFT_BOTTOM,0)
:addTo(self)
self.zombies:setScale(0.5)
self:setContentSize(cc.size(self.zombies:getContentSize().width*0.5,self.zombies:getContentSize().height*0.5))
-- 僵尸的锚点,设置在脚下
self:setAnchorPoint(cc.p(0.5,0.3))
end
-- 僵尸播放动画的函数
-- animKey 缓存动画的key imageNum 帧数 path图片路径 isRepeat 动画是否循环 callBack回调函数
function ZombiesBase:palyAnim(animKey,imageNum,path,isRepeat,callBack)
local animation=display.getAnimationCache(animKey)
if animation==nil then
animation=cc.Animation:create()
local rect={x=0,y=0,width=self.zombies:getContentSize().width,height=self.zombies:getContentSize().height}
for i=1,imageNum do
animation:addSpriteFrame(cc.SpriteFrame:create(string.format(path,i),rect))
end
animation:setDelayPerUnit(0.2)
display.setAnimationCache(animKey,animation)
end
if self.animAction then
self.zombies:stopAction(self.animAction)
end
if isRepeat then
self.animAction=cc.RepeatForever:create(cc.Animate:create(animation))
else
self.animAction=cc.Sequence:create(cc.Animate:create(animation),cc.CallFunc:create(callBack))
end
self.zombies:runAction(self.animAction)
end
-- 僵尸的BoundingBox
function ZombiesBase:getRect()
return cc.rect(self:getPositionX()-self:getContentSize().width/2,self:getPositionY(),
self:getContentSize().width,self:getContentSize().height)
end
-- 僵尸的移动
function ZombiesBase:move()
-- 根据僵尸的行走距离以及移动速度获取僵尸的移动时间
local time=self:getTwoPosDistance(self:getPositionX(),self.endPos.x,self.endPos.y)/self.speed
self:runAction(cc.Sequence:create(cc.MoveTo:create(time,self.endPos),cc.CallFunc:create(function()
scheduler.unscheduleGlobal(self:getParent().addHandler)
self:getParent():unscheduleUpdate()
self:removeFromParent()
app:enterScene("GameOverScene",nil,"crossFade",1.0)
end)))
end
-- 两点间的距离
function ZombiesBase:getTwoPosDistance(x1,y1,x2,y2)
return math.sqrt(math.pow(math.abs(x1-x2),2)+math.pow(math.abs(y1-y2),2))
end
return ZombiesBase
以上就是僵尸基类的实现
在这里我们只创建一种僵尸,就是普通僵尸,普通僵尸继承上面我们创建的僵尸基类。
所以我们在src/app/zombies下创建NormalZombies.lua文件,代码如下:
local scheduler = require(cc.PACKAGE_NAME .. ".scheduler")
local ZombiesBase = require("app.zombies.ZombiesBase")
local NormalZombies = class("NormalZombies",function()
return ZombiesBase.new(NORMAL_ZOMBIES)
end)
function NormalZombies:ctor()
-- 初始化普通僵尸的数值
self.totalHP=10
self.currentHP=self.totalHP
self.attackValue=1
self.speed=30
self.isOnceLoseHead=true
self.isDie=false
self.isAttacking=false
self.isWalking=false
self.isLoseHead=false
-- 创建普通僵尸摇晃图片路径
local path=string.format(self.path.."shake/z_%d_",NORMAL_ZOMBIES).."%02d.png"
-- 默认僵尸动画为摇晃动画
self:palyAnim("normal_shake",2,true)
self.canAttack=true
end
-- 僵尸的走路动画
function NormalZombies:playWalk()
-- 如果僵尸不是走路状态
if not self.isWalking then
-- 如果僵尸没头
if self.isLoseHead then
local path=string.format(self.path.."work_losthead/z_%d_losthead_",NORMAL_ZOMBIES).."%02d.png"
self:palyAnim("normal_noHeadWalk",9,true)
else
local path=string.format(self.path.."walk/z_%d_",NORMAL_ZOMBIES).."%02d.png"
self:palyAnim("normal_walk",7,true)
end
self:move()
-- 非攻击状态
self.isAttacking=false
-- 走路状态
self.isWalking=true
end
end
-- 僵尸的攻击动画
function NormalZombies:playAttack()
if not self.isAttacking then
self:stopAllActions()
if self.isLoseHead then
local path=string.format(self.path.."attack_losthead/z_%d_attack_losthead_",NORMAL_ZOMBIES).."%02d.png"
self:palyAnim("normal_noHeadAttack",8,true)
else
local path=string.format(self.path.."attack/z_%d_attack_",NORMAL_ZOMBIES).."%02d.png"
self:palyAnim("normal_attack",10,true)
end
self.isAttacking=true
self.isWalking=false
end
end
-- 僵尸死亡动画
function NormalZombies:playDie()
-- 将僵尸从僵尸表中移除
table.removebyvalue(self:getParent().zombiesList,self)
self:stopAllActions()
-- 播放死亡动画 移除
local path=string.format(self.path.."die/z_%d_die_",NORMAL_ZOMBIES).."%02d.png"
self:palyAnim("normal_die",6,false,function()
self:removeFromParent()
end)
end
-- 掉头动画
function NormalZombies:playLoseHead()
-- 这里僵尸并没有在攻击状态和走路状态,设置为true只是为了让这两种动画无法执行
self.isAttacking=true
self.isWalking=true
self:stopAllActions()
local path=string.format(self.path.."head/z_%d_head_",NORMAL_ZOMBIES).."%02d.png"
self:palyAnim("normal_loseHead",function()
self.isLoseHead=true
self.isAttacking=false
self.isWalking=false
end)
end
-- 僵尸被攻击函数,参数为植物的攻击力
function NormalZombies:beAttacked(plantAttakValue)
-- 更新血量
self.currentHP=self.currentHP-plantAttakValue
-- 如果血量小于0,僵尸死亡,播放死亡动画
if self.currentHP<=0 and not self.isDie then
self.isDie=true
self:playDie()
-- 否则如果僵尸血量小于总的一般并且头颅还在,则播放掉头动画
elseif self.currentHP<=self.totalHP/2 and self.isOnceLoseHead then
self.isOnceLoseHead=false
self:playLoseHead()
end
end
-- 获取僵尸的攻击力
function NormalZombies:getAttackValue()
-- 僵尸每隔1秒攻击1次
if self.canAttack then
self.canAttack=false
scheduler.performWithDelayGlobal(function()
self.canAttack=true
end,1.0)
return self.attackValue
else
return 0
end
end
return NormalZombies
这样一来,僵尸也就创建好了