1. 程式人生 > >cocos2d-x lua 貪吃蛇完整專案

cocos2d-x lua 貪吃蛇完整專案

學習視訊見慕課網

開發環境,專案編譯執行

===

解壓到某個目錄下就行了,setup.py設定環境
這裡寫圖片描述

切換到如下的目錄,既可以建立lua專案
這裡寫圖片描述

shift +滑鼠右鍵,在該目錄下開啟cmd,輸入

cocos.py new Snake -l lua -d d:\

可以在D:\下建立一個Snake 專案,這些都是可選的,自己隨便玩

接著用vs2012 或者vs2013 開啟如下的解決方案,並完成編譯
這裡寫圖片描述

最後可以執行出結果,可在如下的目錄中執行,點選exe即可
這裡寫圖片描述

這裡寫圖片描述

有模擬器 和 日誌兩個視窗,在實際程式設計中需要多打日誌 和 檢視日誌 分析問題,並解決。

Hello World

===

類似cocos2d-x win32 C++ 功能
程式從 E:\workspace\cocos_lua\Snake\runtime\win32\src\下的main.lua開發,包括了各種配置等(如config.lua的一些螢幕顯示配置)

接著 src/app 目錄下有個 MyApp.lua,載入了 src/app/scenes/下的MainScene

而Mainscene就是繼承了Scene的一個場景了,可以看到有HelloWorld

因為繼承了場景類,所以需要重寫一些方法

void onExitTransitionDidStart();//2,建立完layer的時候呼叫,也就是1呼叫完之後呼叫  
void onEnter();//1,建立時呼叫 void onExit();//3,退出當前layer的時候呼叫,在這裡都是做一些清除工作 void onEnterTransitionDidFinish();//在3完成之後,呼叫該成員方法

所以我們需要在 onEnter(); 中寫各種東西,這樣就可以顯示Sprite, Button,Label等等了。

座標轉換

===

顯示蛇,首先需要重定義座標,認識螢幕的座標系統

這裡寫圖片描述

cGridSize 大小依據蛇身體圖片的大小而定,自定義一個轉換函式,方便用來設定Sprite的位置

local cGridSize = 33
local
scaleRate = 1 / display.contentScaleFactor -- 根據自定義的座標得到實際應該顯示的cocos2d-x座標位置 function Grid2Pos(x,y) local visibleSize = cc.Director:getInstance():getVisibleSize() -- 獲取整個手機可視螢幕尺寸 local origin = cc.Director:getInstance():getVisibleOrigin() -- 獲取手機可視屏原點的座標,螢幕的左上角 local finalX = origin.x + visibleSize.width / 2 + x * cGridSize * scaleRate local finalY = origin.y + visibleSize.height / 2 + y * cGridSize * scaleRate return finalX,finalY end

蛇身

===

有了上面的基礎,可以先顯示蛇身了

src/app 目錄下定義一個Body類,表示蛇身 , 有座標,是否頭部,其父節點等資訊,當然完全看自己如何弄

local Body = class("Body")

-- node為cocos2dx-父節點
function Body:ctor(snake , x, y, node, isHead)

    self.snake = snake
    self.X = x
    self.Y = y

    if isHead then -- 根據是否是頭部,用不同的圖片建立 
        self.sp = cc.Sprite:create("head.png")
    else
        self.sp = cc.Sprite:create("body.png")
    end

    node:addChild(self.sp) -- 新增到父節點

    self:Update()

end

-- 更新自己的位置
function Body:Update()
    local posx,posy = Grid2Pos(self.X , self.Y)
    self.sp:setPosition(posx,posy)
end

return Body

MainScene.lua中

local cGridSize = 33
local scaleRate = 1 / display.contentScaleFactor

-- 根據自定義的座標得到實際應該顯示的cocos2d-x座標位置
function Grid2Pos(x,y)

    local visibleSize = cc.Director:getInstance():getVisibleSize() -- 獲取整個手機可視螢幕尺寸

    local origin = cc.Director:getInstance():getVisibleOrigin() -- 獲取手機可視屏原點的座標,螢幕的左上角

    local finalX = origin.x + visibleSize.width / 2 + x * cGridSize * scaleRate
    local finalY = origin.y + visibleSize.height / 2 + y * cGridSize * scaleRate

    return finalX,finalY

end

-- require相應的類
local Body = require("app.Body") 

