【容易不简单】love 2d Lua 俄罗斯方块超详细教程

news2024/11/25 14:34:42
源码已经更新在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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1563584.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【深耕 Python】Data Science with Python 数据科学(7)书352页练习题

写在前面 关于数据科学环境的建立&#xff0c;可以参考我的博客&#xff1a; 【深耕 Python】Data Science with Python 数据科学&#xff08;1&#xff09;环境搭建 往期数据科学博文&#xff1a; 【深耕 Python】Data Science with Python 数据科学&#xff08;2&#xf…

苹果开发者账号注册步骤中的常见疑问解答与技巧分享

转载&#xff1a;注册苹果开发者账号的方法 在2020年以前&#xff0c;注册苹果开发者账号后&#xff0c;就可以生成证书。 但2020年后&#xff0c;因为注册苹果开发者账号需要使用Apple Developer app注册开发者账号&#xff0c;所以需要缴费才能创建ios证书了。 所以新政策出…

算法系列--递归,回溯,剪枝的综合应用(3)

&#x1f495;"对相爱的人来说&#xff0c;对方的心意&#xff0c;才是最好的房子。"&#x1f495; 作者&#xff1a;Lvzi 文章主要内容&#xff1a;算法系列–递归,回溯,剪枝的综合应用(3) 大家好,今天为大家带来的是算法系列--递归,回溯,剪枝的综合应用(3),带来几…

深入浅出:大模型产业链的全景解码

大模型产业仿佛如同一场盛宴&#xff0c;虽然AGI的菜肴还没有上桌&#xff0c;但掩盖不住的香味已经让所有人垂涎&#xff0c;都希望自己将来在餐桌上能够“吃饱饱”。这也是一场没有邀请函的宴席&#xff0c;从尚在学校的学生到公司的决策层&#xff0c;都能在生成式AI的相关研…

简单而复杂的Python

Python是一种简单&复杂的编程语言。简单的时候可以到极致&#xff1a; print(hello world!)另一方面&#xff0c;Python 也具有许多复杂的语法特性&#xff0c;例如面向对象编程、装饰器、迭代器、生成器等等。这些特性使得 Python 适用于各种不同的编程任务和项目。 当我…

【JavaWeb】Day31.SpringBootWeb请求响应——分层解耦(二)

3.IOC&DI 3.1 IOC&DI入门 完成Controller层、Service层、Dao层的代码解耦 思路&#xff1a; 1. 删除Controller层、Service层中new对象的代码 2. Service层及Dao层的实现类&#xff0c;交给IOC容器管理 3. 为Controller及Service注入运行时依赖的对象 Controller程序…

HarmonyOS 应用开发之同步任务开发指导 (TaskPool和Worker)

同步任务是指在多个线程之间协调执行的任务&#xff0c;其目的是确保多个任务按照一定的顺序和规则执行&#xff0c;例如使用锁来防止数据竞争。 同步任务的实现需要考虑多个线程之间的协作和同步&#xff0c;以确保数据的正确性和程序的正确执行。 由于TaskPool偏向于单个独…

【Java代码审计】SSTI模板注入篇

【Java代码审计】SSTI模板注入篇 1.概述2.Velocity 模板引擎3.Thymeleaf 模板注入复现普通url作为视图 4.SSTI 漏洞修复白名单控制跳转模版设置response参数 1.概述 模板引擎支持使用静态模板文件&#xff0c;在运行时用 HTML 页面中的实际值替换变量/占位符&#xff0c;从而让…

蓝桥杯刷题第六天(昨天忘记发了)

今天想从不一样的角度来解题&#xff1a;从时间紧张暴力求解到思路阔达直接通过所有案例 暴力方法&#xff1a; 思路第一眼看到这个问题我就想到了第一个思路就是先用两个数组一个存石子数一个存颜色状态&#xff0c;每次遍历一遍看看有没有相邻石子颜色一样且为和最小的。 im…

如何整合当地商家资源?如何进行二次变现?

随着市场竞争的日益激烈&#xff0c;商家们纷纷寻求创新的营销方式来扩大市场份额、提升品牌影响力。异业联盟作为一种新型的商业合作模式&#xff0c;正逐渐受到业界的关注和认可。本文将探讨异业联盟的可行性&#xff0c;并分析其是否可以通过小程序形式实现更广泛的应用。 一…

