如何防止renderBlocks()函数进入无限循环?
2021-4-21 20:4:40
收藏:0
阅读:145
评论:3
-- 这是Minecraft,但是是2D和Lua。
-- **************************************
-- ID 0:Air
-- ID 1:Stone
-- ID 2 Logs
-- ID 3:Leaves
-- ID 4:Planks
-- ID 5:工作台
-- ID 6:熔炉
-- ID 7:玩家位置探测器块
-- **************************************
blockTable = { -- 存储所有块
{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},
{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},
{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},
{0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6}
}
tableRow = 1 --块渲染指针在Y轴上的值
tableColumn = 1 --块渲染指针在X轴上的值
runOnce = true --仅仅运行一个循环
tickNum = 0 --自启动以来的滴答数
function renderBlock(X, Y, K) --渲染一个块
if K == 1 then --如果块ID== 1,则绘制一个灰色正方形
screen.setColor(100,100,100)
print(X, Y)
screen.drawRectF(X, Y, 8, 8)
end
if K == 6 then --如果块ID ==绘制灰色正方形
screen.setColor(100,100,100)
screen.drawRectF(X, Y, 8, 8)
end
end
function renderBlocks() --渲染所有块(以光栅模式扫描块表)
while runOnce == true --运行此代码一次
do
while #blockTable >= tableRow
do
while #blockTable[tableRow] >= tableColumn
do
print("TC " .. tableColumn)
tableColumn = tableColumn + 1
blockID = blockTable[tableRow][tableColumn]
renderBlock(tableRow, tableColumn, blockID)
if tableColumn > #blockTable[tableRow] then tableColumn = 1 end
end
runOnce = false
end
print("TR " .. tableRow)
tableRow = tableRow + 1
end
end
function onTick()
print("Tick! Tick count: " .. tickNum) --打印当前滴答,以及说有一个滴答
tickNum = tickNum + 1
end
function onDraw()
while runOnce == true --运行此代码一次
do
renderBlocks()
runOnce = false
end
end
这是我在框架IDE中的代码:链接
我不知道为什么会出现这种情况,我感到迷茫。
点赞
用户7396148
您的 renderBlocks() 函数存在几个问题:
function renderBlocks()
while runOnce == true do
while #blockTable >= tableRow do
while #blockTable[tableRow] >= tableColumn do
print("TC " .. tableColumn)
tableColumn = tableColumn + 1
blockID = blockTable[tableRow][tableColumn]
renderBlock(tableRow, tableColumn, blockID)
if tableColumn > #blockTable[tableRow] then
tableColumn = 1
end
end
runOnce = false
end
print("TR " .. tableRow)
tableRow = tableRow + 1
end
end
首先,我们可以看一下最内层的循环。在这里,我们有一个与循环相关的问题,以及如何增加问题。
while #blockTable[tableRow] >= tableColumn do
print("TC " .. tableColumn)
tableColumn = tableColumn + 1 -- 在此处增加
blockID = blockTable[tableRow][tableColumn]
renderBlock(tableRow, tableColumn, blockID)
if tableColumn > #blockTable[tableRow] then
tableColumn = 1 -- 在此处重置
end
end
在循环体中,您执行了 tableColumn = tableColumn + 1,稍后在相同的循环体中,您执行了 if tableColumn > #blockTable[tableRow] then tableColumn = 1 end,因此当 tableColumn 增加到会结束循环的值时,我们将它重置为 1,从而防止循环结束。
现在让我们再来看一下外层的循环。这里我们从不增加 tableRow,它仅在此循环结束后增加,因此循环不可能结束。
while #blockTable >= tableRow do
while #blockTable[tableRow] >= tableColumn do
...
end
runOnce = false
end
我认为您打算将
print("TR " .. tableRow)
tableRow = tableRow + 1
放在此循环内而不是外面。
2021-04-21 20:35:30
用户3342050
少了一些区块定义。否则你可能看不到结果
function renderBlock(X, Y, blockID) -- 渲染一个方块
if blockID == 0 then -- 空气
-- screen.setColor(10, 20, 220, 0) -- 是否有 alpha 通道?
screen.setColor(10, 20, 220)
elseif blockID == 1 then -- 石头
screen.setColor(100, 100, 100)
elseif blockID == 2 then -- 木头
screen.setColor(200, 50, 50)
elseif blockID == 3 then -- 树叶
screen.setColor(20, 220, 40)
elseif blockID == 4 then -- 木板
screen.setColor(180, 30, 10)
elseif blockID == 5 then -- 工作台
screen.setColor(180, 30, 10)
elseif blockID == 6 then -- 火炉
screen.setColor(100, 100, 100)
elseif blockID == 7 then -- 玩家检测
screen.setColor(220, 30, 30)
end
print(X, Y)
screen.drawRectF(X, Y, 8, 8)
end
循环 for 很容易。设置起始条件和最终完成条件,然后让它自动运行。
function renderBlocks() -- 渲染所有块(以栅格方式扫描 blockTable)
for row = 1, #blockTable do
for col = 1, #blockTable[row] do
print("TC " ..col)
local blockID = blockTable[row][col]
renderBlock(row, col, blockID)
end
print("TR " ..row)
end
end
你可能不需要 runOnce。如果你发现你需要用到它,那就去吧,但在嵌套循环中不需要。
function onDraw()
renderBlocks()
end
2021-04-22 01:06:43
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

在遍历表格时,使用for循环比使用while或repeat循环更好,因为后者更难理解和修复错误。
如果你想获取表格中的索引(即表格中的数字)和相关的值,则使用
for index,value in ipairs(yourtable) do,如果想获取键(通常是作为值的键使用的字符串:yourTable ["key"] = 0)和与之关联的值,则使用for key,value in pairs(yourtable) do。for row,innerTable in ipairs(blockTable) do for col,value in ipairs(innerTable) do print("TC " .. col) blockID = value renderBlock(row, col, blockID) end end最后一个语句应该放在你的
renderBlock函数中。但是这个while循环不是很好。如果它只需要执行一次,就不要把它放在循环中!此外,更好的代码缩进能够更快地了解正在发生的事情。在处理不同问题的代码块之间添加一些空格也会有所帮助。
编辑:因此,你的函数应该像这样:
function renderBlocks() if runOnce then runOnce = false for row,innerTable in ipairs(blockTable) do for col,value in ipairs(innerTable) do blockID = value renderBlock(row, col, blockID) end end end end