local MainScene = class("MainScene", function()
    return display.newScene("MainScene")
end)

function MainScene:onEnter() -- MainScene 載入執行
    -- 測試body
    self.body1 = Body.new(nil,0,0,self,true)

    self.body2 = Body.new(nil,2,2,self,false)
end

return MainScene

顯示如下,很預想的一樣,就證明沒有什麼錯誤了

這裡寫圖片描述

構造一條蛇

===

有了蛇身體,構造一條蛇就容易了
編寫一個蛇Snake類,利用Body類

Snake.lua


local Snake = class("Snake")

local Body = require("app.Body")

local cInitLen = 3 -- 蛇初始長度

-- 建構函式
function Snake:ctor(node)

    self.BodyArray = {} -- Body物件陣列
    self.node = node
    self.MoveDir = "left" -- 蛇的初始移動方向

    for i = 1,cInitLen do
        self:Grow(i == 1)
    end

end


--取出蛇尾
function Snake:GetTailGrid()
    if #self.BodyArray == 0 then -- 設定蛇頭的位置為(0,0)
        return 0,0
    end

    local tail = self.BodyArray[#self.BodyArray]

    return tail.X,tail.Y

end

-- 蛇變長
function Snake:Grow(isHead)

    local tailX,tailY = self:GetTailGrid()
    local body = Body.new(self,tailX,tailY,self.node,isHead)

    table.insert(self.BodyArray,body)

end

-- 根據方向改變座標
local function OffsetGridByDir(x,y,dir)
    if dir == "left" then
        return x - 1, y
    elseif dir == "right" then
        return x + 1, y
    elseif dir == "up" then
        return x, y + 1
    elseif dir == "down" then
        return x, y - 1
    end

    print("Unkown dir", dir)
    return x, y
end


-- 根據蛇的移動方向 更新蛇,就是BodyArray一個一個往前移動
function Snake:Update()

    if #self.BodyArray == 0 then
        return
    end

    for i = #self.BodyArray , 1 , -1 do

        local body = self.BodyArray[i]

        if i == 1 then -- 蛇頭位置 與 方向,得到一個新的位置 存放蛇頭
            body.X, body.Y = OffsetGridByDir(body.X, body.Y, self.MoveDir)
        else
            local front = self.BodyArray[i-1]
            body.X, body.Y = front.X, front.Y
        end

        body:Update()

    end

end


-- 取出蛇頭
function Snake:GetHeadGrid()
    if #self.BodyArray == 0 then
        return nil
    end

    local head = self.BodyArray[1]

    return head.X, head.Y

end

-- 設定方向
function Snake:setDir(dir)
        self.MoveDir = dir
end

return Snake

響應的MainScene.lua中也要調整下


local cGridSize = 33
local scaleRate = 1 / display.contentScaleFactor

-- 根據自定義的座標得到實際應該顯示的cocos2d-x座標位置
function Grid2Pos(x,y)

    local visibleSize = cc.Director:getInstance():getVisibleSize() -- 獲取整個手機可視螢幕尺寸

    local origin = cc.Director:getInstance():getVisibleOrigin() -- 獲取手機可視屏原點的座標,螢幕的左上角

    local finalX = origin.x + visibleSize.width / 2 + x * cGridSize * scaleRate
    local finalY = origin.y + visibleSize.height / 2 + y * cGridSize * scaleRate

    return finalX,finalY

end

-- require相應的類
-- local Body = require("app.Body")
local Snake = require("app.Snake")

local MainScene = class("MainScene", function()
    return display.newScene("MainScene")
end)

function MainScene:onEnter() -- MainScene 載入執行
        self.snake = Snake.new(self) -- 建立一條蛇
end

return MainScene

最後顯示如下,似乎看不到一條蛇,因為它們都重複了,我們需要是的蛇能夠動起來

這裡寫圖片描述

小蛇動起來

===

只需要設個定時器,重新整理螢幕就行了,所以在上面的基礎上,只需要加個定時器,更新小蛇就行了
修改MainScene.lua


local cGridSize = 33
local scaleRate = 1 / display.contentScaleFactor

-- 根據自定義的座標得到實際應該顯示的cocos2d-x座標位置
function Grid2Pos(x,y)

    local visibleSize = cc.Director:getInstance():getVisibleSize() -- 獲取整個手機可視螢幕尺寸

    local origin = cc.Director:getInstance():getVisibleOrigin() -- 獲取手機可視屏原點的座標,螢幕的左上角

    local finalX = origin.x + visibleSize.width / 2 + x * cGridSize * scaleRate
    local finalY = origin.y + visibleSize.height / 2 + y * cGridSize * scaleRate

    return finalX,finalY

end

-- require相應的類
-- local Body = require("app.Body")
local Snake = require("app.Snake")

local MainScene = class("MainScene", function()
    return display.newScene("MainScene")
end)

local cMoveSpeed = 0.3

function MainScene:onEnter() -- MainScene 載入執行
        self.snake = Snake.new(self) -- 建立一條蛇

        local tick = function()
            self.snake:Update() -- 更新蛇
        end -- end tick

        cc.Director:getInstance():getScheduler():scheduleScriptFunc(
             tick,cMoveSpeed,false)

end

return MainScene

定時器,就一句話
schedulerID = cc.Director:getInstance():getScheduler():scheduleScriptFunc(呼叫的function, 定時時間(秒), 是否暫停(true, false))

我們在更新函式中寫了self.snake:Update()

function Snake:Update()

    if #self.BodyArray == 0 then
        return
    end

    for i = #self.BodyArray , 1 , -1 do

        local body = self.BodyArray[i]

        if i == 1 then -- 蛇頭位置 與 方向,得到一個新的位置 存放蛇頭
            body.X, body.Y = OffsetGridByDir(body.X, body.Y, self.MoveDir)
        else
            local front = self.BodyArray[i-1]
            body.X, body.Y = front.X, front.Y
        end

        body:Update()

    end

end

邏輯: 根據一個移動方向,得到新的頭部位置,然後從尾部到頭部,每一個節點都更新成上一個節點,因為Snake中有個BodyArray ={} ,各個body都用這個table儲存著

顯示如下:

這裡寫圖片描述

控制小蛇

===

我們希望蛇能夠靈活點,我們用滑鼠,鍵盤能夠控制它(當然,智慧機上沒有按鍵的,我們在桌面開發),我們應該也知道各種事件,事件監聽等概念。

滑鼠點選控制

MainScene中新增成員方法

local function vector2Dir(x, y)

    if math.abs(x) > math.abs(y) then
        if x < 0 then
            return "left"
        else
            return "right"
     end

    else

        if y > 0 then
            return "up"
        else
            return "down"
      end

    end

end

-- 滑鼠點選事件處理
function MainScene:ProcessInput()

    local function onTouchBegan(touch, event)

        local location = touch:getLocation() -- 得到觸控點座標(cocos2d-x 座標)


-- 判斷移動的方向
        local snakex , snakey = self.snake:GetHeadGrid()
        local snake_fx,snake_fy = Grid2Pos(snakex,snakey)
        local finalX = location.x - snake_fx
        local finalY = location.y - snake_fy

        local dir = vector2Dir(finalX, finalY)
        print("now dir",dir)
        self.snake:setDir(dir) -- 設定蛇的移動方向

    end

    local listener = cc.EventListenerTouchOneByOne:create()
    listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN)
    local eventDispatcher = self:getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self)