zip解压异常java.lang.IllegalArgumentException: MALFORMED处理

使用hutool解压zip包时出错&#xff1a; //压缩包解压到固定目录 ZipUtil.unzip(tempZipFile,dir);在解压文件的时候报错&#xff0c;原因是压缩文件中有中文&#xff1b;导致错误&#xff0c;解决办法是设置编码&#xff1a; ZipFile tempZipFile new ZipFile(zipFile, Cha…

h5 笔记1

Internet是InternationalNetwork的缩写&#xff0c;又称“因特网”。它是将全世界数以千计的上网设备通过TCP/IP通信协议连接在一起。Internet上的服务众多&#xff0c;主要的服务有WWW(万维网)、E-Mail(电子邮件)、FTP(FileTransferProtocol&#xff0c;文件传输协议)、Telnet…

Ps:颜色查找

颜色查找 Color Lookup命令通过应用预设的 LUT 来改变图像的色彩和调性&#xff0c;从而为摄影师和设计师提供了一种快速实现复杂色彩调整的方法&#xff0c;广泛应用于颜色分级、视觉风格的统一和创意色彩效果的制作。 Ps菜单&#xff1a;图像/调整/颜色查找 Adjustments/Colo…

微信小程序-文字转语音(播放及暂停)

1、使用微信小程序的同声传译功能 小程序平台-设置-第三方设置-插件管理-新增同声传译插件 小程序app.json文件配置 "plugins": {"WechatSI": {"version": "0.3.5","provider": "wx069ba97219f66d99"}},小程序中…

python生物信息多组学大数据深度挖掘与论文整理技巧技术应用

生物信息广泛涵盖基因组学、蛋白组学、系统生物学、表观遗传、非编码等前沿领域以及药物设 计、基因工程等应用领域。与传统的理论和实验学科不同&#xff0c;生物信息是一门数据科学&#xff0c;这就需要从业 者具备一定数据收集、管理、处理和分析的能力。在海量的组学数据面…

一文搞懂:Java项目线上故障处理和调优的基本方法

一. 调优和故障处理的方向 Java调优通常指的是对Java应用程序进行性能优化和资源管理的过程。调优的方向很多也很广&#xff0c;比如&#xff1a; 内存管理&#xff1a;优化Java应用程序的内存使用&#xff0c;包括减少内存泄漏、合理设置堆大小、优化垃圾收集器的选择和参数…

PyQt qrc2py 使用PowerShell将qrc文件转为py文件并且将导入模块PyQt或PySide转换为qtpy模块开箱即用

前言 由于需要使用不同的qt环境&#xff08;PySide&#xff0c;PyQt&#xff09;所以写了这个脚本&#xff0c;使用找到的随便一个rcc命令去转换qrc文件&#xff0c;然后将导入模块换成qtpy这个通用库(支持pyside2-6&#xff0c;pyqt5-6)&#xff0c;老版本的是Qt.py(支持pysi…

力扣Lc26--- 1108. IP 地址无效化(java版)-2024年4月02日

1.题目描述 2.知识点 注1&#xff1a;首先&#xff0c;在Java中&#xff0c;字符类型应该使用单引号’&#xff0c;而不是双引号"。其次&#xff0c;修改字符数组中的元素应该使用单引号。 注2&#xff1a;String类的replace方法用于在字符串中替换指定的字符或字符序列。…

OpenHarmony实战:RK3568 开发板镜像烧录指南

前言 烧录开发板是每个开发者的必修课&#xff0c;每次对系统的修改务必进行烧录测试&#xff0c;确保修改正确和不会引入新问题。 本文基于 Windows10&#xff0c;以 RK3568 开发板为例&#xff0c;指导如何烧录 OpenHarmony 镜像&#xff0c;镜像也叫固件。Hihoop&#xff…

芒果YOLOv5改进89:卷积SPConv篇,即插即用,去除特征图中的冗余,FLOPs 和参数急剧下降,提升小目标检测

芒果专栏 基于 SPConv 的改进结构,改进源码教程 | 详情如下🥇 👉1. SPConv 结构、👉2. CfSPConv 结构 💡本博客 改进源代码改进 适用于 YOLOv5 按步骤操作运行改进后的代码即可 即插即用 结构。博客 包括改进所需的 核心结构代码 文件 YOLOv5改进专栏完整目录链接:…