2011-11-16 13:57:43 +00:00
Module { name = " hump.gamestate " ,
title = " Gamestate " ,
short = " A gamestate system " ,
long = [ === [
A gamestate encapsulates independent data an behaviour into a single entity .
2012-04-13 18:05:12 +00:00
A typical game could consist of a { * menu - state } , a { * level - state } and a { * game - over - state } . ] === ] ,
2011-11-16 13:57:43 +00:00
Section { name = " callbacks " ,
title = " Gamestate Callbacks " ,
content = [ === [
2012-04-13 18:05:12 +00:00
A gamestate can define ( nearly ) all callbacks that L & Ouml ; VE defines . In addition ,
2011-11-16 13:57:43 +00:00
there are callbacks for entering and leaving a state . :
[ |
2012-04-13 18:05:12 +00:00
{ # init ( ) } : Called once before entering the state . See { # switch ( ) } .
{ # enter ( previous , ... ) } : Called when entering the state . See { # switch ( ) } .
{ # leave ( ) } : Called when leaving a state . See { # switch ( ) } .
{ # update ( ) } : Update the game state . Called every frame .
{ # draw ( ) } : Draw on the screen . Called every frame .
{ # focus ( ) } : Called if the window gets or looses focus .
{ # keypressed ( ) } : Triggered when a key is pressed .
{ # keyreleased ( ) } : Triggered when a key is released .
{ # mousepressed ( ) } : Triggered when a mouse button is pressed .
{ # mousereleased ( ) } : Triggered when a mouse button is released .
{ # joystickpressed ( ) } : Triggered when a joystick button is pressed .
{ # joystickreleased ( ) } : Triggered when a joystick button is released .
{ # quit ( ) } : Called on quitting the game . Only called on the active gamestate .
]
When using { # registerEvents ( ) } , all these callbacks will receive the same
arguments as the [ ^ http : // love2d.org / wiki / love L & Ouml ; VE callbacks ] do . ] === ] ,
2011-11-16 13:57:43 +00:00
example = [ === [
menu = Gamestate.new ( )
function menu : init ( ) -- run only once
self.background = love.graphics . newImage ( ' bg.jpg ' )
Buttons.initialize ( )
end
function menu : enter ( previous ) -- run every time the state is entered
Buttons.setActive ( Buttons.start )
end
function menu : update ( dt )
Buttons.update ( dt )
end
function menu : draw ( )
love.graphics . draw ( self.background , 0 , 0 )
Buttons.draw ( )
end
function menu : keyreleased ( key )
if key == ' up ' then
Buttons.selectPrevious ( )
elseif key == ' down ' then
Buttons.selectNext ( )
elseif
Buttons.active : onClick ( )
end
end
function menu : mousereleased ( x , y , mouse_btn )
local button = Buttons.hovered ( x , y )
if button then
Button.select ( button )
if mouse_btn == ' l ' then
button : onClick ( )
end
end
end ] === ]
} ,
Function { name = " new " ,
short = " Create a new gamestate. " ,
2012-04-13 18:05:12 +00:00
long = " Declare a new gamestate. A gamestate can define several [^#{{MODULE}}-callbacks callbacks]. " ,
2011-11-16 13:57:43 +00:00
params = { } ,
returns = {
{ " Gamestate " , " The new gamestate. " }
} ,
example = " menu = Gamestate.new() " ,
} ,
Function { name = " switch " ,
short = " Switch to gamestate. " ,
long = [ === [
Switch to a gamestate , with any additional arguments passed to the new state .
2012-04-13 18:05:12 +00:00
Switching a gamestate will call the { # leave ( ) } callback on the current gamestate ,
replace the current gamestate with to , call the { # init ( ) } function if the state
was not yet inialized and finally call { # enter ( old_state , ... ) } on the new gamestate . ] === ] ,
2011-11-16 13:57:43 +00:00
params = {
{ " Gamestate " , " to " , " Target gamestate. " } ,
{ " mixed " , " ... " , " Additional arguments to pass to to:enter(). " }
} ,
returns = {
{ " mixed " , " The results of to:enter() " }
} ,
example = " Gamestate.switch(game, level_two) " ,
} ,
Function { name = {
" update " ,
" draw " ,
" focus " ,
" keypressed " ,
" keyreleased " ,
" mousepressed " ,
" mousereleased " ,
" joystickpressed " ,
" joystickreleased " ,
" quit " ,
} ,
short = {
" Update current gamestate. " ,
" Draw the current gamestate. " ,
" Inform current gamestate of a focus event. " ,
" Inform current gamestate of a keypressed event. " ,
" Inform current gamestate of a keyreleased event. " ,
" Inform current gamestate of a mousepressed event. " ,
" Inform current gamestate of a mousereleased event. " ,
" Inform current gamestate of a joystickpressed event. " ,
" Inform current gamestate of a joystickreleased event. " ,
" Inform current gamestate of a quit event. " ,
} ,
long = [ === [
2012-04-13 18:05:12 +00:00
Calls the corresponding function on the current gamestate ( see [ ^# { { MODULE } } - callbacks callbacks ] ) .
2011-11-16 13:57:43 +00:00
2012-04-13 19:57:31 +00:00
Only needed when not using { # registerEvents ( ) } . ] === ] ,
2011-11-16 13:57:43 +00:00
params = {
2012-04-13 18:05:12 +00:00
{ " mixed " , " ... " , " Arguments to pass to the corresponding [^#{{MODULE}}-callbacks callback]. " } ,
2011-11-16 13:57:43 +00:00
} ,
returns = {
{ " mixed " , " The results of the callback function. " } ,
} ,
example = [ === [
function love . update ( dt )
Gamestate.update ( dt )
end
function love . draw ( )
local mx , my = love.mouse . getPosition ( )
Gamestate.draw ( mx , my )
end
function love . keypressed ( key , code )
Gamestate.keypressed ( key , code )
end ] === ] ,
} ,
Function { name = " registerEvents " ,
short = " Automatically do all of the above when needed. " ,
long = [ === [
2012-04-13 19:57:31 +00:00
Register love callbacks to call { # Gamestate.update ( ) } , { # Gamestate.draw ( ) } , etc . automatically .
2011-11-16 13:57:43 +00:00
2012-01-12 16:36:23 +00:00
This is by done by overwriting the love callbacks , e.g . :
2012-04-13 19:25:06 +00:00
[ % local old_update = love.update
2011-11-16 13:57:43 +00:00
function love . update ( dt )
2012-01-12 16:36:23 +00:00
old_update ( dt )
2011-11-16 13:57:43 +00:00
Gamestate.current : update ( dt )
2012-04-13 19:25:06 +00:00
end ]
2012-01-12 16:36:23 +00:00
2012-04-13 18:05:12 +00:00
{ ! Note : } Only works when called in { # love.load ( ) } or any other function that is executed
2012-01-12 16:36:23 +00:00
after the whole file is loaded . ] === ] ,
2012-04-13 19:57:31 +00:00
params = {
{ ' table ' , ' callbacks ' , ' Names of the callbacks to register. If omitted, register all callbacks. ' , optional = true } ,
} ,
2011-11-16 13:57:43 +00:00
returns = { } ,
2012-04-13 19:57:31 +00:00
example = {
[ === [ function love . load ( )
2011-11-16 13:57:43 +00:00
Gamestate.registerEvents ( )
Gamestate.switch ( menu )
2012-04-13 19:57:31 +00:00
end ] === ] , [ === [ function love . load ( )
Gamestate.registerEvents { ' draw ' , ' update ' , ' quit ' }
Gamestate.switch ( menu )
end ] === ]
}
2011-11-16 13:57:43 +00:00
} ,
}
Module { name = " hump.timer " ,
title = " Timer " ,
short = " Delayed function calls and helpers for interpolating functions. " ,
long = [ === [
2012-05-16 11:38:20 +00:00
hump.timer provides a simple interface to use delayed functions , i.e .
functions that will be executed after some amount time has passed . For
example , you can use a timer to set the player invincible for a short
amount of time .
In addition , the module offers facilities to create functions that
interpolate or oscillate over time . An interpolator could fade the color or
a text message , whereas an oscillator could be used for the movement of
foes in a shmup . ] === ] ,
Function { name = " new " ,
short = " Create new timer instance. " ,
long = [ === [
2012-05-16 13:03:10 +00:00
{ ! If you don ' t need multiple independent schedulers, you can use the
global / default timer ( see examples ) . }
2012-05-16 11:38:20 +00:00
Creates a new timer instance that is independent of the global timer :
It will manage it ' s own list of scheduled functions and does not in any
way affect the the global timer . Likewise , the global timer does not
affect the timer instance .
2012-05-16 13:03:10 +00:00
{ ! Note : } Timer instances use the colon - notation ( e.g .
2012-05-16 11:38:20 +00:00
{ # instance : update ( dt ) } ) , while the global timer uses the dot - notation
( e.g . { # Timer.update ( dt ) } ) . ] === ] ,
params = { } ,
returns = {
{ " Timer " , " A timer instance " }
} ,
example = " menuTimer = Timer.new() " ,
} ,
2011-11-16 13:57:43 +00:00
2012-05-16 11:38:20 +00:00
Function { name = { " add " , " instance:add " } ,
short = " Schedule a function. " ,
2011-11-16 13:57:43 +00:00
long = [ === [
2012-05-16 11:38:20 +00:00
Schedule a function . The function will be executed after { # delay }
seconds have elapsed , given that { # update ( dt ) } is called every frame .
2011-11-16 13:57:43 +00:00
2012-05-16 11:38:20 +00:00
Note that there is no guarantee that the delay will not be exceeded , it
is only guaranteed that the function will not be executed { * before } the
delay has passed .
2011-11-16 13:57:43 +00:00
2012-05-16 11:38:20 +00:00
It is an error to schedule a function again if it is not yet finished
or canceled .
2012-03-31 12:56:26 +00:00
2012-05-16 11:38:20 +00:00
{ # func } will receive itself as only parameter . This is useful to
implement periodic behavior ( see the example ) . ] === ] ,
2011-11-16 13:57:43 +00:00
params = {
{ " number " , " delay " , " Number of seconds the function will be delayed. " } ,
{ " function " , " func " , " The function to be delayed. " } ,
} ,
2012-03-31 12:56:26 +00:00
returns = {
2012-10-02 16:41:43 +00:00
{ " table " , " The timer handle. " }
2012-03-31 12:56:26 +00:00
} ,
2011-11-16 13:57:43 +00:00
example = {
[ === [
-- grant the player 5 seconds of immortality
player.isInvincible = true
Timer.add ( 5 , function ( ) player.isInvincible = false end ) ] === ] ,
[ === [
-- print "foo" every second. See addPeriodic.
2012-05-16 11:38:20 +00:00
Timer.add ( 1 , function ( func ) print ( " foo " ) Timer.add ( 1 , func ) end ) ] === ] ,
[===[menuTimer:add(1, finishAnimation)]===]
2011-11-16 13:57:43 +00:00
} ,
} ,
2012-05-16 11:38:20 +00:00
Function { name = { " addPeriodic " , " instance:addPeriodic " } ,
2011-11-16 13:57:43 +00:00
short = " Add a periodic function. " ,
long = [ === [
2012-05-16 11:38:20 +00:00
Add a function that will be called { # count } times every { # delay }
seconds .
2011-11-16 13:57:43 +00:00
2012-05-16 11:38:20 +00:00
If { # count } is omitted , the function will be called until it returns
{ # false } or { # clear ( ) } is called . ] === ] ,
2011-11-16 13:57:43 +00:00
params = {
{ " number " , " delay " , " Number of seconds between two consecutive function calls. " } ,
{ " function " , " func " , " The function to be called periodically. " } ,
{ " number " , " count " , " Number of times the function is to be called. " , optional = true } ,
} ,
2012-03-31 12:56:26 +00:00
returns = {
2012-10-02 16:41:43 +00:00
{ " table " , " The timer handle. " }
2012-03-31 12:56:26 +00:00
} ,
2011-11-16 13:57:43 +00:00
example = {
" Timer.addPeriodic(1, function() lamp:toggleLight() end) " ,
2012-05-16 11:38:20 +00:00
" mothership_timer:addPeriodic(0.3, function() self:spawnFighter() end, 5) " ,
2011-11-16 13:57:43 +00:00
[ === [ -- flicker player's image as long as he is invincible
Timer.addPeriodic ( 0.1 , function ( )
player : flipImage ( )
return player.isInvincible
end ) ] === ] ,
} ,
} ,
2012-10-02 16:41:43 +00:00
Function { name = { " do_for " , " instance:do_for " } ,
short = " Run a function for the next few seconds. " ,
long = [ === [
Run a { # func ( dt ) } for the next { # delta } seconds . The function is called
every time { # update ( dt ) } is called . Optionally run { # after ( ) } once
{ # delta } seconds have passed .
{ # after } will receive itself as only parameter .
The same constraints as with { # add ( ) } apply . ] === ] ,
params = {
{ " number " , " delta " , " Number of seconds the {#func} will be called. " } ,
{ " function " , " func " , " The function to be called upon {#update(dt)}. " } ,
{ " function " , " after " , " A function to be called after {#delta} seconds. " , optional = true } ,
} ,
returns = {
{ " table " , " The timer handle. " }
} ,
example = {
2012-10-07 11:37:50 +00:00
[ === [ -- play an animation for 5 seconds
Timer.do_for ( 5 , function ( dt ) animation : update ( dt ) end ) ] === ] ,
[ === [ -- shake the camera for one second
local orig_x , orig_y = camera : pos ( )
Timer.do_for ( 1 , function ( )
camera : lookAt ( orig_x + math.random ( - 2 , 2 ) , orig_y + math.random ( - 2 , 2 ) )
end , function ( )
-- reset camera position
camera : lookAt ( orig_x , orig_y )
end ) ] === ] ,
2012-10-02 16:41:43 +00:00
[ === [ player.isInvincible = true
-- flash player for 3 seconds
local t = 0
player.timer : do_for ( 3 , function ( dt )
t = t + dt
player.visible = ( t % .2 ) < .1
end , function ( )
2012-10-07 11:37:50 +00:00
-- make sure the player is visible after three seconds
player.visible = true
2012-10-02 16:41:43 +00:00
player.isInvincible = false
end ) ] === ]
} ,
} ,
2012-05-16 11:38:20 +00:00
Function { name = { " cancel " , " instance:cancel " } ,
2012-03-31 12:56:26 +00:00
short = " Cancel a scheduled function. " ,
2012-05-16 11:38:20 +00:00
long = [ === [
Prevent a timer from being executed in the future .
2012-03-31 12:56:26 +00:00
2012-05-16 11:38:20 +00:00
{ * Always } use the function handle returned by { # add ( ) } / { # addPeriodic ( ) }
to cancel a timer .
2012-03-31 12:56:26 +00:00
2012-05-16 11:38:20 +00:00
{ * Never } use this inside a scheduled function . ] = = = ] ,
2012-03-31 12:56:26 +00:00
params = {
2012-10-02 16:41:43 +00:00
{ " table " , " handle " , " The function to be canceled. " } ,
2012-03-31 12:56:26 +00:00
} ,
returns = { } ,
example = {
[ === [ function tick ( )
print ( ' tick... tock... ' )
end
handle = Timer.addPeriodic ( 1 , tick )
-- later
Timer.cancel ( handle ) -- NOT: Timer.cancel(tick)]===]
} ,
} ,
2012-05-16 11:38:20 +00:00
Function { name = { " clear " , " instance:clear " } ,
2011-11-16 13:57:43 +00:00
short = " Remove all timed and periodic functions. " ,
2012-05-16 11:38:20 +00:00
long = [ === [
Remove all timed and periodic functions . Functions that have not yet
been executed will discarded .
{ * Never } use this inside a scheduled function . ] = = = ] ,
2011-11-16 13:57:43 +00:00
params = { } ,
returns = { } ,
2012-03-31 12:56:26 +00:00
example = " Timer.clear() " ,
2011-11-16 13:57:43 +00:00
} ,
2012-05-16 11:38:20 +00:00
Function { name = { " update " , " instance:update " } ,
short = " Update scheduled functions. " ,
2012-04-13 19:57:31 +00:00
long = " Update timers and execute functions if the deadline is reached. Use this in {#love.update(dt)}. " ,
2011-11-16 13:57:43 +00:00
params = {
{ " number " , " dt " , " Time that has passed since the last update(). " } ,
} ,
returns = { } ,
example = [ === [
function love . update ( dt )
do_stuff ( )
Timer.update ( dt )
end ] === ] ,
} ,
}
Module { name = " hump.vector " ,
title = " vector " ,
2012-04-13 18:05:12 +00:00
short = " 2D vector math. " ,
2011-11-16 13:57:43 +00:00
long = [ === [
A handy 2 D vector class providing most of the things you do with vectors .
2012-04-13 18:05:12 +00:00
You can access the individual coordinates by using { # vec.x } and { # vec.y } . ] === ] ,
2011-11-16 13:57:43 +00:00
Section { name = " operators " ,
title = " Arithmetics and relations " ,
content = [ === [
2012-04-13 18:05:12 +00:00
Vector arithmetic is implemented by using { # __add } , { # __mul } and other metamethods :
2011-11-16 13:57:43 +00:00
[ |
2012-04-13 18:05:12 +00:00
{ # vector + vector = vector } : Component wise sum .
{ # vector - vector = vector } : Component wise difference .
2012-04-13 19:25:06 +00:00
{ # vector * vector = number } : Dot product .
{ # number * vector = vector } : Scalar multiplication ( scaling ) .
{ # vector * number = vector } : Scalar multiplication .
{ # vector / number = vector } : Scalar multiplication .
2012-04-13 18:05:12 +00:00
]
2011-11-16 13:57:43 +00:00
Relational operators are defined , too :
[ |
2012-04-13 18:05:12 +00:00
a == b : { # true } , if { # a.x == b.x } and { # a.y == b.y } .
a <= b : { # true } , if { # a.x <= b.x } and { # a.y <= b.y } .
a < b : Lexical sort : { # true } , if { # a.x < b.x } or { # a.x == b.x } and { # a.y < b.y } .
] ] === ] ,
2011-11-16 13:57:43 +00:00
example = [ === [
-- acceleration, player.velocity and player.position are vectors
acceleration = vector ( 0 , - 9 )
player.velocity = player.velocity + acceleration * dt
player.position = player.position + player.velocity * dt ] === ] ,
} ,
Function { name = " new " ,
short = " Create a new vector. " ,
long = " Create a new vector. " ,
params = {
{ " numbers " , " x,y " , " Coordinates. " }
} ,
returns = {
{ " vector " , " The vector. " }
} ,
example = {
" a = vector.new(10,10) " ,
[ === [ -- as a shortcut, you can call the module like a function:
vector = require " hump.vector "
a = vector ( 10 , 10 ) ] === ] ,
} ,
} ,
Function { name = " isvector " ,
short = " Test if value is a vector. " ,
long = " Test whether a variable is a vector. " ,
params = {
{ " mixed " , " v " , " The variable to test. " }
} ,
returns = {
2012-04-13 18:05:12 +00:00
{ " boolean " , " {#true} if {#v} is a vector, {#false} otherwise " }
2011-11-16 13:57:43 +00:00
} ,
example = [ === [
if not vector.isvector ( v ) then
v = vector ( v , 0 )
end ] === ] ,
} ,
Function { name = " vector:clone " ,
short = " Copy a vector. " ,
long = [ === [
Copy a vector . Simply assigning a vector a vector to a variable will create
a reference , so when modifying the vector referenced by the new variable
would also change the old one :
2012-04-13 19:25:06 +00:00
[ % a = vector ( 1 , 1 ) -- create vector
2011-11-16 13:57:43 +00:00
b = a -- b references a
c = a : clone ( ) -- c is a copy of a
b.x = 0 -- changes a,b and c
2012-04-13 19:25:06 +00:00
print ( a , b , c ) -- prints '(1,0), (1,0), (1,1)']]===],
2011-11-16 13:57:43 +00:00
params = { } ,
returns = {
{ " vector " , " Copy of the vector " }
} ,
example = " copy = original:clone " ,
} ,
Function { name = " vector:unpack " ,
short = " Extract coordinates. " ,
long = " Extract coordinates. " ,
params = { } ,
returns = {
{ " numbers " , " The coordinates " }
} ,
example = {
2012-01-20 14:55:40 +00:00
" x,y = pos:unpack() " ,
2011-11-16 13:57:43 +00:00
" love.graphics.draw(self.image, self.pos:unpack()) "
} ,
} ,
Function { name = " vector:permul " ,
short = " Per element multiplication. " ,
long = [ === [
2012-04-13 18:05:12 +00:00
Multiplies vectors coordinate wise , i.e . { # result = vector ( a.x * b.x , a.y * b.y ) } .
2011-11-16 13:57:43 +00:00
This does not change either argument vectors , but creates a new one . ] === ] ,
params = {
{ " vector " , " other " , " The other vector " }
} ,
returns = {
{ " vector " , " The new vector as described above " }
} ,
example = " scaled = original:permul(vector(1,1.5)) " ,
} ,
Function { name = " vector:len " ,
short = " Get length. " ,
2012-04-13 18:05:12 +00:00
long = " Get length of a vector, i.e. {#math.sqrt(vec.x * vec.x + vec.y * vec.y)}. " ,
2011-11-16 13:57:43 +00:00
params = { } ,
returns = {
{ " number " , " Length of the vector. " }
} ,
example = " distance = (a - b):len() " ,
} ,
Function { name = " vector:len2 " ,
short = " Get squared length. " ,
2012-04-13 18:05:12 +00:00
long = " Get squared length of a vector, i.e. {#vec.x * vec.x + vec.y * vec.y}. " ,
2011-11-16 13:57:43 +00:00
params = { } ,
returns = {
{ " number " , " Squared length of the vector. " }
} ,
example = [ === [
-- get closest vertex to a given vector
closest , dsq = vertices [ 1 ] , ( pos - vertices [ 1 ] ) : len2 ( )
for i = 2 , # vertices do
local temp = ( pos - vertices [ i ] ) : len2 ( )
if temp < dsq then
closest , dsq = vertices [ i ] , temp
end
end ] === ] ,
} ,
Function { name = " vector:dist " ,
short = " Distance to other vector. " ,
2012-04-13 18:05:12 +00:00
long = " Get distance of two vectors. The same as {#(a - b):len()}. " ,
2011-11-16 13:57:43 +00:00
params = {
{ " vector " , " other " , " Other vector to measure the distance to. " } ,
} ,
returns = {
{ " number " , " The distance of the vectors. " }
} ,
example = [ === [
-- get closest vertex to a given vector
-- slightly slower than the example using len2()
closest , dist = vertices [ 1 ] , pos : dist ( vertices [ 1 ] )
for i = 2 , # vertices do
local temp = pos : dist ( vertices [ i ] )
if temp < dist then
closest , dist = vertices [ i ] , temp
end
end ] === ] ,
} ,
Function { name = " vector:normalized " ,
short = " Get normalized vector. " ,
long = [ === [
Get normalized vector , i.e . a vector with the same direction as the input
vector , but with length 1.
This does not change the input vector , but creates a new vector . ] === ] ,
params = { } ,
returns = {
{ " vector " , " Vector with same direction as the input vector, but length 1. " }
} ,
example = " direction = velocity:normalized() "
} ,
Function { name = " vector:normalize_inplace " ,
short = " Normalize vector in-place. " ,
long = [ === [
Normalize a vector , i.e . make the vector unit length . Great to use on
intermediate results .
2012-04-13 18:05:12 +00:00
{ ! This modifies the vector . If in doubt , use { # vector : normalized ( ) } . } ] === ] ,
2011-11-16 13:57:43 +00:00
params = { } ,
returns = {
{ " vector " , " Itself - the normalized vector " }
} ,
example = " normal = (b - a):perpendicular():normalize_inplace() "
} ,
Function { name = " vector:rotated " ,
short = " Get rotated vector. " ,
long = [ === [
Get a rotated vector .
This does not change the input vector , but creates a new vector . ] === ] ,
params = {
2012-04-13 18:05:12 +00:00
{ " number " , " phi " , " Rotation angle in [^http://en.wikipedia.org/wiki/Radians radians]. " }
2011-11-16 13:57:43 +00:00
} ,
returns = {
{ " vector " , " The rotated vector " }
} ,
example = [ === [
-- approximate a circle
circle = { }
for i = 1 , 30 do
local phi = 2 * math.pi * i / 30
circle [ # circle + 1 ] = vector ( 0 , 1 ) : rotated ( phi )
end ] === ] ,
sketch = {
" vector-rotated.png " , " sketch of rotated vectors " , width = 260 , height = 171
} ,
} ,
Function { name = " vector:rotate_inplace " ,
short = " Rotate vector in-place. " ,
long = [ === [
Rotate a vector in - place . Great to use on intermediate results .
2012-04-13 18:05:12 +00:00
{ ! This modifies the vector . If in doubt , use { # vector : rotate ( ) } } ] === ] ,
2011-11-16 13:57:43 +00:00
params = {
2012-04-13 18:05:12 +00:00
{ " number " , " phi " , " Rotation angle in [^http://en.wikipedia.org/wiki/Radians radians]. " }
2011-11-16 13:57:43 +00:00
} ,
returns = {
{ " vector " , " Itself - the rotated vector " }
} ,
example = [ === [
-- ongoing rotation
spawner.direction : rotate_inplace ( dt ) ] === ] ,
} ,
Function { name = " vector:perpendicular " ,
short = " Get perpendicular vector. " ,
long = [ === [
2012-04-13 19:57:31 +00:00
Quick rotation by 90 & deg ; . Creates a new vector . The same ( but faster ) as
{ # vec : rotate ( math.pi / 2 ) } ] === ] ,
2011-11-16 13:57:43 +00:00
params = { } ,
returns = {
{ " vector " , " A vector perpendicular to the input vector " }
} ,
example = " normal = (b - a):perpendicular():normalize_inplace() " ,
sketch = {
" vector-perpendicular.png " , " sketch of perpendicular vectors " , width = 267 , height = 202
} ,
} ,
Function { name = " vector:projectOn " ,
short = " Get projection onto another vector. " ,
long = " Project vector onto another vector (see sketch). " ,
params = {
{ " vector " , " v " , " The vector to project on. " }
} ,
returns = {
{ " vector " , " The projected vector. " }
} ,
example = " velocity_component = velocity:projectOn(axis) " ,
sketch = {
" vector-projectOn.png " , " sketch of vector projection " , width = 605 , height = 178
} ,
} ,
Function { name = " vector:mirrorOn " ,
short = " Mirrors vector on other vector " ,
2012-01-20 14:55:40 +00:00
long = " Mirrors vector on the axis defined by the other vector. " ,
2011-11-16 13:57:43 +00:00
params = {
{ " vector " , " v " , " The vector to mirror on. " }
} ,
returns = {
{ " vector " , " The mirrored vector. " }
} ,
2012-01-20 14:57:19 +00:00
example = " deflected_velocity = ball.velocity:mirrorOn(surface_normal) " ,
2012-01-20 14:55:40 +00:00
sketch = {
" vector-mirrorOn.png " , " sketch of vector mirroring on axis " , width = 334 , height = 201
} ,
2011-11-16 13:57:43 +00:00
} ,
Function { name = " vector:cross " ,
short = " Cross product of two vectors. " ,
long = [ === [
2012-01-20 14:55:40 +00:00
Get cross product of both vectors . Equals the area of the parallelogram
spanned by both vectors . ] === ] ,
2011-11-16 13:57:43 +00:00
params = {
{ " vector " , " other " , " Vector to compute the cross product with. " }
} ,
returns = {
{ " number " , " Cross product of both vectors. " }
} ,
2012-01-20 14:55:40 +00:00
example = " parallelogram_area = a:cross(b) " ,
sketch = {
" vector-cross.png " , " sketch of vector cross product " , width = 271 , height = 137
} ,
2011-11-16 13:57:43 +00:00
} ,
}
2012-04-13 18:05:12 +00:00
Module { name = " hump.vector-light " ,
title = " vector-light " ,
short = " Lightweight 2D vector math. " ,
long = [ === [
An table - free version of { # hump.vector } . Instead of a vector class , { # hump.vector - light } provides functions that operate on numbers .
Using this module instead of { # vector } might result in faster code , but does so at the expense of readability . Unless you are sure that it causes a significant performance penalty , I recommend to use { # hump.vector } . ] === ] ,
Function { name = " str " ,
short = " String representation. " ,
long = " Transforms a vector to a string of the form {#(x,y)}. " ,
params = {
{ " numbers " , " x,y " , " The vector " }
} ,
returns = {
{ " string " , " The string representation " }
} ,
example = {
" print(vector.str(love.mouse.getPosition())) " ,
}
} ,
Function { name = { " mul " , " div " } ,
short = {
" Product of a vector and a scalar. " ,
" Product of a vector and the inverse of a scalar. " ,
} ,
2012-04-13 19:57:31 +00:00
long = " Computes {#x*s,y*s} and {#x/s,y/s} respectively. The order of arguments is chosen so that it's possible to chain multiple operations (see example). " ,
2012-04-13 18:05:12 +00:00
params = {
{ " number " , " s " , " The scalar. " } ,
{ " numbers " , " x,y " , " The vector. " } ,
} ,
returns = {
{ " numbers " , " The result of the operation. " }
} ,
example = {
" velx,vely = vec.mul(dt, vec.add(velx,vely, accx,accy)) " ,
" x,y = vec.div(self.zoom, x-w/2, y-h/2) " ,
} ,
} ,
Function { name = { " add " , " sub " } ,
short = {
" Sum of two vectors. " ,
" Difference of two vectors. " ,
} ,
2012-04-13 19:57:31 +00:00
long = " Computes the sum/difference of vectors. Same as {#x1+x2,y1+y2} and {#x1-x2,y1-y2} respectively. Meant to be used in conjunction with other functions. " ,
2012-04-13 18:05:12 +00:00
params = {
{ " numbers " , " x1,y1 " , " First vector. " } ,
{ " numbers " , " x2,y2 " , " Second vector. " } ,
} ,
returns = {
{ " numbers " , " The result of the operation. " }
} ,
example = {
" player.x,player.y = vector.add(player.x,player.y, vector.mul(dt, dx,dy)) " ,
" dx,dy = vector.sub(400,300, love.mouse.getPosition()) " ,
} ,
} ,
Function { name = " permul " ,
short = " Per element multiplication. " ,
long = [ === [
2012-04-13 19:57:31 +00:00
Multiplies vectors coordinate wise , i.e . { # x1 * x2 , y1 * y2 } . ] === ] ,
2012-04-13 18:05:12 +00:00
params = {
{ " numbers " , " x1,y1 " , " First vector. " } ,
{ " numbers " , " x2,y2 " , " Second vector. " } ,
} ,
returns = {
{ " numbers " , " The result of the operation. " }
} ,
example = " x,y = vector.permul(x,y, 1,1.5) " ,
} ,
Function { name = " dot " ,
short = " [^http://en.wikipedia.org/wiki/Dot_product Dot product] " ,
2012-04-13 19:57:31 +00:00
long = " Computes the [^http://en.wikipedia.org/wiki/Dot_product dot product] of two vectors, {#x1*x2+y1*y2}. " ,
2012-04-13 18:05:12 +00:00
params = {
{ " numbers " , " x1,y1 " , " First vector. " } ,
{ " numbers " , " x2,y2 " , " Second vector. " } ,
} ,
returns = {
{ " number " , " The dot product. " }
} ,
example = " cosphi = vector.dot(rx,ry, vx,vy) "
} ,
Function { name = { " det " , " cross " } ,
short = { " Cross product " , " Cross product " , } ,
2012-04-13 19:57:31 +00:00
long = " Computes the cross product/determinant of two vectors, {#x1*y2-y1*x2}. " ,
2012-04-13 18:05:12 +00:00
params = {
{ " numbers " , " x1,y1 " , " First vector. " } ,
{ " numbers " , " x2,y2 " , " Second vector. " } ,
} ,
returns = {
{ " number " , " The cross product. " }
} ,
example = " parallelogram_area = vector.det(ax,ay, bx,by) "
} ,
Function { name = { " eq " , " le " , " lt " } ,
short = { " Equality. " , " Partial lexical order. " , " Strict lexical order. " } ,
long = [ === [ Compares two vectors according to [ |
{ # vector.eq ( x1 , y1 , x2 , y2 ) } : { # x1 == x2 and y1 == y2 }
{ # vector.le ( x1 , y1 , x2 , y2 ) } : { # x1 <= x2 and y1 <= y2 }
{ # vector.lt ( x1 , y1 , x2 , y2 ) } : { # x1 < x2 or ( x1 == x2 ) and y1 <= y2 }
]
] === ] ,
params = {
{ " numbers " , " x1,y1 " , " First vector. " } ,
{ " numbers " , " x2,y2 " , " Second vector. " } ,
} ,
returns = {
{ " boolean " , " The result of the operation. " }
} ,
example = " ... "
} ,
Function { name = " len " ,
short = " Get length. " ,
long = " Get length of a vector, i.e. {#math.sqrt(x*x + y*y)}. " ,
params = {
{ " numbers " , " x,y " , " The vector. " }
} ,
returns = {
{ " number " , " Length of the vector. " }
} ,
example = " distance = vector.len(love.mouse.getPosition()) " ,
} ,
Function { name = " len2 " ,
short = " Get squared length. " ,
long = " Get squared length of a vector, i.e. {#x*x + y*y}. " ,
params = {
{ " numbers " , " x,y " , " The vector. " }
} ,
returns = {
{ " number " , " Squared length of the vector. " }
} ,
example = [ === [
-- get closest vertex to a given vector
closest , dsq = vertices [ 1 ] , vector.len2 ( px - vertices [ 1 ] . x , py - vertices [ 1 ] . y )
for i = 2 , # vertices do
local temp = vector.len2 ( px - vertices [ i ] . x , py - vertices [ i ] . y )
if temp < dsq then
closest , dsq = vertices [ i ] , temp
end
end ] === ] ,
} ,
Function { name = " dist " ,
short = " Distance of two points. " ,
long = " Get distance of two points. The same as {#vector.len(x1-x2, y1-y2)}. " ,
params = {
{ " numbers " , " x1,y1 " , " First vector. " } ,
{ " numbers " , " x2,y2 " , " Second vector. " } ,
} ,
returns = {
{ " number " , " The distance of the points. " }
} ,
example = [ === [
-- get closest vertex to a given vector
-- slightly slower than the example using len2()
closest , dist = vertices [ 1 ] , vector.dist ( px , py , vertices [ 1 ] . x , vertices [ 1 ] . y )
for i = 2 , # vertices do
local temp = vector.dist ( px , py , vertices [ i ] . x , vertices [ i ] . y )
if temp < dist then
closest , dist = vertices [ i ] , temp
end
end ] === ] ,
} ,
Function { name = " normalize " ,
short = " Normalize vector. " ,
long = [ === [
Get normalized vector , i.e . a vector with the same direction as the input
vector , but with length 1. ] === ] ,
params = {
{ " numbers " , " x,y " , " The vector. " } ,
} ,
returns = {
{ " numbers " , " Vector with same direction as the input vector, but length 1. " }
} ,
example = " dx,dy = vector.normalize(vx,vy) "
} ,
Function { name = " rotate " ,
short = " Rotate vector. " ,
long = " Get a rotated vector. " ,
params = {
{ " number " , " phi " , " Rotation angle in [^http://en.wikipedia.org/wiki/Radians radians]. " } ,
{ " numbers " , " x,y " , " The vector. " } ,
} ,
returns = {
{ " numbers " , " The rotated vector " }
} ,
example = [ === [
-- approximate a circle
circle = { }
for i = 1 , 30 do
local phi = 2 * math.pi * i / 30
circle [ i * 2 - 1 ] , circle [ i * 2 ] = vector.rotate ( phi , 0 , 1 )
end ] === ] ,
} ,
Function { name = " perpendicular " ,
short = " Get perpendicular vector. " ,
2012-04-13 19:57:31 +00:00
long = " Quick rotation by 90°. The same (but faster) as {#vector.rotate(math.pi/2, x,y)} " ,
2012-04-13 18:05:12 +00:00
params = {
{ " numbers " , " x,y " , " The vector. " } ,
} ,
returns = {
{ " numbers " , " A vector perpendicular to the input vector " }
} ,
example = " nx,ny = vector.normalize(vector.perpendicular(bx-ax, by-ay)) " ,
} ,
Function { name = " project " ,
short = " Project projection onto another vector. " ,
long = " Project vector onto another vector. " ,
params = {
{ " numbers " , " x,y " , " The vector to project. " } ,
{ " numbers " , " u,v " , " The vector to project onto. " } ,
} ,
returns = {
{ " numbers " , " The projected vector. " }
} ,
example = " vx_p,vy_p = vector.project(vx,vy, ax,ay) " ,
} ,
Function { name = " mirror " ,
short = " Mirrors vector on other vector. " ,
long = " Mirrors vector on the axis defined by the other vector. " ,
params = {
{ " numbers " , " x,y " , " The vector to mirror. " } ,
{ " numbers " , " u,v " , " The vector defining the axis. " } ,
} ,
returns = {
{ " numbers " , " The mirrored vector. " }
} ,
example = " vx,vy = vector.mirror(vx,vy, surface.x,surface.y) " ,
} ,
}
2011-11-16 13:57:43 +00:00
Module { name = " hump.class " ,
title = " Class " ,
short = " Class-based object orientated programming for Lua " ,
long = " A small, fast class implementation with multiple inheritance support " ,
Function { name = " new " ,
short = " Declare a new class. " ,
long = [ === [
Declare a new class .
The constructor will receive the newly create object as first argument .
2012-04-13 18:05:12 +00:00
You can check if an object is an instance of a class using { # object : is_a ( ) } .
2011-11-16 13:57:43 +00:00
The name of the variable that holds the module can be used as a shortcut to
2012-04-13 18:05:12 +00:00
{ # new ( ) } ( see example ) . ] === ] ,
2011-11-16 13:57:43 +00:00
params = { table_argument = true ,
2012-04-13 18:05:12 +00:00
{ " function " , " constructor " , " Class constructor. Can be accessed with {#theclass.construct(object, ...)} " , optional = true } ,
{ " string " , " the_name " , " Class name (used only to make the class compliant to {#tostring()}. " , name = " name " , optional = true } ,
2011-11-16 13:57:43 +00:00
{ " class or table of classes " , " super " , " Classes to inherit from. Can either be a single class or a table of classes " , name = " inherits " , optional = true } ,
} ,
returns = {
{ " class " , " The class " }
} ,
example = {
[ === [
Class = require ' hump.class ' -- `Class' is now a shortcut to new()
2012-04-13 19:57:31 +00:00
-- define unnamed class
2011-11-16 13:57:43 +00:00
Feline = Class { function ( self , size , weight )
self.size = size
self.weight = weight
end }
2012-04-13 19:57:31 +00:00
print ( Feline ) -- prints '<unnamed class>
2011-11-16 13:57:43 +00:00
-- define class method
function Feline : stats ( )
return string.format ( " size: %.02f, weight %.02f " , self.size , self.weight )
end
-- create two objects
garfield = Feline ( .7 , 45 )
felix = Feline ( .8 , 12 )
print ( " Garfield: " .. garfield : stats ( ) , " Felix: " .. felix : stats ( ) )
] === ] ,
[ === [
Class = require ' hump.class '
-- define class with explicit name 'Feline'
Feline = Class { name = " Feline " , function ( self , size , weight )
self.size = size
self.weight = weight
end }
garfield = Feline ( .7 , 45 )
2012-04-13 19:57:31 +00:00
print ( Feline , garfield ) -- prints '<unnamed class> <instance of <unnamed class>>'
2011-11-16 13:57:43 +00:00
] === ] ,
[ === [
Class = require ' hump.class '
A = Class { }
function A : foo ( )
print ( ' foo ' )
end
B = Class { }
function B : bar ( )
print ( ' bar ' )
end
-- single inheritance
C = Class { inherits = A }
instance = C ( )
instance : foo ( ) -- prints 'foo'
-- multiple inheritance
D = Class { inherits = { A , B } }
instance = D ( )
instance : foo ( ) -- prints 'foo'
instance : bar ( ) -- prints 'bar'
] === ] ,
} ,
} ,
Function { name = " class.construct " ,
short = " Call class constructor. " ,
long = [ === [
Calls class constructor of a class on an object
Derived classes use this function their constructors to initialize the
parent class ( es ) portions of the object . ] === ] ,
params = {
2012-04-13 18:05:12 +00:00
{ " Object " , " object " , " The object. Usually {#self}. " } ,
2011-11-16 13:57:43 +00:00
{ " mixed " , " ... " , " Arguments to pass to the constructor " } ,
} ,
returns = {
{ " mixed " , " Whatever the parent class constructor returns " } ,
} ,
example = {
[ === [
Class = require ' hump.class '
Shape = Class { function ( self , area )
self.area = area
end }
function Shape : __tostring ( )
return " area = " .. self.area
end
Rectangle = Class { inherits = Shape , function ( self , width , height )
Shape.construct ( self , width * height )
self.width = width
self.height = height
end }
function Rectangle : __tostring ( )
local strs = {
" width = " .. self.width ,
" height = " .. self.height ,
Shape.__tostring ( self )
} ,
return table.concat ( strs , " , " )
end
print ( Rectangle ( 2 , 4 ) ) -- prints 'width = 2, height = 4, area = 8'
] === ] ,
[ === [
Menu = Class { function ( self )
self.entries = { }
end }
function Menu : add ( title , entry )
self.entries [ # self.entries + 1 ] = entry
end
function Menu : display ( )
-- ...
end
Entry = Class { function ( self , title , command )
self.title = title
self.command = command
end }
function Entry : execute ( )
return self.command ( )
end
Submenu = Class { inherits = { Menu , Entry } , function ( self , title )
Menu.construct ( self )
-- redirect self:execute() to self:display()
Entry.construct ( self , title , Menu.display )
end }
] === ]
} ,
} ,
Function { name = " class:inherit " ,
short = " Explicit class inheritance/mixin support. " ,
long = [ === [
Inherit functions and variables of another class , if they are not already
defined for the class . This is done by simply copying the functions and
variables over to the subclass . The Lua rules for copying apply
( i.e . tables are referenced , functions and primitive types are copied by value ) .
2012-04-13 18:05:12 +00:00
{ ! Be careful with changing table values in a subclass : This will change the
2011-11-16 13:57:43 +00:00
value in the parent class too . }
If more than one parent class is specified , inherit from all of these , in
order of occurrence . That means that when two parent classes define the same
method , the one from the first class will be inherited .
2012-04-13 18:05:12 +00:00
Note : { # class : inherit ( ) } doesn ' t actually care if the arguments supplied are
2011-11-16 13:57:43 +00:00
hump classes . Just any table will work . ] === ] ,
params = {
{ " tables " , " ... " , " Parent classes to inherit from " }
} ,
returns = { } ,
example = [ === [
Class = require ' hump.class '
Entity = Class { function ( self )
GameObjects.register ( self )
end }
Collidable = {
dispatch_collision = function ( self , other , dx , dy )
if self.collision_handler [ other.type ] )
return collision_handler [ other.type ] ( self , other , dx , dy )
end
return collision_handler [ " * " ] ( self , other , dx , dy )
end ,
collision_handler = { [ " * " ] = function ( ) end } ,
}
Spaceship = Class { function ( self )
self.type = " Spaceship "
-- ...
end }
-- make Spaceship collidable
Spaceship : inherit ( Collidable )
function Spaceship : collision_handler [ " Spaceship " ] ( other , dx , dy )
-- ...
end
] === ]
} ,
Function { name = " object:is_a " ,
short = " Test object's type. " ,
long = " Tests whether an object is an instance of a class. " ,
params = {
2012-04-13 18:05:12 +00:00
{ " class " , " cls " , " Class to test. Note: this is the class itself, {*not} the name of the class. " }
2011-11-16 13:57:43 +00:00
} ,
returns = {
2012-04-13 18:05:12 +00:00
{ " Boolean " , " {#true} if the object is an instance of the class, {#false} otherwise " }
2011-11-16 13:57:43 +00:00
} ,
example = [ === [
Class = require ' hump.class '
A = Class { }
B = Class { inherits = A }
C = Class { inherits = B }
a , b , c = A ( ) , B ( ) , C ( )
print ( a : is_a ( A ) , a : is_a ( B ) , a : is_a ( C ) ) --> true false false
print ( b : is_a ( A ) , b : is_a ( B ) , b : is_a ( C ) ) --> true true false
print ( c : is_a ( A ) , c : is_a ( B ) , c : is_a ( C ) ) --> true true true
D = Class { }
E = Class { inherits = { B , D } }
d , e = D ( ) , E ( )
print ( d : is_a ( A ) , d : is_a ( B ) , d : is_a ( D ) ) --> false false true
print ( e : is_a ( A ) , e : is_a ( B ) , e : is_a ( D ) ) --> true true true
] === ]
} ,
Section { name = " caveats " ,
title = " Caveats " ,
content = [ === [
2012-04-13 18:05:12 +00:00
Be careful when using metamethods like { # __add } or { # __mul } : If subclass
2011-11-16 13:57:43 +00:00
inherits those methods from a superclass , but does not overwrite them , the
result of the operation may be of the type superclass . Consider the following :
2012-04-13 19:25:06 +00:00
[ % Class = require ' hump.class '
2011-11-16 13:57:43 +00:00
A = Class { function ( self , x ) self.x = x end }
function A : __add ( other ) return A ( self.x + other.x ) end
function A : show ( ) print ( " A: " , self.x ) end
B = Class { inherits = A , function ( self , x , y ) A.construct ( self , x ) self.y = y end }
function B : show ( ) print ( " B: " , self.x , self.y ) end
function B : foo ( ) print ( " foo " ) end
one , two = B ( 1 , 2 ) , B ( 3 , 4 )
result = one + two
result : show ( ) -- prints "A: 4"
2012-04-13 19:25:06 +00:00
result : foo ( ) -- error: method does not exist]
2011-11-16 13:57:43 +00:00
2012-04-13 18:05:12 +00:00
Note that while you can define the { # __index } metamethod of the class , this
2012-04-13 19:57:31 +00:00
is not a good idea : It will break the class . To add a custom { # __index }
metamethod without breaking the class system , you have to use { # rawget ( ) } .
2011-11-16 13:57:43 +00:00
But beware that this won ' t affect subclasses:
2012-04-13 19:25:06 +00:00
[ % Class = require ' hump.class '
2011-11-16 13:57:43 +00:00
A = Class { }
function A : foo ( ) print ( ' bar ' ) end
function A : __index ( key )
print ( key )
return rawget ( A , key )
end
instance = A ( )
instance : foo ( ) -- prints foo <newline> bar
B = Class { inherits = A }
instance = B ( )
2012-04-13 19:25:06 +00:00
instance : foo ( ) -- prints only foo]]===],
2011-11-16 13:57:43 +00:00
} ,
}
2012-05-16 13:03:10 +00:00
Module { name = " hump.signal " ,
title = " Signal " ,
short = " Simple Signal/Slot (aka. Observer) implementation. " ,
long = [ === [
A simple yet effective implementation of
[ ^ http : // en.wikipedia . org / wiki / Signals_and_slots Signals and Slots ] , also
known as [ ^ http : // en.wikipedia . org / wiki / Observer_pattern Observer pattern ] :
Functions can be dynamically bound to { * signals } . When a signal is
{ * emitted } , all registered functions will be invoked . Simple as that .
{ # hump.signal } makes things more interesing by allowing to emit all signals
that match a [ ^ http : // www.lua . org / manual / 5.1 / manual.html # 5.4 .1 Lua string
pattern ] . ] === ] ,
Function { name = " new " ,
short = " Create new signal registry. " ,
long = [ === [
{ ! If you don ' t need multiple independent registries, you can use the
global / default registry ( see examples ) . }
Creates a new signal registry that is independent of the default
registry : It will manage it ' s own list of signals and does not in any
way affect the the global registry . Likewise , the global registry does
not affect the instance .
{ ! Note : } Independent registries use the colon - notation ( e.g .
{ # instance : emit ( " foo " ) } ) , while the global registry uses the
dot - notation ( e.g . { # Signal.emit ( " foo " ) } ) . ] === ] ,
params = { } ,
returns = {
{ " Registry " , " A new signal registry. " } ,
} ,
example = " player.signals = Signals.new() "
} ,
Function { name = { " register " , " instance:register " } ,
short = " Register function with a signal. " ,
long = [ === [
Registers a function { # f } to be called when signal { # s } is emitted .
] === ] ,
params = {
{ " string " , " s " , " The signal identifier. " } ,
{ " function " , " f " , " The function to register. " }
} ,
returns = {
{ " function " , " A function handle to use in {#remove}. " }
} ,
example = {
" Signal.register('level-complete', function() self.fanfare:play() end) " ,
" handle = Signal.register('level-load', function(level) level.show_help() end) " ,
" menu:register('key-left', select_previous_item) "
}
} ,
Function { name = { " emit " , " instance:emit " } ,
short = " Call all functions bound to a signal. " ,
long = [ === [
Calls all functions bound to signal { # s } with the supplied arguments .
] === ] ,
params = {
{ " string " , " s " , " The signal identifier. " } ,
{ " mixed " , " ... " , " Arguments to pass to the bound functions. " , optional = true } ,
} ,
returns = { } ,
example = {
[ === [ function love . keypressed ( key )
if key == ' left ' then menu : emit ( ' key-left ' ) end
end ] === ] ,
[ === [ if level.is_finished ( ) then
Signal.emit ( ' level-load ' , level.next_level )
end ] === ] ,
[ === [ function on_collide ( dt , a , b , dx , dy )
a.signals : emit ( ' collide ' , b , dx , dy )
b.signals : emit ( ' collide ' , a , - dx , - dy )
end ] === ]
}
} ,
Function { name = { " remove " , " instance:remove " } ,
short = " Remove functions from registry. " ,
long = [ === [
Unbinds ( removes ) functions from signal { # s } .
] === ] ,
params = {
{ " string " , " s " , " The signal identifier. " } ,
{ " functions " , " ... " , " Functions to unbind from the signal. " }
} ,
returns = { } ,
example = {
" Signal.remove('level-load', handle) " ,
}
} ,
Function { name = { " clear " , " instance:clear " } ,
short = " Clears a signal registry. " ,
long = [ === [
Removes all functions from signal { # s } .
] === ] ,
params = {
{ " string " , " s " , " The signal identifier. " } ,
} ,
returns = { } ,
example = " Signal.clear('key-left') " ,
} ,
Function { name = { " emit_pattern " , " instance:emit_pattern " } ,
short = " Emits signals matching a pattern. " ,
long = [ === [
Emits all signals matching a
[ ^ http : // www.lua . org / manual / 5.1 / manual.html # 5.4 .1 string pattern ] .
] === ] ,
params = {
{ " string " , " p " , " The signal identifier pattern. " } ,
{ " mixed " , " ... " , " Arguments to pass to the bound functions. " , optional = true } ,
} ,
returns = { } ,
example = " Signal.emit_pattern('^update%-.*', dt) " ,
} ,
Function { name = { " remove_pattern " , " instance:remove_pattern " } ,
short = " Remove functions from signals matching a pattern. " ,
long = [ === [
Removes functions from all signals matching a
[ ^ http : // www.lua . org / manual / 5.1 / manual.html # 5.4 .1 string pattern ] .
] === ] ,
params = {
{ " string " , " p " , " The signal identifier pattern. " } ,
{ " functions " , " ... " , " Functions to unbind from the signals. " }
} ,
returns = { } ,
example = " Signal.remove_pattern('key%-.*', play_click_sound) " ,
} ,
Function { name = { " clear_pattern " , " instance:clear_pattern " } ,
short = " Clears signal registry matching a pattern. " ,
long = [ === [
Removes all functions from all signals matching a
[ ^ http : // www.lua . org / manual / 5.1 / manual.html # 5.4 .1 string pattern ] .
] === ] ,
params = {
{ " string " , " p " , " The signal identifier pattern. " } ,
} ,
returns = { } ,
example = {
" Signal.clear_pattern('sound%-.*') " ,
" Signal.clear_pattern('.*') -- clear all signals " ,
}
}
}
2011-11-16 13:57:43 +00:00
Module { name = " hump.camera " ,
title = " Camera " ,
2012-04-13 18:05:12 +00:00
short = " A camera for LÖVE " ,
2011-11-16 13:57:43 +00:00
long = [ === [
2012-04-13 18:05:12 +00:00
A camera utility for L & Ouml ; VE . A camera can " look " at a position . It can zoom in and
2011-11-16 13:57:43 +00:00
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 . ] === ] ,
Function { name = " new " ,
2012-10-07 11:37:50 +00:00
short = " Create a new camera. " ,
2011-11-16 13:57:43 +00:00
long = [ === [
2012-10-07 11:37:50 +00:00
Creates a new camera . You can access the camera position using
2012-04-13 18:05:12 +00:00
{ # camera.x , camera.y } , the zoom using { # camera.zoom } and the rotation using
{ # camera.rot } .
2011-11-16 13:57:43 +00:00
2012-04-13 18:05:12 +00:00
The module variable name can be used at a shortcut to { # new ( ) } . ] === ] ,
2011-11-16 13:57:43 +00:00
params = {
2012-04-13 18:05:12 +00:00
{ " numbers " , " x,y " , " Point for the camera to look at. " , default = " screen center " } ,
2011-11-16 13:57:43 +00:00
{ " number " , " zoom " , " Camera zoom. " , default = " 1 " } ,
{ " number " , " rot " , " Camera rotation in radians. " , default = " 0 " } ,
} ,
returns = {
2012-10-07 11:37:50 +00:00
{ " camera " , " A new camera. " }
2011-11-16 13:57:43 +00:00
} ,
example = [ === [
camera = require ' hump.camera '
-- camera looking at (100,100) with zoom 2 and rotated by 45 degrees
2012-04-13 18:05:12 +00:00
cam = camera ( 100 , 100 , 2 , math.pi / 2 )
2011-11-16 13:57:43 +00:00
] === ]
} ,
Function { name = " camera:rotate " ,
2012-10-07 11:37:50 +00:00
short = " Rotate camera. " ,
2011-11-16 13:57:43 +00:00
long = [ === [
2012-04-13 18:05:12 +00:00
Rotate the camera { * by } some angle . To { * set } the angle use
{ # camera.rot = new_angle } .
2011-11-16 13:57:43 +00:00
2012-04-13 18:05:12 +00:00
This function is shortcut to { # camera.rot = camera.rot + angle } . ] === ] ,
2011-11-16 13:57:43 +00:00
params = {
{ " number " , " angle " , " Rotation angle in radians " }
} ,
returns = {
2012-10-07 11:37:50 +00:00
{ " camera " , " The camera. " }
2011-11-16 13:57:43 +00:00
} ,
example = {
" function love.update(dt) \n camera:rotate(dt) \n end " ,
2012-04-13 18:05:12 +00:00
" function love.update(dt) \n camera:rotate(dt):move(dt,dt) \n end "
2011-11-16 13:57:43 +00:00
} ,
} ,
2012-09-10 08:50:50 +00:00
Function { name = " camera:rotation " ,
2012-10-07 11:37:50 +00:00
short = " Get or set camera rotation. " ,
long = [ === [ Returns { # camera.rot } .
2012-09-10 08:50:50 +00:00
2012-10-07 11:37:50 +00:00
If given an angle , set rotation : { # camera.rot = angle } . ] === ] ,
params = {
{ " number " , " angle " , " Rotation angle in radians " , optional = true }
} ,
2012-09-10 08:50:50 +00:00
returns = {
{ " number " , " Rotation angle in radians. " }
} ,
2012-10-07 11:37:50 +00:00
example = {
[===[love.graphics.print(camera:rotation(), 10, 10)]===] ,
[===[camera:rotation(math.pi/2)]===] ,
}
2012-09-10 08:50:50 +00:00
} ,
2011-11-16 13:57:43 +00:00
Function { name = " camera:move " ,
2012-10-07 11:37:50 +00:00
short = " Move camera. " ,
2011-11-16 13:57:43 +00:00
long = [ === [
2012-10-07 11:37:50 +00:00
{ * Move } the camera { * by } some vector . To { * set } the position , use { # camera : lookAt ( x , y ) } .
2011-11-16 13:57:43 +00:00
2012-04-13 18:05:12 +00:00
This function is shortcut to { # camera.x , camera.y = camera.x + dx , camera.y + dy } . ] === ] ,
2011-11-16 13:57:43 +00:00
params = {
2012-04-13 18:05:12 +00:00
{ " numbers " , " dx,dy " , " Direction to move the camera. " } ,
2011-11-16 13:57:43 +00:00
} ,
returns = {
2012-10-07 11:37:50 +00:00
{ " camera " , " The camera. " } ,
2011-11-16 13:57:43 +00:00
} ,
example = {
2012-09-10 08:50:50 +00:00
" function love.update(dt) \n camera:move(dt * 5, dt * 6) \n end " ,
2011-11-16 13:57:43 +00:00
" function love.update(dt) \n camera:move(dt * 5, dt * 6):rotate(dt) \n end "
} ,
} ,
2012-10-07 11:37:50 +00:00
Function { name = " camera:lookAt " ,
short = " Move camera to a position. " ,
long = [ === [
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 ( x , y ) } .
This function is shortcut to { # camera.x , camera.y = x , y } . ] === ] ,
params = {
{ " numbers " , " x,y " , " Position to look at. " } ,
} ,
returns = {
{ " camera " , " The camera. " } ,
} ,
example = {
" function love.update(dt) \n camera:lookAt(player.pos:unpack()) \n end " ,
" function love.update(dt) \n camera:lookAt(player.pos:unpack()):rotation(player.rot) \n end " ,
} ,
} ,
2012-09-10 08:50:50 +00:00
Function { name = " camera:pos " ,
short = " Get camera position.. " ,
long = [===[Returns {#camera.x, camera.y}.]===] ,
params = { } ,
returns = {
{ " numbers " , " Camera position. " } ,
} ,
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 ] === ] ,
} ,
2011-11-16 13:57:43 +00:00
Function { name = " camera:attach " ,
2012-10-07 11:37:50 +00:00
short = " Attach camera. " ,
2011-11-16 13:57:43 +00:00
long = [ === [
Start looking through the camera .
Apply camera transformations , i.e . move , scale and rotate everything until
2012-04-13 18:05:12 +00:00
{ # camera : detach ( ) } as if looking through the camera . ] === ] ,
2011-11-16 13:57:43 +00:00
params = { } ,
returns = { } ,
example = [ === [
function love . draw ( )
camera : attach ( )
draw_world ( )
cam : detach ( )
draw_hud ( )
end ] === ]
} ,
Function { name = " camera:detach " ,
2012-10-07 11:37:50 +00:00
short = " Detach camera. " ,
2011-11-16 13:57:43 +00:00
long = " Stop looking through the camera. " ,
params = { } ,
returns = { } ,
example = [ === [
function love . draw ( )
camera : attach ( )
draw_world ( )
cam : detach ( )
draw_hud ( )
end ] === ]
} ,
Function { name = " camera:draw " ,
short = " Attach, draw and detach. " ,
long = [ === [
2012-04-13 18:05:12 +00:00
Wrap a function between a { # camera : attach ( ) } / { # camera : detach ( ) } pair :
2012-04-13 19:25:06 +00:00
[ % cam : attach ( )
2011-11-16 13:57:43 +00:00
func ( )
2012-04-13 19:25:06 +00:00
cam : detach ( ) ] ] === ] ,
2011-11-16 13:57:43 +00:00
params = {
{ " function " , " func " , " Drawing function to be wrapped. " } ,
} ,
returns = { } ,
example = [ === [
function love . draw ( )
camera : draw ( draw_world )
draw_hud ( )
end ] === ]
} ,
Function { name = {
" camera:worldCoords " ,
" camera:cameraCoords " ,
} ,
short = {
" Convert point to world coordinates. " ,
" Convert point to camera coordinates. " ,
} ,
long = [ === [
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
2012-04-13 18:05:12 +00:00
is called { * world coordinates } , the second one { * camera coordinates } .
2011-11-16 13:57:43 +00:00
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 .
These two functions convert a point between these two coordinate systems . ] === ] ,
params = {
2012-04-13 18:05:12 +00:00
{ " numbers " , " x, y " , " Point to transform. " } ,
2011-11-16 13:57:43 +00:00
} ,
returns = {
2012-04-13 18:05:12 +00:00
{ " numbers " , " Transformed point. " } ,
2011-11-16 13:57:43 +00:00
} ,
example = {
[ === [
2012-04-13 18:05:12 +00:00
x , y = camera : worldCoords ( love.mouse . getPosition ( ) )
selectedUnit : plotPath ( x , y )
2011-11-16 13:57:43 +00:00
] === ] , [ === [
2012-06-12 11:03:45 +00:00
x , y = cam : cameraCoords ( player.pos )
2012-04-13 18:05:12 +00:00
love.graphics . line ( x , y , love.mouse . getPosition ( ) )
2011-11-16 13:57:43 +00:00
] === ]
} ,
} ,
Function { name = " camera:mousepos " ,
short = " Get mouse position in world coordinates. " ,
2012-04-13 19:57:31 +00:00
long = " Shortcut to {#camera:worldCoords(love.mouse.getPosition())}. " ,
2011-11-16 13:57:43 +00:00
params = { } ,
returns = {
2012-04-13 18:05:12 +00:00
{ " numbers " , " Mouse position in world coordinates. " } ,
2011-11-16 13:57:43 +00:00
} ,
example = [ === [
2012-04-13 18:05:12 +00:00
x , y = camera : mousepos ( )
selectedUnit : plotPath ( x , y )
2011-11-16 13:57:43 +00:00
] === ] ,
} ,
}
Module { name = " hump.ringbuffer " ,
title = " Ringbuffer " ,
short = " A data structure that wraps around itself. " ,
long = [ === [
A ring - buffer is a circular array : It does not have a first nor a last item ,
2012-04-13 18:05:12 +00:00
but it has a { * selected } or { * current } element .
2011-11-16 13:57:43 +00:00
2012-04-13 18:05:12 +00:00
A ring - buffer can be used to implement { * Tomb Raider } style inventories , looping
2011-11-16 13:57:43 +00:00
play - lists , recurring dialogs ( like a unit ' s answers when selecting it multiple
2012-04-13 18:05:12 +00:00
times in { * Warcraft } ) and generally everything that has a circular or looping
2011-11-16 13:57:43 +00:00
structure . ] === ] ,
Function { name = " new " ,
short = " Create new ring-buffer. " ,
long = " Create new ring-buffer. \n \n The module name is a shortcut to this function. " ,
params = {
{ " mixed " , " ... " , " Initial elements. " }
} ,
returns = {
{ " Ringbuffer " , " The ring-buffer object. " } ,
} ,
example = [ === [
Ringbuffer = require ' hump.ringbuffer '
rb = ringbuffer ( 1 , 2 , 3 )
] === ]
} ,
Function { name = " ringbuffer:insert " ,
short = " Insert element. " ,
long = " Insert items behind current element. " ,
params = {
{ " mixed " , " ... " , " Items to insert. " } ,
} ,
returns = { } ,
example = [ === [
rb = RingbuffeR ( 1 , 5 , 6 ) -- content: 1,5,6
rb : insert ( 2 , 3 , 4 ) -- content: 1,2,3,4,5,6
] === ]
} ,
Function { name = " ringbuffer:remove " ,
short = " Remove currently selected item. " ,
long = " Remove current item, return it and select next element. " ,
params = { } ,
returns = {
{ " mixed " , " The removed item. " }
} ,
example = [ === [
rb = Ringbuffer ( 1 , 2 , 3 , 4 ) -- content: 1,2,3,4
val = rb : remove ( ) -- content: 2,3,4
print ( val ) -- prints `1'
] === ]
} ,
Function { name = " ringbuffer:removeAt " ,
short = " Remove an item. " ,
long = " Remove the item at a position relative to the current element. " ,
params = {
{ " number " , " pos " , " Position of the item to remove. " }
} ,
returns = {
{ " mixed " , " The removed item. " }
} ,
example = [ === [
rb = Ringbuffer ( 1 , 2 , 3 , 4 , 5 ) -- content: 1,2,3,4,5
rb : removeAt ( 2 ) -- content: 1,2,4,5
rb : removeAt ( - 1 ) -- content: 1,2,4
] === ]
} ,
Function { name = " ringbuffer:next " ,
short = " Select next item. " ,
long = " Select and return the next element. " ,
params = { } ,
returns = {
{ " mixed " , " The next item. " }
} ,
example = [ === [
rb = Ringbuffer ( 1 , 2 , 3 )
rb : next ( ) -- content: 2,3,1
rb : next ( ) -- content: 3,1,2
x = rb : next ( ) -- content: 1,2,3
print ( x ) -- prints `1'
] === ]
} ,
Function { name = " ringbuffer:prev " ,
short = " Select previous item. " ,
long = " Select and return the previous item. " ,
params = { } ,
returns = {
{ " mixed " , " The previous item. " }
} ,
example = [ === [
rb = Ringbuffer ( 1 , 2 , 3 )
rb : prev ( ) ) -- content: 3,1,2
rb : prev ( ) ) -- content: 2,3,1
x = rb : prev ( ) -- content: 1,2,3
print ( x ) -- prints `1'
] === ]
} ,
Function { name = " ringbuffer:get " ,
short = " Get currently selected item. " ,
long = " Return the current element. " ,
params = { } ,
returns = {
{ " mixed " , " The currently selected element. " }
} ,
example = [ === [
rb = Ringbuffer ( 1 , 2 , 3 )
rb : next ( ) -- content: 2,3,1
print ( rb : get ( ) ) -- prints '2'
] === ]
} ,
Function { name = " ringbuffer:size " ,
short = " Get ringbuffer size. " ,
long = " Get number of items in the buffer " ,
params = { } ,
returns = {
{ " number " , " Number of items in the buffer. " } ,
} ,
example = [ === [
rb = Ringbuffer ( 1 , 2 , 3 )
print ( rb : size ( ) ) -- prints '3'
rb : remove ( )
print ( rb : size ( ) ) -- prints '2'
] === ]
} ,
}