end

定義一個事件監聽,並註冊,分發事件等
onTouchBegan
onTouchMoved
onTouchEnded;
這三個是要重寫的,跟cocos2d-x C++, Android中的事件處理都差不多的。

那麼我們重寫了onTouchBegan() ,裡面的邏輯就是 根據 滑鼠點選點蛇頭 相對位置,判斷蛇該往哪個方向,更新蛇的移動方向就行了

別忘了MainScene:onEnter() 呼叫此方法

function MainScene:onEnter() -- MainScene 載入執行
        self:ProcessInput() -- 滑鼠touch事件

        self.snake = Snake.new(self) -- 建立一條蛇

        local tick = function()
            self.snake:Update() -- 更新蛇
        end -- end tick

        cc.Director:getInstance():getScheduler():scheduleScriptFunc(
             tick,cMoveSpeed,false)

end

執行截圖
這裡寫圖片描述

鍵盤控制小蛇

有了滑鼠控制,自然鍵盤控制也不應該成為一個問題

同樣的MainScene中 新增一個事件處理 成員函式

-- 按鍵事件處理
function MainScene:ProcessKeyInput()

    local function keyboardPressed(keyCode,event)

        -- up
        if keyCode == 28 then
                print("up")
                self.snake:setDir("up") -- 設定蛇的移動方向
        -- down
        elseif keyCode == 29 then
                print("down")
                self.snake:setDir("down") -- 設定蛇的移動方向
        --left
        elseif keyCode == 26 then
                print("left")
                self.snake:setDir("left") -- 設定蛇的移動方向
        --right
        elseif keyCode == 27 then
                print("right")
                self.snake:setDir("right") -- 設定蛇的移動方向
        end

    end

    local listener = cc.EventListenerKeyboard:create()
    listener:registerScriptHandler(keyboardPressed, cc.Handler.EVENT_KEYBOARD_PRESSED)
    local eventDispatcher = self:getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener,self)

