hump.camera¶
Camera = require "hump.camera"
A camera utility for LÖVE. A camera can “look” at a position. It can zoom in and out and it can rotate it’s view. In the background, this is done by actually moving, scaling and rotating everything in the game world. But don’t worry about that.
Example:
function love.load()
camera = Camera(player.pos.x, player.pos.y)
end
function love.update(dt)
local dx,dy = player.x - camera.x, player.y - camera.y
camera:move(dx/2, dy/2)
end
function love.draw()
camera:attach()
-- do your drawing here
camera:detach()
end
List of Functions¶
Camera.new(x,y, zoom, rot)
camera:move(dx,dy)
camera:lookAt(x,y)
camera:position()
camera:rotate(angle)
camera:rotateTo(angle)
camera:zoom(mul)
camera:zoomTo(zoom)
camera:attach()
camera:detach()
camera:draw(func)
camera:worldCoords(x, y)
camera:cameraCoords(x, y)
camera:mousePosition()
camera:lockX(x, smoother, ...)
camera:lockY(y, smoother, ...)
camera:lockPosition(x,y, smoother, ...)
camera:lockWindow(x,y, x_min, x_max, y_min, y_max, smoother, ...)
Camera.smooth.none()
Camera.smooth.linear(speed)
Camera.smooth.damped(stiffness)
Function Reference¶
-
Camera.
new
(x, y, zoom, rot)¶ Arguments: - x,y (numbers) – Point for the camera to look at. (optional)
- zoom (number) – Camera zoom. (optional)
- rot (number) – Camera rotation in radians. (optional)
Returns: A new camera.
Creates a new camera. You can access the camera position using camera.x,
camera.y
, the zoom using camera.scale
and the rotation using camera.rot
.
The module variable name can be used at a shortcut to new()
.
Example:
camera = require 'hump.camera'
-- camera looking at (100,100) with zoom 2 and rotated by 45 degrees
cam = camera(100,100, 2, math.pi/2)
-
camera:move
(dx, dy)¶ Arguments: - dx,dy (numbers) – Direction to move the camera.
Returns: The camera.
Move the camera by some vector. To set the position, use
camera:lookAt()
.
This function is shortcut to camera.x,camera.y = camera.x+dx, camera.y+dy
.
Examples:
function love.update(dt)
camera:move(dt * 5, dt * 6)
end
function love.update(dt)
camera:move(dt * 5, dt * 6):rotate(dt)
end
-
camera:lookAt
(x, y)¶ Arguments: - x,y (numbers) – Position to look at.
Returns: The camera.
Let the camera look at a point. In other words, it sets the camera position. To
move the camera by some amount, use camera:move()
.
This function is shortcut to camera.x,camera.y = x, y
.
Examples:
function love.update(dt)
camera:lookAt(player.pos:unpack())
end
function love.update(dt)
camera:lookAt(player.pos:unpack()):rotate(player.rot)
end
-
camera:position
()¶ Returns: x,y
– Camera position.
Returns camera.x, camera.y
.
Example:
-- let the camera fly!
local cam_dx, cam_dy = 0, 0
function love.mousereleased(x,y)
local cx,cy = camera:position()
dx, dy = x-cx, y-cy
end
function love.update(dt)
camera:move(dx * dt, dy * dt)
end
-
camera:rotate
(angle)¶ Arguments: - angle (number) – Rotation angle in radians
Returns: The camera.
Rotate the camera by some angle. To set the angle use camera:rotateTo()
.
This function is shortcut to camera.rot = camera.rot + angle
.
Examples:
function love.update(dt)
camera:rotate(dt)
end
function love.update(dt)
camera:rotate(dt):move(dt,dt)
end
-
camera:rotateTo
(angle)¶ Arguments: - angle (number) – Rotation angle in radians
Returns: The camera.
Set rotation: camera.rot = angle
.
Example:
camera:rotateTo(math.pi/2)
-
camera:zoom
(mul)¶ Arguments: - mul (number) – Zoom change. Should be > 0.
Returns: The camera.
Multiply zoom: camera.scale = camera.scale * mul
.
Examples:
camera:zoom(2) -- make everything twice as big
camera:zoom(0.5) -- ... and back to normal
camera:zoom(-1) -- mirror and flip everything upside down
-
camera:zoomTo
(zoom)¶ Arguments: - zoom (number) – New zoom.
Returns: The camera.
Set zoom: camera.scale = zoom
.
Example:
camera:zoomTo(1) -- reset zoom
-
camera:attach
()¶
Start looking through the camera.
Apply camera transformations, i.e. move, scale and rotate everything until
camera:detach()
as if looking through the camera.
Example:
function love.draw()
camera:attach()
draw_world()
camera:detach()
draw_hud()
end
-
camera:detach
()¶
Stop looking through the camera.
Example:
function love.draw()
camera:attach()
draw_world()
camera:detach()
draw_hud()
end
-
camera:draw
(func)¶ Arguments: - func (function) – Drawing function to be wrapped.
Wrap a function between a camera:attach()
/camera:detach()
pair.
Equivalent to:
camera:attach()
func()
camera:detach()
Example:
function love.draw()
camera:draw(draw_world)
draw_hud()
end
-
camera:worldCoords
(x, y)¶ Arguments: - x, y (numbers) – Point to transform.
Returns: x,y
– Transformed point.
Because a camera has a point it looks at, a rotation and a zoom factor, it defines a coordinate system. A point now has two sets of coordinates: One defines where the point is to be found in the game world, and the other describes the position on the computer screen. The first set of coordinates is called world coordinates, the second one camera coordinates. Sometimes it is needed to convert between the two coordinate systems, for example to get the position of a mouse click in the game world in a strategy game, or to see if an object is visible on the screen.
camera:worldCoords()
and camera:cameraCoords()
transform points
between these two coordinate systems.
Example:
x,y = camera:worldCoords(love.mouse.getPosition())
selectedUnit:plotPath(x,y)
-
camera:cameraCoords
(x, y)¶ Arguments: - x, y (numbers) – Point to transform.
Returns: x,y
– Transformed point.
Because a camera has a point it looks at, a rotation and a zoom factor, it defines a coordinate system. A point now has two sets of coordinates: One defines where the point is to be found in the game world, and the other describes the position on the computer screen. The first set of coordinates is called world coordinates, the second one camera coordinates. Sometimes it is needed to convert between the two coordinate systems, for example to get the position of a mouse click in the game world in a strategy game, or to see if an object is visible on the screen.
camera:worldCoords()
and camera:cameraCoords()
transform points
between these two coordinate systems.
Example:
x,y = camera:cameraCoords(player.pos.x, player.pos.y)
love.graphics.line(x, y, love.mouse.getPosition())
-
camera:mousePosition
()¶ Returns: Mouse position in world coordinates.
Shortcut to camera:worldCoords(love.mouse.getPosition())
.
Example:
x,y = camera:mousePosition()
selectedUnit:plotPath(x,y)
Camera Movement Control¶
Camera movement is one of these things that go almost unnoticed when done well, but add a lot to the overall experience. The article Scroll Back: The Theory and Practice of Cameras in SideScrollers by Itay Keren gives a lot of insight into how to design good camera systems.
hump.camera offers functions that help to implement most of the techniques
discussed in the article. The functions camera:lockX()
,
camera:lockY()
, camera:lockPosition()
, and camera:lockWindow()
move the camera so that the interesting content stays in frame.
Note that the functions must be called every frame:
function love.update()
-- vertical locking
camera:lockX(player.pos.x)
end
All movements are subject to smoothing (see Movement Smoothers).
You can specify a default movement smoother by assigning the variable
camera.smoother
:
cam.smoother = Camera.smooth.linear(100)
-
camera:lockX
(x, smoother, ...)¶ Arguments: - x (number) – X coordinate (in world coordinates) to lock to.
- smoother (function) – Movement smoothing override. (optional)
- ... (mixed) – Additional parameters to the smoothing function. (optional)
Horizontal camera locking: Keep the camera locked on the defined x
-position
(in world coordinates). The y
-position is not affected.
You can define an off-center locking position by “aiming” the camera left or right of your actual target. For example, to center the player 20 pixels to the left of the screen, aim 20 pixels to it’s right (see examples).
Examples:
-- lock on player vertically
camera:lockX(player.x)
-- ... with linear smoothing at 25 px/s
camera:lockX(player.x, Camera.smooth.linear(25))
-- lock player 20px left of center
camera:lockX(player.x + 20)
-
camera:lockY
(y, smoother, ...)¶ Arguments: - y (number) – Y coordinate (in world coordinates) to lock to.
- smoother (function) – Movement smoothing override. (optional)
- ... (mixed) – Additional parameters to the smoothing function. (optional)
Vertical camera locking: Keep the camera locked on the defined y
-position
(in world coordinates). The x
-position is not affected.
You can define an off-center locking position by “aiming” the camera above or below your actual target. For example, to center the player 20 pixels below the screen center, aim 20 pixels above it (see examples).
Examples:
-- lock on player horizontally
camera:lockY(player.y)
-- ... with damped smoothing with a stiffness of 10
camera:lockY(player.y, Camera.smooth.damped(10))
-- lock player 20px below the screen center
camera:lockY(player.y - 20)
-
camera:lockPosition
(x, y, smoother, ...)¶ Arguments: - x,y (numbers) – Position (in world coordinates) to lock to.
- smoother (function) – Movement smoothing override. (optional)
- ... (mixed) – Additional parameters to the smoothing function. (optional)
Horizontal and vertical camera locking: Keep the camera locked on the defined position (in world coordinates).
You can define an off-center locking position by “aiming” the camera to the opposite direction away from your real target. For example, to center the player 10 pixels to the left and 20 pixels above the screen center, aim 10 pixels to the right and 20 pixels below.
Examples:
-- lock on player
camera:lockPosition(player.x, player.y)
-- lock 50 pixels into player's aiming direction
camera:lockPosition(player.x - player.aiming.x * 50, player.y - player.aiming.y * 50)
-
camera:lockWindow
(x, y, x_min, x_max, y_min, y_max, smoother, ...)¶ Arguments: - x,y (numbers) – Position (in world coordinates) to lock to.
- x_min (numbers) – Upper left X coordinate of the camera window (in camera coordinates!).
- x_max (numbers) – Lower right X coordinate of the camera window (in camera coordinates!).
- y_min (numbers) – Upper left Y coordinate of the camera window (in camera coordinates!).
- y_max (numbers) – Lower right Y coordinate of the camera window (in camera coordinates!).
- smoother (function) – Movement smoothing override. (optional)
- ... (mixed) – Additional parameters to the smoothing function. (optional)
The most powerful locking method: Lock camera to x,y
, but only move the
camera if the position would be out of the screen-rectangle defined by x_min
,
x_max
, y_min
, y_max
.
Note
The locking window is defined in camera coordinates, whereas the position to lock to is defined in world coordinates!
All of the other locking methods can be implemented by window locking. For
position locking, set x_min = x_max
and y_min = y_max
.
Off-center locking can be done by defining the locking window accordingly.
Examples:
-- lock on player
camera:lock(player.x, player.y)
-
camera.
smoother
¶
The default smoothing operator. Must be a function
with the following
prototype:
function customSmoother(dx,dy, ...)
do_stuff()
return new_dx,new_dy
end
where dx,dy
is the offset the camera would move before smoothing and
new_dx, new_dy
is the offset the camera should move after smoothing.
Movement Smoothers¶
It is not always desirable that the camera instantly locks on a target. Platform snapping, for example, would look terrible if the camera would instantly jump to the focussed platform. Smoothly moving the camera to the locked position can also give the illusion of a camera operator an add to the overall feel of your game.
hump.camera allows to smooth the movement by either passing movement
smoother functions to the locking functions or by setting a default smoother
(see camera.smoother
).
Smoothing functions must have the following prototype:
function customSmoother(dx,dy, ...)
do_stuff()
return new_dx,new_dy
end
where dx,dy
is the offset the camera would move before smoothing and
new_dx, new_dy
is the offset the camera should move after smoothing.
This is a simple “rubber-band” smoother:
function rubber_band(dx,dy)
local dt = love.timer.getDelta()
return dx*dt, dy*dt
end
hump.camera defines generators for the most common smoothers:
-
Camera.smooth.
none
()¶ Returns: Smoothing function.
Dummy smoother: does not smooth the motion.
Example:
cam.smoother = Camera.smooth.none()
-
Camera.smooth.
linear
(speed)¶ Arguments: - speed (number) – Smoothing speed.
Returns: Smoothing function.
Smoothly moves the camera towards to snapping goal with constant speed.
Examples:
cam.smoother = Camera.smooth.linear(100)
-- warning: creates a function every frame!
camera:lockX(player.x, Camera.smooth.linear(25))
-
Camera.smooth.
damped
(stiffness)¶ Arguments: - stiffness (number) – Speed of the camera movement.
Returns: Smoothing function.
Smoothly moves the camera towards the goal with a speed proportional to the distance to the target. Stiffness defines the speed of the motion: Higher values mean that the camera moves more quickly.
Examples:
cam.smoother = Camera.smooth.damped(10)
-- warning: creates a function every frame!
camera:lockPosition(player.x, player.y, Camera.smooth.damped(2))