源码已经更新在CSDN的码库里:
git clone https://gitcode.com/funsion/love2d-game.git
一直在找Lua 能快速便捷实现图形界面的软件,找了一堆,终于发现love2d是小而美的原生lua图形界面实现的方式。
并参考相关教程做了一个更详细的,以便入门。
功能如上图,
开发过程用了love2d, 不大哦,直接Win下解压可以用的。这是跑程序用的。需要改一下Win的环境变量。
另外用了一个Love2D Editor,写代码用的,也很小,直接Win下解压可以用的。自己发个快捷方式到桌面即可。
已更新安装教程。请关注,love 2d win 下超简单安装方式,学习Lua 中文编程 刚需!!
再结合我们之前的Lua 中文入门教程,我相信,写起来,用起来。真的其实代码就像注释一样明了。
七个方块集合
-- 定义一个块的集合,每个块由多个二维数组表示
方块组={{{0,1,1},{1,1,0}},{{1,1,0},{0,1,1}},{{1,1,1},{0,0,1}},{{1,1,1},{1,0,0}},{{1,1,1},{0,1,0}},{{1,1},{1,1}},{{1,1,1,1}}}
{{0,1,1},{1,1,0}} | {{1,1,0},{0,1,1}} | {{1,1,1},{0,0,1}} |
{{1,1,1},{1,0,0}} | {{1,1,1},{0,1,0} | {{1,1},{1,1}} |
{{1,1,1,1}} | ||
10列22行的游戏地图
初始化一个空的字段数组,用于游戏地图。
像一个10列(10个格子),22行(22个格子)的空格子。如左下图。
主体格子={}
主体格子={}
for i=1,22 do
主体格子[i]={0,0,0,0,0,0,0,0,0,0}
end
初始化当前方块
随机选择一个块,初始化块的位置,坐标系在左下角,4,19,分别为第4列,第19行。
math.random()是随机数,取值范围1到7。即对应上方介绍过的7种方块组的图案。为什么是19行,如右上图中所示。刚好是4个竖向方格出现时能全显。
同样的4列也是这个原因,并且显示居中。
当前方块,方块X坐标,方块Y坐标 = 方块组[math.random(7)],4,19
检测方块是否与现有的游戏地图重叠
先检查是否超边界
@当前方块: 要检测的块,
@方块x坐标: 方块的起始x坐标,
@方块y坐标: 方块的起始y坐标
返回值: 如果有重叠返回true(真),否则返回false(假)。
如下图,我们用一个田字方块做检查,红色空框代表当前位置,黄色实心框代表返回的位置。
左边红色空框位置如果超界,就会横坐标+1格变成黄色实心框,如箭头方向回到游戏地图内。
右边红色空框位置如果超界,就会横坐标-1格变成黄色实心框,如箭头方向回到游戏地图内。
下边红色空框位置如果超界,就会纵坐标+1格变成黄色实心框,如箭头方向回到游戏地图内。
检查块是否放置在边界之外
“当前方块[1]” 是方块的宽度
如果 “方块x坐标” 超出边界(横向小于1个格或者大于11格),
或者 “方块y坐标” 超出边界,
则 返回 “true”(真)
下面是检查的代码:
if 方块x坐标 < 1 or 方块x坐标+#当前方块[1] > 11 or 方块y坐标 < 1 then --当前方块[1]是方块的宽度
return true
return true
end
检查是否与游戏地图 “主体格子” 现存的方块重叠。
假如你的游戏地图如左下图,蓝色的是 “主体格子” 现存的方块。
遍历 “当前方块” 的每个元素,检查是否与 “主体格子” 现存的方块重叠
主体格子[方块y坐标+i-1] 即在游戏地图上 “主体格子”与对应“当前方块”y坐标的位置,是否现存的方块格子。
当前方块[i][j]即 “当前方块” 的二唯表格位置里的数据,
如果大于0,则表示是“主体格子”在当前位置不是空位,即现存的方块与 “当前方块” 相交。
如右下图红框与蓝色的 “主体格子” 相交,“当前方块”就会按箭头位置复位成黄色块相应的位置。
代码如下:
for i=1,#当前方块 do -- 遍历块的每一行,即高度
for j=1,#当前方块[1] do -- 遍历块的每一列,即宽度
if 主体格子[方块y坐标+i-1] and 当前方块[i][j] > 0 and 主体格子[方块y坐标+i-1][方块x坐标+j-1] > 0 then
return true
end
end
end
下落过程函数
此函数用于处理方块的下落过程,包括方块位置的更新、方块与底部或其它方块的碰撞检测、以及消除满行等逻辑。
1、尝试将当前方块下落一行
2、检测当前方块是否与底部或其它方块发生重叠
2.1 如果发生重叠,则将 “当前方块” 位置回退到重叠之前
2.2 如果没有重叠,将 “当前方块” 的形状数据复制到游戏场地即“主体格子”内
2.2.1 遍历“当前方块”的每一行
2.2.2 遍历“当前方块”的每一列
2.2.3 如果“当前方块”的形状数据在这个位置不为空,则将其复制到游戏场地即“主体格子”内
3、检查并消除满行
4、生成新的随机方块,设置其初始位置
代码如下:
function drop()
方块Y坐标 = 方块Y坐标 - 1 -- 尝试将当前方块下落一行
-- 检测当前方块是否与底部或其它方块发生重叠
if 检查重叠(当前方块, 方块X坐标, 方块Y坐标) then
方块Y坐标 = 方块Y坐标 + 1 -- 如果发生重叠,则将方块位置回退到重叠之前
-- 将当前方块的形状数据复制到游戏场地上
for i = 1, #当前方块 do -- 遍历方块的每一行
for j = 1, #当前方块[1] do -- 遍历方块的每一列
if 当前方块[i][j] ~= 0 then -- 如果方块元素不为空,则将其复制到游戏场地上
主体格子[方块Y坐标 + i - 1][方块X坐标 + j - 1] = 1
end
end
end
-- 检查并消除满行
for i = 方块Y坐标 + #当前方块 - 1, 方块Y坐标, -1 do
local ct = 0 -- 用于统计当前行是否全满的计数器
for j = 1, 10 do
ct = ct + 主体格子[i][j]
end
if ct == 10 then
table.remove(主体格子, i) -- 移除满行
table.insert(主体格子, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) -- 在场地上方补充一行空行
end
end
-- 生成新的随机方块,设置其初始位置
当前方块, 方块X坐标, 方块Y坐标 = 方块组[math.random(7)], 4, 19
end
end
按键事件处理函数
参数: i: 用户按下的键名(例如"left", "right", "up", "down"等)
处理左键按下事件:方块向左移动一格,并检查重叠,如果不重叠,即会更新“当前方块”的位置。
处理右键按下事件:方块向右移动一格,并检查重叠,如果不重叠,即会更新“当前方块”的位置
处理上键按下事件:方块旋转,构建旋转矩阵,若无重叠,则使用旋转后的方块数组为 “当前方块”。
处理下键按下事件:方块加速下落,不断执行下落操作,直到 “当前方块” Y坐标 = 19。
-- 按键事件处理函数
-- 参数:
-- i: 用户按下的键名(例如"left", "right", "up", "down"等)
function love.keypressed(i)
-- 处理左键按下事件:方块向左移动,并检查重叠,如果不重叠,即会更新“当前方块”的位置
if i=="left" then
if not 检查重叠(当前方块,方块X坐标-1,方块Y坐标) then
方块X坐标=方块X坐标-1
end
-- 处理右键按下事件:方块向右移动,并检查重叠,如果不重叠,即会更新“当前方块”的位置
elseif i=="right" then
if not 检查重叠(当前方块,方块X坐标+1,方块Y坐标) then
方块X坐标=方块X坐标+1
end
-- 处理上键按下事件:方块旋转,
elseif i== "up" then
local m={} -- 创建用于存储旋转后方块的新数组
for i=1,#当前方块[1] do -- 构建旋转矩阵
m[i]={}
for j=1,#当前方块 do
m[i][j] = 当前方块[j][#当前方块[1]+1-i]
end
end
if not 检查重叠(m,方块X坐标,方块Y坐标) then
当前方块=m -- 若无重叠,则使用旋转后的方块数组
end
-- 处理下键按下事件:方块加速下落
elseif i=="down" then
repeat drop() -- 不断执行下落操作
until 方块Y坐标==19 --这里执行效果不高,没做判断,应该有多余的循环次数。但结果是符合的。
end
end
引擎主循环函数
在Love引擎启动的时候就会调用love.run,这里程序里需要一个非默认的,所以要自己写一个functionlove.run()-引擎工作函数,
love的run函数重写可以重用。重点哦。
1、初始化计时器
2、设置颜色为红色
3、返回一个游戏循环函数
3.1、处理事件队列
3.2、遍历并处理所有事件,name,a,b,c,d,e,f 是什么呢,要去查一下love.event.poll()的定义去。
3.3、检查是否需要进行下落操作,.6是什么呢,要去查一下love.timer.getTime()的定义去。
3.4、清空画布
3.5、绘制场地
3.6、绘制下落的方块
3.7、更新屏幕显示
然后会再次循环3的步骤。
代码如下:
-- 引擎主循环函数
-- 在Love引擎启动的时候就会调用love.run,这里程序里需要一个非默认的,所以要自己写一个functionlove.run()-引擎工作函数,
-- 重写可以重用。重点哦。
function love.run()
-- 初始化计时器
flag = love.timer.getTime()
-- 设置画笔颜色为红色
love.graphics.setColor(255,0,0)
-- 返回一个游戏循环函数
return function()
-- 处理事件队列
love.event.pump()
-- 遍历并处理所有事件,name,a,b,c,d,e,f 是什么呢,要去查一下love.event.poll()的定义去。
for name,a,b,c,d,e,f in love.event.poll() do
-- 如果事件为退出,则终止游戏循环
if name=="quit" then return 0 end
-- 调用相应的事件处理函数
love.handlers[name](a,b,c,d,e,f)
end
-- 检查是否需要进行下落操作,.6是什么呢,要去查一下love.timer.getTime()的定义去。
if love.timer.getTime()-flag >.6 then
-- 执行下落逻辑
drop()
-- 重置计时器
flag=love.timer.getTime()
end
-- 清空画布
love.graphics.clear(255,255,255)
-- 绘制场地
for j=1,20 do
for i=1,10 do
if 主体格子[j][i]==1 then
--这里的40是相素值,-39是偏移量,因为坐标原点在左上角,而方块的左上角在左下角,所以要偏移。
--这是一个方块的左上角坐标
love.graphics.rectangle("fill",40*i-39,801-40*j,38,38)
end
end
end
-- 绘制下落的方块
for j=1,#当前方块 do
for i=1,#当前方块[1]do
if 当前方块[j][i]==1 then
love.graphics.rectangle("fill",40*(i+方块X坐标-1)-39,801-40*(j+方块Y坐标-1),38,38)
end
end
end
-- 更新屏幕显示
love.graphics.present()
end
end
引用了这位大玩家MrZ_26的bili教程。
59行代码实现俄罗斯方块(lua&love2d)
<iframe src="//player.bilibili.com/player.html?aid=59385769&bvid=BV14t411G7uS&cid=103480280&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>