效果如下
代码简介
一个简简单单的贪吃蛇框架
代码思路
整个场景基于10*10的二维数组生成,value=1表示蛇的身体,value=2表示果实。蛇的身体由n个白色方块组成,初始蛇的长度为1,每吃掉一个果实长度+1。
1.场景生成
2.功能实现
1.画蛇
把蛇抽象为一个表table,表长即蛇长。表里的元素是白色方块的坐标,通过遍历table来绘制方块,连在一起的方块就变成了蛇。
2.如何让蛇的身体变长
根据按键来预测蛇头的位置,如果预测到蛇头要到达的地方是果实,则把果实的坐标插入表头。
3.如何实现蛇的身体移动
根据按键来预测蛇头的位置,如果预测到蛇头要到达的地方为空,则把把该坐标传给表头元素,表头的坐标传给表的第二个元素,依次内推。
想到过使用递归的方法,但是本身表的递归就用for循环就最为方便。
遇到的问题
1️⃣按下右键,蛇长从3变成2,如图
我们要知道贪吃蛇不能通过左右方向键来立即掉头,所以我们必须设置当按下某个方向键的时候,此时按下与其方向相反的键的时候就没反应。
我这里设置状态量
stateList={
rightMove = true,
leftMove = false,
upMove = true,
downMove = true,
}
-- 然后按下一个方向键就让反方向键的状态为false,其他键状态为true
--为了方便我写了一个间接函数
function state(a,b,c,d)
if a == 1 then
stateList.rightMove=false
stateList.leftMove =true
stateList.downMove = true
stateList.upMove = true
end
if b == 1 then
stateList.rightMove = true
stateList.leftMove = false
stateList.downMove = true
stateList.upMove = true
end
if c == 1 then
stateList.rightMove = true
stateList.leftMove = true
stateList.downMove = false
stateList.upMove = true
end
if d == 1 then
stateList.rightMove = true
stateList.leftMove = true
stateList.downMove = true
stateList.upMove = false
end
end
-- 此函数为监听键盘函数,通过状态量也限制了某些按键
function love.keypressed(key)
local x = snake[1].x
local y = snake[1].y
if key == "right" and stateList.rightMove then
x = x + 1
-- 调用state函数,限制左键的输入,以下同理
state(0,1,0,0)
elseif key == "left" and stateList.leftMove then
x = x - 1
state(1, 0, 0, 0)
elseif key == "up" and stateList.upMove then
y = y - 1
state(0, 0, 1, 0)
elseif key == "down" and stateList.downMove then
y = y + 1
state(0, 0, 0, 1)
end
-- 为了把x,y限制在10*10的范围内
if y<1 then
y=1
elseif y >10 then
y=10
end
if x < 1 then
x = 1
elseif x > 10 then
x = 10
end
-- 调用移动函数
if blockList[y][x] == 0 then
snake_move(x, y)
else
end
end
效果如下:
2️⃣果实出现在蛇身上
分析:果实的生成代码我是随机生成1-10内的x与y作为果实的坐标,这中随机性就会可能让果实出现在蛇体内只要做一个do-while函数即可实现
function Block:new()
local block = {}
repeat
block.x = math.random(10)
block.y = math.random(10)
\\ 如果产生的果实在蛇的身体里则一直生成随机坐标,只到果实在蛇的身体外面
until blockList[block.y][block.x] ~= 1
blockList[block.y][block.x] = 2
return true
end
项目代码
<main.lua>
if os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") == "1" then
require("lldebugger").start()
end
function love.load()
blockList={
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 2, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
}
Object=require "Classic"
require "block"
snake={
{x=4,y=2},{x=3,y=2},{x=2,y=2}
}
stateList={
rightMove = true,
leftMove = false,
upMove = true,
downMove = true,
}
fruit = true
end
function love.keypressed(key)
local x = snake[1].x
local y = snake[1].y
if key == "right" and stateList.rightMove then
x = x + 1
state(0,1,0,0)
elseif key == "left" and stateList.leftMove then
x = x - 1
state(1, 0, 0, 0)
elseif key == "up" and stateList.upMove then
y = y - 1
state(0, 0, 1, 0)
elseif key == "down" and stateList.downMove then
y = y + 1
state(0, 0, 0, 1)
end
if y<1 then
y=1
elseif y >10 then
y=10
end
if x < 1 then
x = 1
elseif x > 10 then
x = 10
end
if blockList[y][x] == 0 then
snake_move(x, y)
elseif blockList[y][x] == 2 then
local block1={}
block1.x = x
block1.y = y
table.insert(snake,1,block1)
blockList[y][x] = 1
fruit = false
end
end
function love.update(dt)
if not fruit then
if Block:new() then
fruit = true
end
end
end
function love.draw()
Block:draw()
end
<block.lua>
Block = Object:extend()
function Block:new()
local block = {}
repeat
block.x = math.random(10)
block.y = math.random(10)
until blockList[block.y][block.x] ~= 1
blockList[block.y][block.x] = 2
return true
end
function snake_move(pre_x, pre_y)
for i, v in ipairs(snake) do
if v then
local x = v.x
local y = v.y
v.x = pre_x
v.y = pre_y
blockList[pre_y][pre_x] = 1
pre_x = x
pre_y = y
blockList[y][x] = 0
end
end
end
function Block:update(dt)
end
function Block:draw()
local x =0
for i =1,10,1 do
local y =0
for j =1,10,1 do
if blockList[j][i]==1 then
love.graphics.rectangle("fill",(i-1)*31,(j-1)*31,30,30)
elseif blockList[j][i]==0 then
love.graphics.setColor(0,0,0)
love.graphics.rectangle("fill", (i - 1) * 31, (j - 1) * 31, 30, 30)
love.graphics.setColor(255,255,255)
elseif blockList[j][i] == 2 then
love.graphics.setColor(255, 0, 0)
love.graphics.rectangle("fill", (i - 1) * 31, (j - 1) * 31, 30, 30)
love.graphics.setColor(255, 255, 255)
end
y = y +31
end
x= x+31
end
end
function state(a,b,c,d)
if a == 1 then
stateList.rightMove=false
stateList.leftMove =true
stateList.downMove = true
stateList.upMove = true
end
if b == 1 then
stateList.rightMove = true
stateList.leftMove = false
stateList.downMove = true
stateList.upMove = true
end
if c == 1 then
stateList.rightMove = true
stateList.leftMove = true
stateList.downMove = false
stateList.upMove = true
end
if d == 1 then
stateList.rightMove = true
stateList.leftMove = true
stateList.downMove = true
stateList.upMove = false
end
end
<Classic.lua>该文件代码我就不放了,在我的任意的代码库文章中都有,自行复制。