基于LÖVE2D的射击游戏角色朝向鼠标光标问题求助
解决LÖVE2D角色朝向鼠标的问题
原代码存在的核心问题
- 鼠标坐标未转换:使用push虚拟分辨率时,窗口坐标和虚拟坐标不匹配,直接调用
love.mouse.getX()会导致瞄准偏移,需用push:toGame()转换。 - 角色位置初始化错误:
love.graphics.getWidth()在push:setupScreen()前调用,获取的是窗口尺寸而非虚拟尺寸,且应将角色位置设置在虚拟画布中心。 - draw参数顺序错误:
love.graphics.draw的旋转参数应在位置之后,原点参数在缩放之后,原代码参数顺序完全颠倒,导致旋转失效。 - 角度单位错误:LÖVE的旋转使用弧度,原代码将
atan2的结果转成角度传入,会导致旋转异常。 - 游戏状态逻辑缺失:未处理空格按键切换状态,且角色绘制在
push:apply('end')之后,不在虚拟画布上显示。
修正后的完整代码
local data = {} push = require 'push' Class = require 'class' WINDOW_WIDTH = 1280 WINDOW_HEIGHT = 720 VIRTUAL_WIDTH = 432 VIRTUAL_HEIGHT = 243 function love.load() love.graphics.setDefaultFilter('nearest', 'nearest') love.window.setTitle('Alien Shooter') math.randomseed(os.time()) -- 初始化字体 smallFont = love.graphics.newFont('font.ttf', 8) largeFont = love.graphics.newFont('font.ttf', 16) scoreFont = love.graphics.newFont('font.ttf', 32) love.graphics.setFont(smallFont) PlayerScore = 0 -- 先初始化push,再设置角色位置 push:setupScreen(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT, { fullscreen = false, resizable = true, vsync = true }) -- 加载角色 sprite 并设置初始位置(虚拟画布中心) MCSprite = love.graphics.newImage("MC.png") data.width = MCSprite:getWidth() data.height = MCSprite:getHeight() data.x = VIRTUAL_WIDTH / 2 data.y = VIRTUAL_HEIGHT / 2 data.originX = data.width / 2 data.originY = data.height / 2 gameState = 'start' end function love.resize(w, h) push:resize(w, h) end function love.update(dt) if gameState == 'play' then -- 将鼠标窗口坐标转换为虚拟坐标 local mouseX, mouseY = push:toGame(love.mouse.getX(), love.mouse.getY()) -- 计算角色到鼠标的角度(弧度,LÖVE默认使用弧度) if mouseX and mouseY then -- 确保鼠标在虚拟画布内 local dx = mouseX - data.x local dy = mouseY - data.y data.angle = math.atan2(dy, dx) end end end function love.keypressed(key) if key == 'escape' then love.event.quit() elseif key == 'space' then -- 切换游戏状态 gameState = gameState == 'start' and 'play' or 'start' end end function love.draw() push:apply('start') if gameState == 'start' then -- 开始界面绘制 love.graphics.printf('ALIEN SHOOTER!', 0, VIRTUAL_HEIGHT / 2 - 6, VIRTUAL_WIDTH, 'center') love.graphics.printf('Press SPACE to Start!', 0, VIRTUAL_HEIGHT / 2 + 12, VIRTUAL_WIDTH, 'center') else -- 游戏界面绘制:角色朝向鼠标 love.graphics.draw(MCSprite, data.x, data.y, data.angle, 1, 1, data.originX, data.originY) -- 可选:显示分数 love.graphics.setFont(scoreFont) love.graphics.print(tostring(PlayerScore), VIRTUAL_WIDTH - 50, 10) end push:apply('end') end
关键修正说明
- 坐标转换:用
push:toGame()将鼠标的窗口坐标转为虚拟坐标,确保瞄准位置和角色在同一坐标系。 - 角色位置:在push初始化后,基于
VIRTUAL_WIDTH和VIRTUAL_HEIGHT设置角色中心位置,保证在虚拟画布内。 - draw参数顺序:修正为
(图像, x, y, 旋转弧度, 缩放X, 缩放Y, 原点X, 原点Y),让旋转和原点偏移生效。 - 角度计算:直接使用
math.atan2(dy, dx)的弧度结果,无需转角度,匹配LÖVE的旋转要求。 - 状态切换:添加空格按键切换start/play状态,角色仅在play状态下绘制并更新瞄准逻辑。
内容的提问来源于stack exchange,提问作者Ahmet Talha
相关产品推荐
相关产品推荐

