这一篇我们来讲游戏中的植物是怎么实现的,在这个游戏Demo中,我们就不一一的把所有的植物都写出来的,在这里我们就写豌豆射手Pease(攻击型植物),向日葵SunFlower(生产型植物)以及坚果Nut(防御性植物)这三种,其中豌豆射手需要发射豌豆,也就是子弹,所有我们也要创建一个豌豆子弹类PeaseBullet来作为豌豆射手的子弹,向日葵能够生产太阳,所以我们也要创建一个太阳类Sun。
我们先来看看豌豆子弹PeaseBullet的创建,在src/app/下创建一个bullet文件夹,然后在该文件夹下创建PeaseBullet类,这个类很简单,我们看下面代码:
local PeaseBullet = class("PeaseBullet",function()
return display.newSprite("fight/bullet.png")
end)
function PeaseBullet:ctor()
self:setScale(0.5)
-- 子弹的攻击力,由豌豆射手决定
self.attackValue=0
end
-- 子弹小时的时候回调函数 self:getParent()就是豌豆射手 bullets是它的一个属性--弹夹,用来存放发射出来的子弹统一管理
function PeaseBullet:over()
-- 从弹夹中移除自身
table.removebyvalue(self:getParent().bullets, self)
self:removeFromParent()
end
return PeaseBullet
植物和僵尸一样,也分为很多种,那么他们也有一个共同的父类---植物基类,我们先来看看基类,
在src/app/下创建一个plant文件夹,然后在该文件夹下创建PlantBase类
local scheduler = require(cc.PACKAGE_NAME .. ".scheduler")
local PlantBase = class("PlantBase",function()
return display.newNode()
end)
function PlantBase:ctor(path)
-- 植物血量
self.currentHP=0
-- 攻击力
self.attackValue=0
-- 所在行列
self.row=0
self.col=0
self.plant=display.newSprite(string.format(path,1))
:align(display.LEFT_BOTTOM, 0, 0)
:addTo(self)
self.plant:setScale(0.5)
self:setContentSize(cc.size(self.plant:getContentSize().width*0.5, self.plant:getContentSize().height*0.5))
self:setAnchorPoint(cc.p(0.5,0.5))
end
-- 播放动画的函数,和僵尸基类是一样的,这里就不多说了
function PlantBase:palyAnim(animKey,imageNum,path)
local animation=display.getAnimationCache(animKey)
if animation==nil then
animation=cc.Animation:create()
local rect={x=0,y=0,width=self.plant:getContentSize().width,height=self.plant: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
self.plant:runAction(cc.RepeatForever:create(cc.Animate:create(animation)))
end
-- 获取植物的BoundingBox
function PlantBase:getRect()
return cc.rect(self:getPositionX()-self:getContentSize().width/2,self:getPositionY()-self:getContentSize().height/2,
self:getContentSize().width,self:getContentSize().height)
end
-- 植物被攻击 参数为敌方攻击力
function PlantBase:hurted(hurtValue)
-- 血量减少
self.currentHP=self.currentHP-hurtValue
-- 如果血量小于0
if self.currentHP<=0 then
-- 植物将会消失,随意对应的行列位置又可以放置植物
self:getParent().lawnMatrix[self.row][self.col]=true
-- 从植物列表中删除
table.removebyvalue(self:getParent().allPlants, self)
-- 如果植物攻击力为0,则是非攻击型植物,从非攻击性植物列表中移除
if self.attackValue==0 then
table.removebyvalue(self:getParent().defensePlants, self)
-- 否则则是攻击型植物,从攻击性植物列表中移除
else
table.removebyvalue(self:getParent().attackPlants, self)
end
self:removeFromParent()
end
end
function PlantBase:getTwoPosDistance(x1,y1,x2,y2)
return math.sqrt(math.pow(math.abs(x1-x2), 2)+math.pow(math.abs(y1-y2), 2))
end
return PlantBase
植物基类就创建好了,现在我们来创建豌豆射手Pease,在plant文件夹下创建
local scheduler = require(cc.PACKAGE_NAME .. ".scheduler")
local PlantBase = require("app.plant.PlantBase")
local PeaseBullet = require("app.bullet.PeaseBullet")
local Pease = class("Pease",function()
return PlantBase.new("plant/pease/p_2_%02d.png")
end)
function Pease:ctor()
self.currentHP=10
self.attackValue=1
self:palyAnim("peaseAnim",8,"plant/pease/p_2_%02d.png")
-- 发射子弹的速度
self.speed=10
-- 每隔一秒检测和植物在同一行上有木有僵尸
local repeatFunction=cc.RepeatForever:create(cc.Sequence:create(cc.DelayTime:create(1.0),cc.CallFunc:create(function()
self:cheak()
end)))
self:runAction(repeatFunction)
end
-- 每隔一秒检测和植物在同一行上有木有僵尸
function Pease:cheak()
-- 遍历僵尸集合
for i,zombies in ipairs(self:getParent().zombiesList) do
-- 如果在同一行上有僵尸
if zombies.row==self.row then
-- 攻击
self:launch()
end
end
end
function Pease:launch()
-- 创建子弹加载豌豆射手嘴巴位置
local bullet=PeaseBullet.new()
:pos(self:getPositionX()+self:getContentSize().width/4, self:getPositionY()+self:getContentSize().height/4)
-- :pos(self:getPositionX(),self:getPositionY())
:addTo(self:getParent())
-- 子弹的攻击力就是植物的攻击力
bullet.attackValue=self.attackValue
-- 将子弹放入弹夹中统一管理
table.insert(self:getParent().bullets,bullet)
-- 打出去,也就是移动,终点是移除屏幕,在这个过程我们会启动帧事件来进行碰撞检测
local move=cc.MoveTo:create((display.width-bullet:getPositionX())/self.speed,cc.p(display.width,bullet:getPositionY()))
bullet:runAction(cc.Sequence:create(move,cc.CallFunc:create(function()
-- 如果子弹一到终点,飞出屏幕外了,从弹夹中移除
table.removebyvalue(self:getParent().bullets, bullet)
bullet:removeFromParent()
end)))
end
return Pease
这一篇就先讲豌豆射手的实现,下一篇我们来讲向日葵和坚果的实现