游戏的一个重要逻辑就是黄色小车变换轨道,红色小车在玩家的控制下避开黄色小车以免发生碰撞,红色小车变轨是玩家控制的,而黄色小车是自动变轨的。上篇博客我们将红色小车和黄色小车的运动分开做了处理,本篇博客就实现一下黄色小车的运动,使黄色小车可以自动变轨。我们将黄色小车的变轨放到固定的俩个点处,一个是由外圈轨道进入到内圈轨道处,另一个是由内圈轨道进入到外圈轨道处。小车在运动的过程中,通过概率来计算是否要进入到内圈轨道,在内圈轨道的时候同样通过概率来决定是否要出去到外圈的轨道处,整个代码和红色小车相比真是简单多了。

Lua小游戏别撞车——实现小车AI

function MainGameScene:runYelloCar(car)

    --返回执行里圈轨道或者外圈轨道的动作
    local function getAction()
        --初始化运动过程中需要的成员变量 代表外圈的轨道
        local y1 = self.track_size.height*0.445
        local y2 = -y1
        local point1 = cc.p(self.track_size.width*0.245,self.car_bottomy)
        local point2 = cc.p(self.track_size.width*0.745,self.car_topy)

        --判断执行里圈的轨道还是外圈的轨道
        local switch = self.yello_switch
        --代表里圈的轨道
        if switch then
            y1 = self.track_size.height*0.335
            y2 = -y1
            point1 = cc.p(self.track_size.width*0.245,self.track_size.height*0.171)
            point2 = cc.p(self.track_size.width*0.745,self.track_size.height*0.844)
        end

        --[[根据速率计算小车需要运动的时间--]]
        local rate = math.pi*self.track_size.height*0.3
        --圆周运动的时间
        local tm = math.pi*y1/rate
        --直线运动的时间
        local tm2 = (self.track_size.width*0.5)/rate

        --创建动作
        local circle1 = tt.CircleBy:create(tm,{x=0,y=y1},180)
        local spawn1 = cc.Spawn:create(circle1:reverse(),cc.RotateBy:create(tm,-180))
        local move2 = cc.MoveTo:create(tm2,{x=point1.x,y=point2.y})
        local circle2 = tt.CircleBy:create(tm,{x=0,y=y2},180)
        local spawn2 = cc.Spawn:create(circle2:reverse(),cc.RotateBy:create(tm,-180))
        local move1 = cc.MoveTo:create(tm2,{x=point2.x,y=point1.y})

        return tm,tm2,spawn1,move2,spawn2,move1
    end

    local tm,tm2,spawn1,move2,spawn2,move1 = getAction()

    --获得一个随机数
    math.randomseed(os.time())
    local r = math.random(0,100)
    --只有当小车在外部的轨道,并且满足概率的时候才会进入内部的轨道
    if r > 50 and (self.yello_switch == false) then
        --变轨固定在这个点 进入内部的轨道
        local circle1 = cc.Spawn:create(tt.CircleBy:create(tm/2,{x=-30,y=self.track_size.height*0.4},-90),cc.RotateBy:create(tm/2,-90))
        local circle2 = cc.Spawn:create(tt.CircleBy:create(tm/2,{x=-162,y=self.track_size.height*0.0015},-90),cc.RotateBy:create(tm/2,-90))
        spawn1 = cc.Sequence:create(circle1,circle2)
        --代表里圈轨道
        self.yello_switch = true
        tm,tm2,_,move2,spawn2,_ = getAction()
    end

    r = math.random(0,100)
    if r > 50 and (self.yello_switch == true) then
        --变轨固定在这个点 转到外部的轨道
        local circle1 = cc.Spawn:create(tt.CircleBy:create(tm/2,{x=-25,y=-self.track_size.height*0.4},-90),cc.RotateBy:create(tm/2,-90))
        local circle2 = cc.Spawn:create(tt.CircleBy:create(tm/2,{x=225,y=self.track_size.height*0.02},-90),cc.RotateBy:create(tm/2,-90))
        spawn2 = cc.Sequence:create(circle1,circle2)
        --代表外圈轨道
        self.yello_switch = false
    end

    --执行完毕一圈以后重新执行动作,这样轨道就是随机的
    local callfunc = cc.CallFunc:create(function()
        self:runYelloCar(self.car_yello)
    end)

    --动作序列
    local action_yello = cc.Sequence:create(move1,spawn1,move2,spawn2,callfunc)
    action_yello:setTag(2)

    car:runAction(action_yello)
end

小车是否变轨是通过随机数来判断的,这里获取随机数是使用了Lua中的数学库,同样先设置一个随机数种子,然后获取随机数,math.random(0,100)的含义是获取0-100之间的一个随机数,包括0和100。如果确定了变轨,我们会新创建一个动作来取代原来的半圆周运动,这个新的圆周运动其实是俩个四分之一的圆周运动叠加起来的,这里所有的参数都是我自己调节的,可能不是非常准确,不过最后的效果还算可以。最后小车执行的动作系列并不是repeat的,而是在执行完毕当前的动作序列以后重新调用runYelloCar函数,这样是否变轨就是随机了。