Mouse: How to emulate "MouseLook" from FPS games?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
T-Bone
Inner party member
Posts: 1492
Joined: Thu Jun 09, 2011 9:03 am

Re: Mouse: How to emulate "MouseLook" from FPS games?

Post by T-Bone »

First rule of engineering: sin(x) ≈ x for small x ;)
User avatar
IMP1
Prole
Posts: 43
Joined: Mon Oct 03, 2011 8:46 pm

Re: Mouse: How to emulate "MouseLook" from FPS games?

Post by IMP1 »

This kinda works for me:

Code: Select all

function love.load()
  TURN_SPEED = 0.005
  VISION_LENGTH = 1
  inverseYAxis = true
  
  horizontalAngle = 0
  verticalAngle = 0
  
  love.mouse.setGrab(true)
  love.mouse.setVisible(false)
  love.mouse.setPosition( love.graphics.getWidth() / 2, love.graphics.getHeight() / 2 )
  oldMouse = { love.mouse.getPosition() }
end

function love.update(dt)
  if love.keyboard.isDown("q") then
    love.event.push("q")
  end
  
  local dx = love.mouse.getX() - oldMouse[1]
  local dy = love.mouse.getY() - oldMouse[2]
  if dx ~= 0 then
    local angle = math.atan( (dx * TURN_SPEED) / VISION_LENGTH )
    horizontalAngle = (horizontalAngle + angle) % (math.pi * 2)
  end
  if dy ~= 0 then
    local angle = math.atan( (dy * TURN_SPEED) / VISION_LENGTH )
    if inverseYAxis then
      verticalAngle = math.max(math.min(verticalAngle + angle, math.pi / 2), -math.pi / 2)
    else
      verticalAngle = math.max(math.min(verticalAngle - angle, math.pi / 2), -math.pi / 2)
    end
  end
  love.mouse.setPosition(love.mouse.getX() - dx, love.mouse.getY() - dy)
end

function love.draw()
  love.graphics.print( "horiz: "..(horizontalAngle * 180 / math.pi), 16, 16 )
  love.graphics.print( "verti: "..(verticalAngle * 180 / math.pi), 16, 32 )
  love.graphics.circle( "line", love.graphics.getWidth() / 2, love.graphics.getHeight() / 2, 5 )
end
All angles are done in radians, but it prints them out in degrees, as I find them easier to read/understand. And it's easier to see how the angle is changing (radians are too small).
User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: Mouse: How to emulate "MouseLook" from FPS games?

Post by Boolsheet »

IMP1 wrote:This kinda works for me.
Interesting. A hidden cursor works like a charm with updates on every frame.
Shallow indentations.
User avatar
T-Bone
Inner party member
Posts: 1492
Joined: Thu Jun 09, 2011 9:03 am

Re: Mouse: How to emulate "MouseLook" from FPS games?

Post by T-Bone »

IMP1's solution totally works.
User avatar
IMP1
Prole
Posts: 43
Joined: Mon Oct 03, 2011 8:46 pm

Re: Mouse: How to emulate "MouseLook" from FPS games?

Post by IMP1 »

It's not perfect in terms of the angle. It should be slightly less, but the maths is a lot more confusing.

Code: Select all

local angle = math.atan( (dx * TURN_SPEED) / VISION_LENGTH )
should be

Code: Select all

local y = math.sqrt(math.abs(VISION_LENGTH ^ 2 - dx ^ 2))
local angle = math.atan( (dx * TURN_SPEED) / y )
Not sure about this, but I have this drawn out
Image
Other quadrants might need adjusting for. And if visionLength is large, then visionLength^2 - dx^2 is roughly visionLength^2.

*shrug*

EDIT: So I guess with this maths-ness, it becomes:

Code: Select all

-- main.lua
function love.load()
  TURN_SPEED = 1
  VISION_LENGTH = 100
  inverseYAxis = true
  
  horizontalAngle = 0
  verticalAngle = 0
  
  love.mouse.setGrab(true)
  love.mouse.setVisible(false)
  love.mouse.setPosition( love.graphics.getWidth() / 2, love.graphics.getHeight() / 2 )
  oldMouse = { love.mouse.getPosition() }
end

function love.update(dt)
  if love.keyboard.isDown("q") then
    love.event.push("q")
  end
  
  local dx = love.mouse.getX() - oldMouse[1]
  local dy = love.mouse.getY() - oldMouse[2]
  if dx ~= 0 then
    local angle = math.atan( (dx * TURN_SPEED) / math.sqrt(math.abs(VISION_LENGTH^2 - dx^2)) )
    horizontalAngle = (horizontalAngle + angle) % (math.pi * 2)
  end
  if dy ~= 0 then
    local angle = math.atan( (dy * TURN_SPEED) / math.sqrt(math.abs(VISION_LENGTH^2 - dy^2)) )
    if inverseYAxis then
      verticalAngle = math.max(math.min(verticalAngle + angle, math.pi / 2), -math.pi / 2)
    else
      verticalAngle = math.max(math.min(verticalAngle - angle, math.pi / 2), -math.pi / 2)
    end
  end
  love.mouse.setPosition(love.mouse.getX() - dx, love.mouse.getY() - dy)
end

function love.draw()
  love.graphics.print( "horiz: "..(horizontalAngle * 180 / math.pi), 16, 16 )
  love.graphics.print( "verti: "..(verticalAngle * 180 / math.pi), 16, 32 )
  love.graphics.circle( "line", love.graphics.getWidth() / 2, love.graphics.getHeight() / 2, 5 )
end
TURN_SPEED and VISION_LENGTH need to be edited to suit yer wolfen-thingamybob.
Post Reply

Who is online

Users browsing this forum: No registered users and 224 guests