Cocos2d-x 3.2 lua飞机大战开发实例(二)敌机类的封装,以及碰撞检测的实现

时间:2022-06-01 18:58:11

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,x,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   true down

self.flyWidth=30 --摇摆的幅度

self.flyX=0  --当前的摇摆值

 

self.count=0          --控制移动的逻辑执行的次数

 

end

 

--init()

function Enemy:init(t,x,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,0,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",cc.rect(0,0,87,100))

     local sf2=cc.SpriteFrame:create("fonts/Resources/ld1.png",cc.rect(87,0,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==2 then

   local sf1=cc.SpriteFrame:create("fonts/Resources/ld2.png",cc.rect(0,0,87,100))

     local sf2=cc.SpriteFrame:create("fonts/Resources/ld2.png",cc.rect(87,0,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))

  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

             --摇摆

           ifself.dirH then --向右摇摆

              self.ex=self.ex+self.flyX--敌机的横坐标+摇摆的值

           else

                self.ex=self.ex-self.flyX--敌机的横坐标摇摆的值

           end

           self.flyX=self.flyX+3       --当前的摇摆值

           ifself.flyX>self.flyWidththen--如果当前的摇摆值大于摇摆的幅度

              self.flyX=0              --摇摆值归0

              self.dirH=notself.dirH   --反向

           end

       elseif self.type==2 then

            --飞到屏幕的*向两侧飞行

            ifself.ey>=self.winsize.height/2then

             self.ey=self.ey-2       --如果在屏幕中间的上方就让它不断乡下走         

            else

                self.ex=self.ex+5       --向右走

                ifself.ex>self.winsize.widththen   --如果大于屏幕的宽度

                

                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--mathlua中的基本函数。math.random()它产生的是0~1的随机数,*3之后变成1~3的随机数

     local etype=0   --敌机的类型

     if num>2 andnum<=3 then etype=2end

      if num>1 andnum<=2 then etype=1end

      if num>0 andnum<=1 then etype=0end

     --创建敌机--产生随机的类型--产生随机的飞机坐标

     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.indexOfAllEnemythen

                            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              --i1循环到g_allbullet的长度

           localnowbullet=g_allBullet[i]   --获取第i个子弹

           forj=1,#g_allEnemydo

                localnowe=g_allEnemy[j]

                localrect1=cc.rect(nowbullet.bx,nowbullet.by,7,10)

                localrect2=cc.rect(nowe.ex,nowe.ey,87,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.indexOfAllEnemythen

                            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.indexOfAllEnemythen

                        g_allEnemy[i].indexOfAllEnemy=g_allEnemy[i].indexOfAllEnemy-1

                    end

                end

                self:unscheduleUpdate()

--这样就基本上实现了子弹和敌机碰撞检测了,只是一些效果还没有添加