Lua & Love2D表格加载异常:最后放置的tile随机位移问题
Love2D拖拽Tile释放后随机位移问题修复
我开发的Love2D游戏支持拖拽tile到屏幕指定位置,但释放鼠标后,最后放置的tile会随机位移到屏幕某个位置,点击左上角按钮可复现该问题。
问题代码
local mouseX local mouseY local love = require "love" local placeImg, deleteImg, rotateImg local mouseleftDown = false local placeRail = false local placeNewRail = false local railArray = {} local railIndex = 0 function love.load() placeRail = true -- 全屏设置 love.window.setFullscreen(true, "desktop") placeHolderImg = love.graphics.newImage('PlaceIcon.png') placeImg = love.graphics.newImage('PlaceIcon.png') deleteImg = love.graphics.newImage('DeleteIcon.png') end function love.draw() drawIcons() if(checkPressed(mouseX, mouseY, 5, 100, 10, 100, 100) and mouseleftDown) then placeNewRail = true end if placeNewRail then newRail(placeImg) end drawRails(placeImg, railArray) end function love.update() mouseX = love.mouse.getX() mouseY = love.mouse.getY() if love.mouse.isDown(1) then mouseleftDown = true else mouseleftDown = false end end function drawIcons() love.graphics.draw(placeImg, 100, 10) love.graphics.draw(deleteImg, 300, 10) end function newRail(image) -- 放置轨道 if placeNewRail then currentImgPosX = mouseX currentImgPosY = mouseY love.graphics.draw(image, mouseX, mouseY) if not mouseleftDown then table.insert(railArray, railIndex, currentImgPosX) table.insert(railArray, railIndex + 1, currentImgPosY) railIndex = railIndex + 1 end end if not mouseleftDown then placeNewRail = false end end function drawRails(img, arr) local array = arr local i = 0 for i in pairs(array) do -- 获取数组大小 i = i + 1 local _ = 0 -- 遍历数组绘制元素 while _ < i do love.graphics.draw(img, array[_], array[_+1]) _ = _ + 1 end end end function checkPressed(mouse_x, mouse_y, cursor_radius, button_x, button_y, button_width, button_height) if (mouse_x + cursor_radius >= button_x) and (mouse_x - cursor_radius <= button_x + button_width) then if (mouse_y + cursor_radius >= button_y) and (mouse_y - cursor_radius <= button_y + button_height) then return true end end end function test() return true end -- 后续用的碰撞检测 function detectCollision(a, b) return a.x < b.x + b.width and a.x + a.width > b.x and a.y < b.y + b.height and a.y + a.height > b.y; end
问题根源
- 数组存储逻辑错误:每次插入x和y两个值,但
railIndex只自增1,导致后续插入位置错位、索引混乱。 - 绘制函数逻辑完全错误:
drawRails用pairs遍历数组,内部嵌套while循环重复绘制,触发索引越界,读取到表中未初始化的无效数据。 - 全局变量污染:
currentImgPosX和currentImgPosY是全局变量,可能被意外修改导致坐标错误。 - 按钮检测位置错误:在
love.draw中检测按钮点击,draw函数每帧调用多次,会导致placeNewRail被重复触发,执行多次插入操作。
修复后的代码
local mouseX, mouseY local love = require "love" local placeImg, deleteImg, rotateImg local mouseleftDown = false local placeRail = false local placeNewRail = false -- 改用table存储每个tile的坐标,结构更清晰 local railArray = {} function love.load() placeRail = true love.window.setFullscreen(true, "desktop") placeHolderImg = love.graphics.newImage('PlaceIcon.png') placeImg = love.graphics.newImage('PlaceIcon.png') deleteImg = love.graphics.newImage('DeleteIcon.png') end function love.draw() drawIcons() if placeNewRail then -- 绘制跟随鼠标的预览tile love.graphics.draw(placeImg, mouseX, mouseY) end drawRails(placeImg, railArray) end function love.update() mouseX = love.mouse.getX() mouseY = love.mouse.getY() mouseleftDown = love.mouse.isDown(1) end -- 用love的鼠标点击事件检测按钮,避免重复触发 function love.mousepressed(x, y, button) if button == 1 then if checkPressed(x, y, 5, 100, 10, 100, 100) then placeNewRail = true end end end -- 鼠标释放时完成放置 function love.mousereleased(x, y, button) if button == 1 and placeNewRail then -- 插入当前鼠标坐标作为新tile table.insert(railArray, {x = x, y = y}) placeNewRail = false end end function drawIcons() love.graphics.draw(placeImg, 100, 10) love.graphics.draw(deleteImg, 300, 10) end function drawRails(img, arr) -- 用ipairs遍历顺序数组,每个元素是包含x和y的table for _, tile in ipairs(arr) do love.graphics.draw(img, tile.x, tile.y) end end function checkPressed(mouse_x, mouse_y, cursor_radius, button_x, button_y, button_width, button_height) return (mouse_x + cursor_radius >= button_x) and (mouse_x - cursor_radius <= button_x + button_width) and (mouse_y + cursor_radius >= button_y) and (mouse_y - cursor_radius <= button_y + button_height) end function test() return true end function detectCollision(a, b) return a.x < b.x + b.width and a.x + a.width > b.x and a.y < b.y + b.height and a.y + a.height > b.y; end
关键修改说明
- 数组结构优化:
railArray存储每个tile的坐标table({x=..., y=...}),避免索引混乱,逻辑更清晰。 - 事件拆分:把按钮点击检测移到
love.mousepressed,放置操作移到love.mousereleased,避免每帧重复触发。 - 修复绘制逻辑:用
ipairs遍历数组,直接读取每个tile的x和y,确保正确绘制所有已放置的tile。 - 消除全局变量:移除了全局的
currentImgPosX/Y,直接使用鼠标释放时的坐标。
内容的提问来源于stack exchange,提问作者robert Vincent
相关产品推荐
相关产品推荐