end

MainScene:onEnter() 呼叫此方法

function MainScene:onEnter() -- MainScene 載入執行
        self:ProcessInput() -- 滑鼠touch事件
        self:ProcessKeyInput() -- 鍵盤控制

        self.snake = Snake.new(self) -- 建立一條蛇

        local tick = function()
            self.snake:Update() -- 更新蛇
        end -- end tick

        cc.Director:getInstance():getScheduler():scheduleScriptFunc(
             tick,cMoveSpeed,false)

end

就這樣就行了

這裡寫圖片描述

按下方向鍵盤,試一下,可以多打打日誌,調一調,應該沒問題。

圍牆 和 死亡

===

上例中,我們看到蛇是可以跑出螢幕的,我們需要給蛇弄個圍牆,只能在圍牆內任意走動,撞到了牆 就死了

新增圍牆

編寫src/app/Fence.lua

  • 需要一個矩形圍牆

  • 能夠給出一個撞牆的判斷函式


local Snake = require("app.Snake")
local Fence = class("Fence")


local function fenceGenerator(node, bound, callback)

    for i = -bound, bound do
        local sp = cc.Sprite:create("fence.png")
        local posx,posy = callback(i)
        sp:setPosition(posx,posy)
        node:addChild(sp)
    end
end

function Fence:ctor(rowBound, colBound, node)

    self.rowBound = rowBound -- 螢幕中心往上或下 有 幾個格子
    self.colBound = colBound -- 螢幕中心往左或右 有 幾個格子

    -- up
    fenceGenerator(node, colBound,function(i)
        return Grid2Pos(i, rowBound)
    end)

        -- down
    fenceGenerator(node, colBound,function(i)
        return Grid2Pos(i, -rowBound)
    end)

        -- left
    fenceGenerator(node, rowBound,function(i)
        return Grid2Pos(-colBound, i)
    end)

        -- right
    fenceGenerator(node, rowBound,function(i)
        return Grid2Pos(colBound, i)
    end)

end

-- 判斷是否與圍牆相撞
function Fence:CheckCollide(x,y)
    return x == self.colBound or
                 x == -self.colBound or
                 y == self.rowBound or
                 y == -self.rowBound
end

return Fence

程式需要傳遞 行,列(其實只是最終圍牆的一半),父節點(MainScene控制的,就是MainScene類了)

接著 MainScene.lua 新增顯示
在原來的基礎上新增,部分程式碼如下

local Fence = require("app.Fence")

local MainScene = class("MainScene", function()
    return display.newScene("MainScene")
end)

local cMoveSpeed = 0.3
local rowBound = 5
local colBound = 8

function MainScene:onEnter() -- MainScene 載入執行
        self:ProcessInput() -- 滑鼠touch事件
        self:ProcessKeyInput() -- 鍵盤控制

        self.snake = Snake.new(self) -- 建立一條蛇
        self.fence = Fence.new(rowBound, colBound, self)  -- 建立圍牆

        local tick = function()
            self.snake:Update() -- 更新蛇
        end -- end tick

        cc.Director:getInstance():getScheduler():scheduleScriptFunc(
             tick,cMoveSpeed,false)

end

require, 所需變數的定義, onEnter()方法定義出fence, 這幾點注意就行了

執行圖如下
這裡寫圖片描述

蛇與圍牆相撞

MainScene.lua的onter方法中加幾句話就行了

local Snake = require("app.Snake")
local Fence = require("app.Fence")

local MainScene = class("MainScene", function()
    return display.newScene("MainScene")
end)

local cMoveSpeed = 0.3
local rowBound = 5
local colBound = 8

function MainScene:onEnter() -- MainScene 載入執行
        self:ProcessInput() -- 滑鼠touch事件
        self:ProcessKeyInput() -- 鍵盤控制

        self.snake = Snake.new(self) -- 建立一條蛇
        self.fence = Fence.new(rowBound, colBound, self)  -- 建立圍牆

        local tick = function()
            self.snake:Update() -- 更新蛇

            local headX , headY = self.snake:GetHeadGrid()
            if self.fence:CheckCollide(headX,headY) then -- 蛇與圍牆相撞
                print("collide fence")
            end

        end -- end tick

        cc.Director:getInstance():getScheduler():scheduleScriptFunc(
             tick,cMoveSpeed,false)

end

加了下面的幾句

local headX , headY = self.snake:GetHeadGrid()
            if self.fence:CheckCollide(headX,headY) then -- 蛇與圍牆相撞
                print("collide fence")
            end

因為原來我們都寫好了很多方法,比如我們是可以得到蛇的頭部座標的,有了座標我們當然是可以判斷是否撞牆的,這裡我加了日誌
執行如下:

這裡寫圖片描述

看到日誌了,表明成功了,不過蛇並沒有死亡,仍然跑出了邊界,因為我們什麼都沒有做。

死亡動畫

死亡的處理會比較複雜,我們要處理
* 死亡後,直接重新開始就行了,可以來個死亡動畫後再開始遊戲
* 死亡後,介面仍在重新整理,我們需要設定一個程式執行狀態
* 死亡後,我們希望,蛇能夠重新生成,開始(因為我們以後的蛇,如果邊長了,我們重來,蛇將依然是初始長度)

Fence.lua


local Fence = class("Fence")


function Fence:fenceGenerator(node, bound, callback)

    for i = -bound, bound do
        local sp = cc.Sprite:create("fence.png")
        local posx,posy = callback(i)
        sp:setPosition(posx,posy)
        node:addChild(sp)

        table.insert(self.fenceSpArray,sp)
    end
end

function Fence:ctor(rowBound, colBound, node)

    self.rowBound = rowBound -- 螢幕中心往上或下 有 幾個格子
    self.colBound = colBound -- 螢幕中心往左或右 有 幾個格子
    self.fenceSpArray = {}
    self.node = node

    -- up
    self:fenceGenerator(node, colBound,function(i)
        return Grid2Pos(i, rowBound)
    end)

    -- down
    self:fenceGenerator(node, colBound,function(i)
        return Grid2Pos(i, -rowBound)
    end)

    -- left
    self:fenceGenerator(node, rowBound,function(i)
        return Grid2Pos(-colBound, i)
    end)

    -- right
    self:fenceGenerator(node, rowBound,function(i)
        return Grid2Pos(colBound, i)
    end)

end

-- 判斷是否與圍牆相撞
function Fence:CheckCollide(x,y)
    return x == self.colBound or
                 x == -self.colBound or
                 y == self.rowBound or
                 y == -self.rowBound
end

function Fence:Reset()

    for _,sp in ipairs(self.fenceSpArray) do
        self.node:removeChild(sp)
    end

end

return Fence

改動:

  • 類似 Snake一樣 , 用了table 儲存了圍牆Sprite

  • 添加了一個Rest() 成員方法,用來銷燬Fence,注意要儲存父節點node

Snake.lua 新增兩個成員方法

-- 死亡之後的閃爍效果
function Snake:Blink(callback)

    for index,body in ipairs (self.BodyArray) do
        local blink = cc.Blink:create(3,5)

        if index == 1 then -- 蛇頭
            local a = cc.Sequence:create(blink, cc.CallFunc:create(callback))
            body.sp:runAction(a)
        else
            body.sp:runAction(blink) -- 蛇身
        end

    end -- for

end

-- 死亡銷燬
function Snake:Kill()
    for _,body in ipairs(self.BodyArray) do
        self.node:removeChild(body.sp)
    end
end

其中 Blink 函式中用到了cc.Blink 動畫,讓蛇閃爍

MainScene.lua

直接貼上到目前為止MainScene修改後的整個程式碼


local cGridSize = 33
local scaleRate = 1 / display.contentScaleFactor

-- 根據自定義的座標得到實際應該顯示的cocos2d-x座標位置
function Grid2Pos(x,y)

    local visibleSize = cc.Director:getInstance():getVisibleSize() -- 獲取整個手機可視螢幕尺寸

    local origin = cc.Director:getInstance():getVisibleOrigin() -- 獲取手機可視屏原點的座標,螢幕的左上角

    local finalX = origin.x + visibleSize.width / 2 + x * cGridSize * scaleRate
    local finalY = origin.y + visibleSize.height / 2 + y * cGridSize * scaleRate

    return finalX,finalY

end

-- require相應的類
-- local Body = require("app.Body")
local Snake = require("app.Snake")
local Fence = require("app.Fence")

local MainScene = class("MainScene", function()
    return display.newScene("MainScene")
end)

local cMoveSpeed = 0.3
local rowBound = 5
local colBound = 8

function MainScene:onEnter() -- MainScene 載入執行
        self:ProcessInput() -- 滑鼠touch事件
        self:ProcessKeyInput() -- 鍵盤控制

        self:Reset()

        --self.snake = Snake.new(self) -- 建立一條蛇
        --self.fence = Fence.new(rowBound, colBound, self)  -- 建立圍牆

        local tick = function()
            if self.stage == "running" then

                self.snake:Update() -- 更新蛇

                local headX , headY = self.snake:GetHeadGrid()
                if self.fence:CheckCollide(headX,headY) then -- 蛇與圍牆相撞
                    self.stage = "dead"
                    self.snake:Blink(function()

                                self:Reset()


                                end)
                end
            end

        end -- end tick

        cc.Director:getInstance():getScheduler():scheduleScriptFunc(
             tick,cMoveSpeed,false)

end



local function vector2Dir(x, y)

    if math.abs(x) > math.abs(y) then
        if x < 0 then
            return "left"
        else
            return "right"
     end

    else

        if y > 0 then
            return "up"
        else
            return "down"
      end

    end

end

-- 滑鼠點選事件處理
function MainScene:ProcessInput()

    local function onTouchBegan(touch, event)

        local location = touch:getLocation() -- 得到觸控點座標(cocos2d-x 座標)


-- 判斷移動的方向
        local snakex , snakey = self.snake:GetHeadGrid()
        local snake_fx,snake_fy = Grid2Pos(snakex,snakey)
        local finalX = location.x - snake_fx
        local finalY = location.y - snake_fy

        local dir = vector2Dir(finalX, finalY)
        print("now dir",dir)
        self.snake:setDir(dir) -- 設定蛇的移動方向

    end

    local listener = cc.EventListenerTouchOneByOne:create()
    listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN)
    local eventDispatcher = self:getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self)

end


-- 按鍵事件處理
function MainScene:ProcessKeyInput()

    local function keyboardPressed(keyCode,event)

        -- up
        if keyCode == 28 then
                print("up")
                self.snake:setDir("up") -- 設定蛇的移動方向
        -- down
        elseif keyCode == 29 then
                print("down")
                self.snake:setDir("down") -- 設定蛇的移動方向
        --left
        elseif keyCode == 26 then
                print("left")
                self.snake:setDir("left") -- 設定蛇的移動方向
        --right
        elseif keyCode == 27 then
                print("right")
                self.snake:setDir("right") -- 設定蛇的移動方向
        end

    end

    local listener = cc.EventListenerKeyboard:create()
    listener:registerScriptHandler(keyboardPressed, cc.Handler.EVENT_KEYBOARD_PRESSED)
    local eventDispatcher = self:getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener,self)

end


-- 遊戲結束操作
function MainScene:Reset()
    if self.snake ~= nil then
        self.snake:Kill()
    end

    if self.fence ~= nil then
        self.fence:Reset()
    end

    self.snake = Snake.new(self) -- 建立一條蛇
    self.fence = Fence.new(rowBound, colBound, self)  -- 建立圍牆
    self.stage = "running"

end

return MainScene

改動,

我們定義了Reset()成員方法, 並且給程式執行時加了state狀態

在onEnter()中, 直接呼叫Reset()方法,就可以重新建立 蛇和圍牆了

tick() 函式中呼叫了 snake的死亡閃爍動畫,並且設定了state = “dead”

MainScene始終控制著整個程式的邏輯

看下執行截圖,小蛇會死,然後重新開始
這裡寫圖片描述

圍牆內隨機產生蘋果

===

跟Fence, Snake差不多,編寫AppleFactory.lua

local AppleFactory = class("AppleFactory")

function AppleFactory:ctor(rowBound, colBound, node)

    self.rowBound = rowBound
    self.colBound = colBound
    self.node = node

    math.randomseed(os.time())

    self:Generate()

end


local function getRandomPos