Finding the translation to offset the zoom.
Posted: Sat Sep 20, 2014 8:38 pm
Hello out there,
I am hoping (more like desperately pleading) that somebody here will be able to help me. I have a problem regarding scaling that I have been stuck on for years! I know that it is a relatively simple problem, and I've tried my best to find a solution, but nothing I have tried has worked.
The Context
My project is top-down and implements a camera system which will follow the player and keep him close to the center of the screen.
The Problem
So naturally when I use love.graphics.scale() it zooms from the top left. I need to implement zooming over any particular point I choose. I know that there are plenty of tutorials and articles online explaining this but never any that I've been able to fully grasp or translate into my own working code.
What I Hope For
I'm going to post my code below consisting of my camera object and my main file. I'm effectively begging the love community to show me how to get this working within the context of the code I have. If my camera system is inadequate any examples of how to do this using the hump camera would be helpful as well. I've looked at all the info I could find regarding that camera system.
In a Nutshell
When it comes down to it, all I really need is the formula to arrive at the x and y values I need to translate the camera by to offset the zoom.
The Code
Most of the relevant code is in the mouse handling functions responding to 'mouse wheel up and down' input. The code in there now was adapted from another love tutorial implementing zooming but is not working in the context of my code. Please help if you can, at the risk of sounding dumb, I fully admit that I cannot figure this out on my own. Been trying a long time. Thanks in advance!
The Camera
Main
I am hoping (more like desperately pleading) that somebody here will be able to help me. I have a problem regarding scaling that I have been stuck on for years! I know that it is a relatively simple problem, and I've tried my best to find a solution, but nothing I have tried has worked.
The Context
My project is top-down and implements a camera system which will follow the player and keep him close to the center of the screen.
The Problem
So naturally when I use love.graphics.scale() it zooms from the top left. I need to implement zooming over any particular point I choose. I know that there are plenty of tutorials and articles online explaining this but never any that I've been able to fully grasp or translate into my own working code.
What I Hope For
I'm going to post my code below consisting of my camera object and my main file. I'm effectively begging the love community to show me how to get this working within the context of the code I have. If my camera system is inadequate any examples of how to do this using the hump camera would be helpful as well. I've looked at all the info I could find regarding that camera system.
In a Nutshell
When it comes down to it, all I really need is the formula to arrive at the x and y values I need to translate the camera by to offset the zoom.
The Code
Most of the relevant code is in the mouse handling functions responding to 'mouse wheel up and down' input. The code in there now was adapted from another love tutorial implementing zooming but is not working in the context of my code. Please help if you can, at the risk of sounding dumb, I fully admit that I cannot figure this out on my own. Been trying a long time. Thanks in advance!
The Camera
Code: Select all
Camera = {}
--------------------------- Basic Functions -||
function Camera:new(o)
o=o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Camera:init(x, y)
self.width = love.window.getWidth()
self.height = love.window.getHeight()
self.halfWidth = self.width / 2
self.halfHeight = self.height / 2
self.x = x
self.y = y
self.rotation = 0
self.zoom = 1
self.displayInfo = true
end
function Camera:set()
love.graphics.push()
love.graphics.rotate(-self.rotation)
love.graphics.scale(self.zoom, self.zoom)
love.graphics.translate(-self.x, -self.y)
end
function Camera:unset()
love.graphics.pop()
end
function Camera:reset()
self.x = 0
self.y = 0
self.rotation = 0
self.zoom = 1
end
function Camera:move(dx, dy)
self.x = self.x + (dx or 0)
self.y = self.y + (dy or 0)
end
function Camera:rotate(dr)
self.rotation = self.rotation + dr
end
function Camera:scale(amt)
amt = amt or 1
oldZoom = self.zoom
self.zoom = self.zoom * amt
return oldZoom
end
function Camera:setPosition(x, y)
self.x = x or self.x
self.y = y or self.y
end
function Camera:setScale(amt)
self.zoom = amt or self.zoom
end
function Camera:incScale(amt)
self.zoom = self.zoom + amt
end
-----------------------------Extra Functions -||
function Camera:inform()
local info = tostring(self.x) .. ", " .. tostring(self.y)
love.graphics.print(info, 0, 0)
love.graphics.print(self.zoom, 0, 12)
end
function Camera:toggleInfo()
self.displayInfo = not self.displayInfo
end
function Camera:draw()
if self.displayInfo then self:inform() end
end
Code: Select all
require 'camera'
----------------------------Love functions -||
function love.load()
camera = Camera:new()
camera:init(0, 0)
img = love.graphics.newImage('testShip.png')
--I start the ship so that it is at the centre of the camera's view
shipWorldx = camera.halfWidth
shipWorldy = camera.halfHeight
end
function love.update(dt)
cameraInputHandling() --This is here for testing purposes
end
function love.draw()
camera:set()
love.graphics.draw(img, shipWorldx, shipWorldy)
camera:unset()
--Draw a circle at the centre of the screen for reference
love.graphics.setColor(0, 255, 0)
love.graphics.circle('fill', camera.halfWidth, camera.halfHeight, 15, 360)
love.graphics.setColor(255, 255, 255)
camera:draw() --For now, simply displays camera's world co-ordinates
end
function love.keyreleased(key)
if key == 'escape' then
love.event.push('quit')
end
if key == 'i' then
camera:toggleInfo()
end
if key == 'r' then
camera:reset()
end
end
--I must be doing something wrong in here...right?
function love.mousepressed(x, y, button) if button == 'wu' then
local mousex = x - camera.x
local mousey = y - camera.y
local lastZoom = camera.zoom
camera:incScale(0.1)
local newx = mousex * (camera.zoom / lastZoom)
local newy = mousey * (camera.zoom / lastZoom)
local tx = mousex - newx
local ty = mousey - newy
camera:move(tx, ty)
end
if button == 'wd' then
local mousex = x - camera.x
local mousey = y - camera.y
local lastZoom = camera.zoom
camera:incScale(-0.1)
local newx = mousex * (camera.zoom / lastZoom)
local newy = mousey * (camera.zoom / lastZoom)
local tx = mousex - newx
local ty = mousey - newy
camera:move(tx, ty)
end
end
---------------------------------My functions -||
function cameraInputHandling()
if love.keyboard.isDown('right') then camera:move(1) end
if love.keyboard.isDown('left') then camera:move(-1) end
if love.keyboard.isDown('up') then camera:move(0, -1) end
if love.keyboard.isDown('down') then camera:move(0, 1) end
end