Cocos2d-x 3.2 lua飞机大战开发实例(二)敌机类的封装,以及碰
Cocos2d-X 3.2 lua语言飞机大战开发实例(二)1.敌机类的封装以及碰撞检测 -- Enemy的类中 require "Cocos2d" local Enemy=class("Enemy",function () return cc.Node:create() end) function Enemy:create(t,x,y) local enemy=Enemy.new() enemy:addChild(enemy:init(t,y)) return enemy end --构造 function Enemy:ctor() self.winsize=cc.Director:getInstance():getWinSize() self.ex=0 self.ey=0 self.type=0 self.dirH=true --真为rigth 假为left self.dirV=true --false up truedown self.flyWidth=30 --摇摆的幅度 self.flyX=0 --当前的摇摆值
self.count=0 --控制移动的逻辑执行的次数 end --init() function Enemy:init(t,y) local layer=cc.Layer:create() local sp=cc.Sprite:create() layer:addChild(sp) --敌机动画 if t==0 then --动画的每一帧 local sf1=cc.SpriteFrame:create("fonts/Resources/ld1.png",cc.rect(0,0,87,100)) local sf2=cc.SpriteFrame:create("fonts/Resources/ld1.png",cc.rect(87,100)) local allf={sf1,sf2} --创建动画 local animation=cc.Animation:createWithSpriteFrames(allf,0.1) local animate=cc.Animate:create(animation) sp:runAction(cc.RepeatForever:create(animate))
elseif t==1 then local sf1=cc.SpriteFrame:create("fonts/Resources/ld1.png",0.1) local animate=cc.Animate:create(animation) sp:runAction(cc.RepeatForever:create(animate)) elseif t==2 then local sf1=cc.SpriteFrame:create("fonts/Resources/ld2.png",100)) local sf2=cc.SpriteFrame:create("fonts/Resources/ld2.png",0.1) local animate=cc.Animate:create(animation) sp:runAction(cc.RepeatForever:create(animate)) end
--设置坐标 sp:setPosition(x,y) self.ex=x self.ey=y self.type=t --计划任务,然敌机自动向下飞 local function logic(t) self.count=self.count+1 -—控制它的帧率 if self.count<5 then return else self.count=0 end if self.type==0 then --自动向下飞 self.ey=self.ey-10 if self.ey<0 then
self:removeFromParent()--移除 return end elseif self.type==1 then --左右摇摆向下飞 self.ey=self.ey-2 if self.ey<0 then self:removeFromParent()--移除 return end --摇摆 if self.dirH then --向右摇摆 self.ex=self.ex+self.flyX--敌机的横坐标+摇摆的值 else self.ex=self.ex-self.flyX--敌机的横坐标—摇摆的值 end self.flyX=self.flyX+3 --当前的摇摆值 if self.flyX>self.flyWidth then--如果当前的摇摆值大于摇摆的幅度 self.flyX=0 --摇摆值归0 self.dirH=not self.dirH --反向 end elseif self.type==2 then --飞到屏幕的中央向两侧飞行 if self.ey>=self.winsize.height/2 then self.ey=self.ey-2--如果在屏幕中间的上方就让它不断乡下走 else self.ex=self.ex+5--向右走 if self.ex>self.winsize.width then --如果大于屏幕的宽度
self:removeFromParent() --就移除 return end
end
end
sp:setPosition(self.ex,self.ey) --敌机的坐标 end sp:scheduleUpdateWithPriorityLua(logic,0) --让这个敌机执行它的计划任务
return layer end return Enemy --这样我们就实现好了敌机类的封装,下面我们就从GameScene中再添加敌机 2.在GameScene的init()中 跟飞机产生子弹的原理一致,首先需要在构造函数中添加一个计数器 self.countEnemy=0 --敌机产生的计数器 --添加敌机 --添加敌机 local function newEnemy(t) self.countEnemy=self.countEnemy+1 if self.countEnemy>=120 then --产生敌机 local newEnemy=require("nodes.Enemy") --产生随机数--把type定义成随机数 local num=math.random()*3--math是lua中的基本函数。math.random()它产生的是0~1的随机数,*3之后变成1~3的随机数 local etype=0 --敌机的类型 if num>2 and num<=3 then etype=2 end if num>1 and num<=2 then etype=1 end if num>0 and num<=1 then etype=0 end --创建敌机--产生随机的类型--产生随机的飞机坐标 local ne=newEnemy:create(etype,math.random()*self.winsize.width,self.winsize.height) layer:addChild(ne)
self.countEnemy=0 end end --给敌机计划任务 local node2=cc.Node:create() layer:addChild(node2) node2:scheduleUpdateWithPriorityLua(newEnemy,0) -- 3.碰撞检测的实现,首先要确定的是思路,我们该怎么取到子弹和敌机呢?这样做。。。 产生子弹时,我们不但要将子弹添加到layer中,还要定义table,将子弹添加到table中 在GameData全局数据中定义: g_allBullet={}—保存所有的子弹 g_allEnemy={}—保存所有的敌机 我们在子弹类的构造函数中,定义: self.indexInAllBullet=0 --当前这个子弹在table集合中的编号 在这里子弹节点删除时,还要将子弹从全局表中删除 table.remove(g_allBullet,self.indexInAllBullet) --调整编号 for i=1,#g_allBullet do if g_allBullet[i].indexInAllBullet>self.indexInAllBulletthen g_allBullet[i].indexInAllBullet=g_allBullet[i].indexInAllBullet-1 end end self.unscheduleUpdate() 在GameScene中子弹产生,添加到layer的同时也要添加这个子弹到全局数据里 newb.indexInAllBullet=#g_allBullet+1 --记录当前这颗子弹在这个集合中的下标是几 g_allBullet[#g_allBullet+1]=newb --#号能够返回这个table中有多少个数据!+1是下标从1开始 --print("目前子弹的个数"..tostring(#g_allBullet))—-每产生一个子弹都再g_allBullet中 --~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 同理,我们也需要将敌机做这样的处理 我们在敌机类的构造函数中,也需要加一个成员属性: self.indexInAllEnemy=0 --当前这个敌机在table集合中的编号 --在这里敌机节点删除时,还要将敌机从全局表中删除 table.remove(g_allEnemy,self.indexInAllEnemy) --删除这个表中的这个元素 --后续编号-- for i=1,#g_allEnemydo if g_allEnemy[i].indexOfAllEnemy>self.indexOfAllEnemy then g_allEnemy[i].indexOfAllEnemy=g_allEnemy[i].indexOfAllEnemy-1 end end self:unscheduleUpdate() 在GameScene中敌机产生,添加到layer的同时也要添加这个敌机到全局table里 --把这个敌机添加到全局的table中 ne.indexOfAllEnemy=#g_allEnemy+1--记录当前这个敌机在这个集合中的下标是几 g_allEnemy[#g_allEnemy+1]=ne --#号能够返回这个table中有多少个数据!+1是下标从1开始 --print("目前敌机的数量"..tostring(#g_allEnemy))
--实际上我们的做到这里只是为了做碰撞检测的一个前提,我们已经把所有的敌机和子弹都转化成了table中的数据这样我们就可以实现访问敌机和子弹了—接下来我们就该做碰撞检测了 4.碰撞检测 --增加碰撞检测逻辑 local function gamelogic(t) --碰撞检测 --i就是第i个元素,v就是第i个元素的值,v,还可以写成nowbullet,g_allBullet返回的是这个元素的编号 --for i,nowbullet in pairs(g_allBullet) do -- for j,nowenemy inpairs(g_allEnemy) do -- -- -- end --end for i=1,#g_allBullet do--i从1循环到g_allbullet的长度 local nowbullet=g_allBullet[i] --获取第i个子弹 for j=1,#g_allEnemy do local nowe=g_allEnemy[j] local rect1=cc.rect(nowbullet.bx,nowbullet.by,7,10) local rect2=cc.rect(nowe.ex,nowe.ey,50) --print(nowe.ex..","..nowe.ey..","..nowbullet.bx..","..nowbullet.by) if cc.rectIntersectsRect(rect1,rect2) then
--子弹消失 table.remove(g_allBullet,nowbullet.indexInAllBullet)--从全局表里删除自己--table表中的第i个元素消失 --后续编号-- for i=1,#g_allBulletdo if g_allBullet[i].indexInAllBullet>nowbullet.indexInAllBulletthen g_allBullet[i].indexInAllBullet=g_allBullet[i].indexInAllBullet-1 end end nowbullet:unscheduleUpdate() nowbullet:removeFromParent() --将本节点删除
--敌机消失 table.remove(g_allEnemy,nowe.indexOfAllEnemy) --后续编号-- for i=1,#g_allEnemydo if g_allEnemy[i].indexOfAllEnemy>nowe.indexOfAllEnemy then g_allEnemy[i].indexOfAllEnemy=g_allEnemy[i].indexOfAllEnemy-1 end end nowe:unscheduleUpdate() nowe:removeFromParent() --将本节点删除 break end end end end local node3=cc.Node:create() layer:addChild(node3) node3:scheduleUpdateWithPriorityLua(gamelogic,0) 5.在子弹的类这敌机的类中我们也要对后续的table表中的编号进行重整 子弹类的init()的移除子弹处,中我们这样做:
--后续编号-- for i=1,#g_allBullet do --要移除的是第i(self.indexInAllBullet)个子弹, 假如我们移除了第2个子弹,我们就让第3个子弹的编号变成2 if g_allBullet[i].indexInAllBullet>self.indexInAllBulletthen g_allBullet[i].indexInAllBullet=g_allBullet[i].indexInAllBullet-1 end end self:unscheduleUpdate() 6.在敌机的类中我们都需要对移除敌机时进行后续编号的一个处理 在敌机类的init()移除敌机中时: --后续编号-- for i=1,#g_allEnemydo if g_allEnemy[i].indexOfAllEnemy>self.indexOfAllEnemy then g_allEnemy[i].indexOfAllEnemy=g_allEnemy[i].indexOfAllEnemy-1 end end self:unscheduleUpdate() --这样就基本上实现了子弹和敌机碰撞检测了,只是一些效果还没有添加 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |