日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Love2D游戏引擎制作贪吃蛇游戏

發布時間:2024/8/26 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Love2D游戏引擎制作贪吃蛇游戏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

預覽游戲

love2d游戲引擎重要函數

詳情:

  • love.load:當游戲開始時被調用且僅調用一次

  • love.draw:回調函數,每幀更新一次游戲畫面

  • love.update:回調函數,每幀更新一次游戲狀態

  • love.keypressed:回調函數,當有按鍵被按下時觸發

  • love.filesystem.load:加載一個lua腳本文件但不執行

!其他的函數在用到時再做解釋

版本區別以及初始化資源

!首先要注意的是,本次使用的游戲引擎時love 0.9版本,與最新的love 11.x版本稍有區別。在0.9版本中顏色使用0~255來表示,而在11.x版本中是0~1來表示。

因為需要制作的游戲非常小,所以我們將所用到的資源在第一時間將其初始化并加載到內存中,以便使用。使用到的資源主要有:

  • 字體

  • 顏色

  • 聲音

  • 窗口大小與塊大小

  • 標題

  • 邊框

所用到的函數:

  • love.window.setMode:設置窗口大小,以及樣式

  • love.window.setTitle:設置標題

  • love.graphics.newFont:加載字體文件,大小自定義,返回Font類型

  • love.audio.newSource:加載音效文件

代碼如下:

function love.load ()-- 塊大小,窗口寬高,標題cellSize = 20width = 20 * 40height = 20 * 25title = 'SNAKE !'-- 設置窗口大小和標題love.window.setMode (width, height)love.window.setTitle (title)-- 加載不同大小字體fonts = {pixies100 = love.graphics.newFont ('Fonts/Pixies.TTF', 100),pixies30 = love.graphics.newFont ('Fonts/Pixies.TTF', 30),pixies10 = love.graphics.newFont ('Fonts/Pixies.TTF', 10)}-- 加載音效資源sounds = {showMenu = love.audio.newSource ('Sounds/showMenu.wav', 'stream'),switchOption = love.audio.newSource ('Sounds/switchOption.wav', 'stream'),eatFood = love.audio.newSource ('Sounds/eatFood.wav', 'stream'),collided = love.audio.newSource ('Sounds/collided.wav', 'stream'),gameOver = love.audio.newSource ('Sounds/gameOver.wav', 'stream')}-- 邊框數據border = {1, 1,width-1, 1,width-1, height-1,1, height-1,1, 1}-- 顏色數據colors = {darkGray = { 0.3, 0.3, 0.3, 1 },beiga = { 0.98, 0.91, 0.76, 1 },white = { 1, 1, 1, 1 },paleTurquoise = { 0.7, 1, 1, 1 },}SwitchScence ('Menu') end

場景與其切換

!首先我們需要實現一個簡單的場景切換函數,因為一個游戲總是有多個場景

  • 先將love2d引擎的主要回調函數賦值nil以免之后出現錯誤
  • 加載新場景的lua腳本
  • 執行新場景的lua腳本
  • 代碼如下:

    function SwitchScence (scence)-- 將重要的函數賦予空值,以免沖突love.update = nillove.draw = nillove.keypressed = nil-- 將需要的場景加載進來,并執行load函數love.filesystem.load ('Scences/'..scence..'.lua') ()love.load () end-- 切換到初始化場景 SwitchScence ('Init')

    繪制開始界面

    在這里我們需要認識一些游戲買賣函數:

    • love.graphics.setFont:設置當期字體

    • love.graphics.setColor:設置當前顏色

    • love.graphics.rectangle:繪制矩形

    • love.graphics.line:繪制直線

    • love.graphics.print:在窗口上輸出

    !繪制比較簡單,其他詳情都在代碼里有詳細注釋,要注意的是我繪制選項的方法。options的有效長度并不是#options,而是options.count記錄的選項數量

    代碼如下:

    -- 游戲標題,以及繪制位置 local gameName = {text = title,textX = cellSize * 12,textY = cellSize * 6 }-- 選項:開始和退出 local options = {{text = "START",textX = cellSize * 18,textY = cellSize * 15 - 5,border = {cellSize*16, cellSize*14,cellSize*24, cellSize*14,cellSize*24, cellSize*17,cellSize*16, cellSize*17,cellSize*16, cellSize*14}},{text = "QUIT",textX = cellSize * 19 - 10,textY = cellSize * 19 - 5,border = {cellSize*16, cellSize*18,cellSize*24, cellSize*18,cellSize*24, cellSize*21,cellSize*16, cellSize*21,cellSize*16, cellSize*18}},-- 一些其他屬性count = 2,selected = 1 }function love.load ()-- 加載并播放背景音樂sounds.showMenu:play ()-- 設置米色和藍色的透明程度為0,為了之后的動畫效果colors.beiga[4] = 0colors.paleTurquoise[4] = 0 endfunction love.draw ()-- 灰色背景love.graphics.setColor (colors.darkGray)love.graphics.rectangle ('fill',0,0,width,height)-- 白色邊框love.graphics.setColor (colors.white)love.graphics.line (border)-- 漸顯效果if colors.beiga[4] < 1 thencolors.beiga[4] = colors.beiga[4] + 0.01colors.paleTurquoise[4] = colors.paleTurquoise[4] + 0.01end-- 設置字體,在指定位置畫出米色標題love.graphics.setFont (fonts.pixies100)love.graphics.setColor (colors.beiga)love.graphics.print (gameName.text, gameName.textX, gameName.textY)-- 設置字體love.graphics.setFont (fonts.pixies30)-- 繪制所有選項for i = 1, options.count doif i == options.selected thenlove.graphics.setColor (colors.paleTurquoise)elselove.graphics.setColor (colors.beiga)end-- 繪制選項邊框和字體love.graphics.line (options[i].border)love.graphics.print (options[i].text, options[i].textX, options[i].textY)end endfunction love.keypressed (key)-- 上下箭頭選擇選項,回車按鍵確認選項if key == 'up' then-- 關閉切換選項的聲音并重新播放if sounds.switchOption.isPlaying thensounds.switchOption:stop ()endsounds.switchOption:play ()-- 切換當前選項索引options.selected = options.selected - 1if options.selected <= 0 thenoptions.selected = options.countendelseif key == 'down' then-- 同上if sounds.switchOption.isPlaying thensounds.switchOption:stop ()endsounds.switchOption:play ()options.selected = options.selected + 1if options.selected > options.count thenoptions.selected = 1endelseif key == 'return' then-- 關閉顯示界面聲音if sounds.showMenu.isPlaying thensounds.showMenu:stop ()end-- 對應不同選項作出不同回應if options.selected == 1 thenSwitchScence ('GameStart')elseif options.selected == 2 thenlove.event.quit ()endend end

    實現游戲主體

    游戲的實現方法,主要知道兩個方面:

    • 蛇的移動方式:根據方向獲取下一個頭的位置,若沒有吃到食物就將蛇尾刪除,達到移動效果
    -- 下一個蛇頭位置 local nextX = snake.body[1].x local nextY = snake.body[1].y-- 當方向隊列中的方向大于1時除去第一個方向(當前方向) if #directionQueue > 1 thentable.remove (directionQueue, 1) end-- 根據方向作出改動 if directionQueue[1] == 'right' thennextX = nextX + 1if nextX > limit.x thennextX = 0endelseif directionQueue[1] == 'left' thennextX = nextX - 1if nextX < 0 thennextX = limit.xendelseif directionQueue[1] == 'down' thennextY = nextY + 1if nextY > limit.y thennextY = 0endelseif directionQueue[1] == 'up' thennextY = nextY - 1if nextY < 0 thennextY = limit.yendend-- 蛇是否可以移動(沒有與自身相撞)local canMove = truefor index, pair in ipairs (snake.body) doif index ~= #snake.bodyand nextX == pair.xand nextY == pair.y thencanMove = falseendend-- 當蛇可以移動時if canMove then-- 將新位置加在蛇身的頭,并檢測是否吃到了食物table.insert (snake.body, 1, { x = nextX, y = nextY })if nextX == food.x and nextY == food.y then-- 播放吃到食物的音效(關閉之前的音效)if sounds.eatFood.isPlaying thensounds.eatFood:stop ()endsounds.eatFood:play ()-- 分數加一,并生成新的食物位置currentScore.score = currentScore.score + 1CreateFood ()else-- 沒有吃到食物則刪去蛇身的尾部,達到移動的目的table.remove (snake.body)endelse-- 蛇死亡,并播放相撞的音效snake.alive = falsesounds.collided:play ()end end
    • 方向隊列的引入:主要是解決鍵位沖突的問題
    function love.keypressed (key)-- 空格鍵暫停游戲if key == 'space' thenpaused = not pausedend-- 沒有暫停時if not paused then-- 記錄方向鍵的按下順序,同方向或相反方向的不記錄if key == 'right'and directionQueue[#directionQueue] ~= 'right'and directionQueue[#directionQueue] ~= 'left' thentable.insert (directionQueue, 'right')elseif key == 'left'and directionQueue[#directionQueue] ~= 'left'and directionQueue[#directionQueue] ~= 'right' thentable.insert (directionQueue, 'left')elseif key == 'down'and directionQueue[#directionQueue] ~= 'down'and directionQueue[#directionQueue] ~= 'up' thentable.insert (directionQueue, 'down')elseif key == 'up'and directionQueue[#directionQueue] ~= 'up'and directionQueue[#directionQueue] ~= 'down' thentable.insert (directionQueue, 'up')endend end

    代碼如下:

    -- 游戲窗口與記分窗口的分界線 local boundary = {cellSize*30, 0,cellSize*30, height }-- 當前分數的信息 local currentScore = {text = 'SCORE',score = 0,-- 文字的繪圖位置textX = cellSize * 33,textY = cellSize * 2,-- 分數的繪圖位置scoreX = cellSize * 34,scoreY = cellSize * 5 }-- 最高分的信息 local highScore = {text = 'HIGH SCORE',score = 0,-- 同上textX = cellSize * 31,textY = cellSize * 12,scoreX = cellSize * 34,scoreY = cellSize * 15 }-- 提示信息 local notes = {{text = 'ARROW KEY TO MOVE',textX = cellSize * 34,textY = cellSize * 22},{text = 'ENTER KEY TO PAUSE',textX = cellSize * 34,textY = cellSize * 23} }-- 游戲窗口的限制 local limit = { x = 29, y = 24 }-- 蛇的初始化信息 local snake = {-- 蛇身body = {{ x = 2, y = 0 },{ x = 1, y = 0 },{ x = 0, y = 0 }},-- 速度與狀態speed = 0.1,alive = true, }-- 食物的位置 local food = { x = nil, y = nil }-- 方向隊列,用于記錄鍵盤按下的順序以免產生沖突 local directionQueue = { 'right' }-- 計時器,暫停狀態以及最高分文件 local timer = 0 local paused = false local file = nil-- 用于生成食物的可存在位置 local function CreateFood ()local foodPosition = {}-- 遍歷整個窗口,將可生成食物的位置記錄在foodPosition表里for i = 0, limit.x dofor j = 0, limit.y dolocal possible = true-- 是否與蛇身沖突for index, pair in ipairs (snake.body) doif i == pair.x and j == pair.y thenpossible = falseendendif possible thentable.insert (foodPosition, { x = i, y = j })endendend-- 生成隨機食物位置local index = love.math.random (#foodPosition)food.x, food.y = foodPosition[index].x, foodPosition[index].y endfunction love.load ()file = love.filesystem.newFile ('HighScore.txt')file:open ('r')highScore.score = file:read ()file:close ()-- 沒有透明度colors.beiga[4] = 1colors.paleTurquoise[4] = 1CreateFood () endfunction love.draw ()-- 繪制背景love.graphics.setColor (colors.darkGray)love.graphics.rectangle ('fill',0,0,width,height)-- 繪制白色邊框和邊界線love.graphics.setColor (colors.white)love.graphics.line (border)love.graphics.line (boundary)-- 設置字體和顏色,并在指定位置繪制當前分數信息和最高分信息love.graphics.setFont (fonts.pixies30)love.graphics.setColor (colors.beiga)love.graphics.print (currentScore.text, currentScore.textX, currentScore.textY)love.graphics.print (currentScore.score, currentScore.scoreX, currentScore.scoreY)love.graphics.setColor (colors.paleTurquoise)love.graphics.print (highScore.text, highScore.textX, highScore.textY)love.graphics.print (highScore.score, highScore.scoreX, highScore.scoreY)-- 蛇生存和死亡時使用不同的顏色繪制if snake.alive thenlove.graphics.setColor (colors.paleTurquoise)elselove.graphics.setColor (colors.beiga)end-- 繪制蛇身,蛇頭另繪for index, pair in ipairs (snake.body) doif index == 1 thenlove.graphics.rectangle ('fill',cellSize*pair.x,cellSize*pair.y,cellSize,cellSize)endlove.graphics.rectangle ('fill',cellSize*pair.x+1,cellSize*pair.y+1,cellSize-1*2,cellSize-1*2)end-- 繪制食物love.graphics.setColor (colors.beiga)love.graphics.rectangle ('fill',cellSize*food.x+1,cellSize*food.y+1,cellSize-1*2,cellSize-1*2)-- 如果是暫停狀態,則繪制暫停字樣if paused thenlove.graphics.print ('PAUSED !', cellSize*12, cellSize*11)end-- 設置字體和顏色并繪制提示信息love.graphics.setFont (fonts.pixies10)love.graphics.setColor (colors.beiga)for i = 1, #notes dolove.graphics.print (notes[i].text, notes[i].textX, notes[i].textY)end endfunction love.update (dt)-- 使用計時器timer = timer + dt-- 當蛇生存時if snake.alive then-- 根據蛇的速度更新游戲if timer > snake.speed thentimer = timer - snake.speed-- 沒有暫停時if not paused then-- 下一個蛇頭位置local nextX = snake.body[1].xlocal nextY = snake.body[1].y-- 當方向隊列中的方向大于1時除去第一個方向(當前方向)if #directionQueue > 1 thentable.remove (directionQueue, 1)end-- 根據方向作出改動if directionQueue[1] == 'right' thennextX = nextX + 1if nextX > limit.x thennextX = 0endelseif directionQueue[1] == 'left' thennextX = nextX - 1if nextX < 0 thennextX = limit.xendelseif directionQueue[1] == 'down' thennextY = nextY + 1if nextY > limit.y thennextY = 0endelseif directionQueue[1] == 'up' thennextY = nextY - 1if nextY < 0 thennextY = limit.yendend-- 蛇是否可以移動(沒有與自身相撞)local canMove = truefor index, pair in ipairs (snake.body) doif index ~= #snake.bodyand nextX == pair.xand nextY == pair.y thencanMove = falseendend-- 當蛇可以移動時if canMove then-- 將新位置加在蛇身的頭,并檢測是否吃到了食物table.insert (snake.body, 1, { x = nextX, y = nextY })if nextX == food.x and nextY == food.y then-- 播放吃到食物的音效(關閉之前的音效)if sounds.eatFood.isPlaying thensounds.eatFood:stop ()endsounds.eatFood:play ()-- 分數加一,并生成新的食物位置currentScore.score = currentScore.score + 1CreateFood ()else-- 沒有吃到食物則刪去蛇身的尾部,達到移動的目的table.remove (snake.body)endelse-- 蛇死亡,并播放相撞的音效snake.alive = falsesounds.collided:play ()endendend-- 等待一秒elseif timer >= 1 then-- 存儲最高分if currentScore.score > tonumber (highScore.score) thenfile:open ('w')file:write (tostring (currentScore.score))file:close ()end-- 切換到游戲結束場景SwitchScence ('GameOver')end endfunction love.keypressed (key)-- 回車鍵暫停游戲if key == 'return' thenpaused = not pausedend-- 沒有暫停時if not paused then-- 記錄方向鍵的按下順序,同方向或相反方向的不記錄if key == 'right'and directionQueue[#directionQueue] ~= 'right'and directionQueue[#directionQueue] ~= 'left' thentable.insert (directionQueue, 'right')elseif key == 'left'and directionQueue[#directionQueue] ~= 'left'and directionQueue[#directionQueue] ~= 'right' thentable.insert (directionQueue, 'left')elseif key == 'down'and directionQueue[#directionQueue] ~= 'down'and directionQueue[#directionQueue] ~= 'up' thentable.insert (directionQueue, 'down')elseif key == 'up'and directionQueue[#directionQueue] ~= 'up'and directionQueue[#directionQueue] ~= 'down' thentable.insert (directionQueue, 'up')endend end

    實現最高分的保存與讀取

    游戲存檔目錄:

    • Windows XP: C:\Documents and Settings\user\Application Data\LOVE\ or %appdata%\LOVE\

    • Windows Vista and 7,8: C:\Users\user\AppData\Roaming\LOVE or %appdata%\LOVE\

    • Linux:?$XDG_DATA_HOME/love/ or ~/.local/share/love/

    • Mac: /Users/user/Library/Application Support/LOVE/

    !寫文件只能在存檔目錄

    最高分讀取:

    file = love.filesystem.newFile ('HighScore.txt') file:open ('r') highScore.score = file:read () file:close ()

    最高分保存:

    file:open ('w') file:write (tostring (currentScore.score)) file:close ()

    繪制游戲結束界面

    游戲結束界面的繪制與開始界面大致相同,這里不再贅述

    代碼如下:

    local gameOver = {text = 'GAME OVER !',textX = cellSize * 6,textY = cellSize * 6 }-- 選項:開始和退出 local options = {{text = "BACK",textX = cellSize * 13 - 15,textY = cellSize * 17 - 5,border = {cellSize*10, cellSize*16,cellSize*18, cellSize*16,cellSize*18, cellSize*19,cellSize*10, cellSize*19,cellSize*10, cellSize*16}},{text = "RETRY",textX = cellSize * 24,textY = cellSize * 17 - 5,border = {cellSize*22, cellSize*16,cellSize*30, cellSize*16,cellSize*30, cellSize*19,cellSize*22, cellSize*19,cellSize*22, cellSize*16}},-- 一些其他屬性count = 2,selected = 1 }function love.load ()sounds.gameOver:play ()-- 設置米色和藍色的透明程度為0,為了之后的動畫效果colors.beiga[4] = 0colors.paleTurquoise[4] = 0 endfunction love.draw ()-- 灰色背景love.graphics.setColor (colors.darkGray)love.graphics.rectangle ('fill',0,0,width,height)-- 白色邊框love.graphics.setColor (colors.white)love.graphics.line (border)-- 漸顯效果if colors.beiga[4] < 1 thencolors.beiga[4] = colors.beiga[4] + 0.01colors.paleTurquoise[4] = colors.paleTurquoise[4] + 0.01end-- 設置字體,在指定位置畫出米色標題love.graphics.setFont (fonts.pixies100)love.graphics.setColor (colors.beiga)love.graphics.print (gameOver.text, gameOver.textX, gameOver.textY)-- 設置字體love.graphics.setFont (fonts.pixies30)for i = 1, options.count doif i == options.selected thenlove.graphics.setColor (colors.paleTurquoise)elselove.graphics.setColor (colors.beiga)endlove.graphics.line (options[i].border)love.graphics.print (options[i].text, options[i].textX, options[i].textY)end endfunction love.keypressed (key)-- 上下箭頭選擇選項,回車按鍵確認選項if key == 'left' thenif sounds.gameOver.isPlaying thensounds.gameOver:stop ()endif sounds.switchOption.isPlaying thensounds.switchOption:stop ()endsounds.switchOption:play ()options.selected = options.selected - 1if options.selected <= 0 thenoptions.selected = options.countendelseif key == 'right' thenif sounds.gameOver.isPlaying thensounds.gameOver:stop ()endif sounds.switchOption.isPlaying thensounds.switchOption:stop ()endsounds.switchOption:play ()options.selected = options.selected + 1if options.selected > options.count thenoptions.selected = 1endelseif key == 'return' thenif sounds.gameOver.isPlaying thensounds.gameOver:stop ()endif options.selected == 1 thenSwitchScence ('Menu')elseif options.selected == 2 thenSwitchScence ('GameStart')endend end

    項目結構

    項目結構圖如下

    Love2D游戲引擎制作貪吃蛇游戲

    總結

    以上是生活随笔為你收集整理的Love2D游戏引擎制作贪吃蛇游戏的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。