From f4337138e3baa617987acf49b33113b50bf613eb Mon Sep 17 00:00:00 2001
From: Matthias Richter Helper Utilities for a Multitude of Problems is a set of lightweight
- helpers for the awesome
- LÖVE Engine. It features
- hump differs from other libraries in that every component is
- independent of the remaining ones (apart from camera.lua, which does depends on
- vector.lua). hump's footprint is very small and thus should fit nicely
- into your projects. Below is the documentation of the various modules. You can directly jump to a
- module by clicking these: A typical game could consist of a menu-state, a level-state and a game-over-state. A gamestate can define (nearly) all callbacks that LÖVE defines. In addition,
- there are callbacks for entering and leaving a state.: When using Helper Utilities for a Multitude of Problems is a set of lightweight helpers for the awesome LÖVE Engine. It features hump differs from other libraries in that every component is independent of the remaining ones (apart from camera.lua, which does depends on vector.lua). hump's footprint is very small and thus should fit nicely into your projects. A gamestate encapsulates independent data an behaviour into a single entity. A typical game could consist of a menu-state, a level-state and a game-over-state. A gamestate can define (nearly) all callbacks that LÖVE defines. In addition, there are callbacks for entering and leaving a state.: When using Declare a new gamestate. A gamestate can define several callbacks Switch to a gamestate, with any additional arguments passed to the new state. 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. Calls the corresponding function on the current gamestate (see callbacks). Only needed when not using registerEvents(). Declare a new gamestate. A gamestate can define several callbacks. The new gamestate. Switch to a gamestate, with any additional arguments passed to the new state. Switching a gamestate will call the Target gamestate. Additional arguments to pass to to:enter(). The results of to:enter() Calls the corresponding function on the current gamestate (see callbacks). Only needed when not using registerEvents(). Arguments to pass to the corresponding callback. The results of the callback function. Register all love callbacks to call Gamestate.update(), Gamestate.draw(), etc. automatically. This is by done by overwriting the love callbacks, e.g.:
- Note: Only works when called in Register all love callbacks to call Gamestate.update(), Gamestate.draw(), etc. automatically. This is by done by overwriting the love callbacks, e.g.: Note: Only works when called in 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. Add a timed function. The function will be executed after 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. It is an error to schedule a timer again if it is not yet finished or canced. hump.timer provides a simple interface to use delayed functions, i.e. functionsthat will be executed after some amount time has passed. For example, you can usea timer to set the player invincible for a short amount of time. In addition, the module offers facilities to create functions that interpolateor 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. Add a timed function. The function will be executed after 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. It is an error to schedule a function again if it is not yet finished or canceled. Number of seconds the function will be delayed. The function to be delayed. The timer handle. Add a function that will be called If Add a function that will be called If Number of seconds between two consecutive function calls. The function to be called periodically. Number of times the function is to be called. The timer handle. Prevent a timer from being executed in the future. Alway use the function handle returned by Never use this in another timer. Prevent a timer from being executed in the future. Always use the function handle returned by add()/addPeriodic() to cancel a timer. Never use this in another timer. The function to be canceled. Update timers and execute functions if the deadline is reached. Use this in love.update(dt). Remove all timed and periodic functions. Functions that have not yet been executed will discarded. Update timers and execute functions if the deadline is reached. Use this in love.update(dt). Time that has passed since the last update(). Remove all timed and periodic functions. Functions that have not yet been executed will discarded. Update timers and execute functions if the deadline is reached. Use this in love.update(dt). Create a wrapper for an interpolating function, i.e. a function that acts
- depending on how much time has passed. The wrapper will have the prototype:
- The prototype of the interpolating function is:
- Create a wrapper for an interpolating function, i.e. a function that acts depending on how much time has passed. The wrapper will have the prototype: The prototype of the interpolating function is: Interpolation length in seconds. Interpolating function. The wrapper function. Create a wrapper for an oscillating function, which is basically a looping
- interpolating function. The function prototypes are the same as with Interpolator():
- As with Interpolator, the wrapper will return whatever Create a wrapper for an oscillating function, which is basically a looping interpolating function. The function prototypes are the same as with Interpolator(): As with Interpolator, the wrapper will return whatever Length of one interpolation period. Oscillating function. The wrapper function. You can access the individual coordinates by using Vector arithmetic is implemented by using Relational operators are defined, too: A handy 2D vector class providing most of the things you do with vectors. You can access the individual coordinates by using Vector arithmetic is implemented by using Relational operators are defined, too: Create a new vector. Test whether a variable is a vector. Create a new vector. Coordinates. The vector. Test whether a variable is a vector. The variable to test. 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:
- Extract coordinates. Multiplies vectors coordinate wise, i.e. This does not change either argument vectors, but creates a new one. Get length of a vector, i.e. Get squared length of a vector, i.e. 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: Copy of the vector Extract coordinates. The coordinates Multiplies vectors coordinate wise, i.e. This does not change either argument vectors, but creates a new one. The other vector The new vector as described above Get length of a vector, i.e. Length of the vector. Get squared length of a vector, i.e. Squared length of the vector. Get distance of two vectors. The same as Get distance of two vectors. The same as Other vector to measure the distance to. The distance of the vectors. 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. Normalize a vector, i.e. make the vector unit length. Great to use on
- intermediate results. This modifies the vector. If in doubt, use Get a rotated vector. This does not change the input vector, but creates a new vector. 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. Vector with same direction as the input vector, but length 1. Normalize a vector, i.e. make the vector unit length. Great to use on intermediate results. This modifies the vector. If in doubt, use {#vector:normalized()}. Itself - the normalized vector Get a rotated vector. This does not change the input vector, but creates a new vector. Rotation angle in radians. The rotated vector Rotate a vector in-place. Great to use on intermediate results. This modifies the vector. If in doubt, use Quick rotation by 90°. Creates a new vector. The same as (but faster):
- Project vector onto another vector (see sketch). Mirrors vector on the axis defined by the other vector. Get cross product of both vectors. Equals the area of the parallelogram
- spanned by both vectors. Declare a new class. The constructor will receive the newly create object as first argument. You can check if an object is an instance of a class using The name of the variable that holds the module can be used as a shortcut to
- Rotate a vector in-place. Great to use on intermediate results. This modifies the vector. If in doubt, use {#vector:rotate()} Rotation angle in radians. Itself - the rotated vector Quick rotation by 90°. Creates a new vector. The same as (but faster): A vector perpendicular to the input vector Project vector onto another vector (see sketch). The vector to project on. The projected vector. Mirrors vector on the axis defined by the other vector. The vector to mirror on. The mirrored vector. Get cross product of both vectors. Equals the area of the parallelogram spanned by both vectors. Vector to compute the cross product with. Cross product of both vectors. An table-free version of Using this module instead of Transforms a vector to a string of the form The vector The string representation Computes The scalar. The vector. The result of the operation. Computes the sum/difference of vectors. Same as First vector. Second vector. The result of the operation. Multiplies vectors coordinate wise, i.e. First vector. Second vector. The result of the operation. Computes the dot product of two vectors, First vector. Second vector. The dot product. Computes the cross product/determinant of two vectors, First vector. Second vector. The cross product. Compares two vectors according to First vector. Second vector. The result of the operation. Get length of a vector, i.e. The vector. Length of the vector. Get squared length of a vector, i.e. The vector. Squared length of the vector. Get distance of two points. The same as First vector. Second vector. The distance of the points. Get normalized vector, i.e. a vector with the same direction as the input vector, but with length 1. The vector. Vector with same direction as the input vector, but length 1. Get a rotated vector. Rotation angle in radians. The vector. The rotated vector Quick rotation by 90°. The same as (but faster) The vector. A vector perpendicular to the input vector Project vector onto another vector. The vector to project. The vector to project onto. The projected vector. Mirrors vector on the axis defined by the other vector. The vector to mirror. The vector defining the axis. The mirrored vector. A small, fast class implementation with multiple inheritance support Declare a new class. The constructor will receive the newly create object as first argument. You can check if an object is an instance of a class using The name of the variable that holds the module can be used as a shortcut to Class constructor. Can be accessed with Class name (used only to make the class compliant to Classes to inherit from. Can either be a single class or a table of classes The class 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. 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. The object. Usually Arguments to pass to the constructor Whatever the parent class constructor returns 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). Be careful with changing table values in a subclass: This will change the
- 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. Note: 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). Be careful with changing table values in a subclass: This will change the 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. Note: Parent classes to inherit from Tests whether an object is an instance of a class. Tests whether an object is an instance of a class. Class to test. Note: this is the class itself, not the name of the class. Be careful when using metamethods like 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"
-result:foo() -- error: method does not exist Note that while you can define the 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()
-instance:foo() -- prints only foo 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. Creates a new camera object. You can access the camera position using
- The module variable name can be used at a shortcut to Be careful when using metamethods like A = Class{function(self, x) self.x = x end}function A:__add(other) return A(self.x + other.x) endfunction 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) endfunction B:foo() print("foo") end one, two = B(1,2), B(3,4)result = one + tworesult:show() -- prints "A: 4"result:foo() -- error: method does not exist Note that while you can define the 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 B = Class{inherits = A}instance = B()instance:foo() -- prints only foo Depends on hump.vector-light A camera utility for LÖVE. A camera can "look" at a position. It can zoom in andout and it can rotate it's view. In the background, this is done by actuallymoving, scaling and rotating everything in the game world. But don't worry aboutthat. Creates a new camera object. You can access the camera position using The module variable name can be used at a shortcut to Point for the camera to look at. Camera zoom. Camera rotation in radians. A new camera object. Rotate the camera by some angle. To set the angle use
- This function is shortcut to Rotate the camera by some angle. To set the angle use This function is shortcut to Rotation angle in radians The camera object. Move the camera by some vector. To set the position, use
- This function is shortcut to Move the camera by some vector. To set the position, use This function is shortcut to Direction to move the camera. The camera object. Start looking through the camera. Apply camera transformations, i.e. move, scale and rotate everything until
- Start looking through the camera. Apply camera transformations, i.e. move, scale and rotate everything until Stop looking through the camera. Stop looking through the camera. Wrap a function between a Wrap a function between a Drawing function to be wrapped. 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. These two functions convert a point between these two coordinate systems. Shortcut to A ring-buffer can be used to implement Tomb Raider style inventories, looping
- play-lists, recurring dialogs (like a unit's answers when selecting it multiple
- times in Warcraft) and generally everything that has a circular or looping
- structure. Create new ring-buffer. The module name is a shortcut to this function. 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. These two functions convert a point between these two coordinate systems. Point to transform. Transformed point. Shortcut to Mouse position in world coordinates. A ring-buffer is a circular array: It does not have a first nor a last item,but it has a selected or current element. A ring-buffer can be used to implement Tomb Raider style inventories, loopingplay-lists, recurring dialogs (like a unit's answers when selecting it multipletimes in Warcraft) and generally everything that has a circular or loopingstructure. Create new ring-buffer. The module name is a shortcut to this function. Initial elements. The ring-buffer object. Insert items behind current element. Insert items behind current element. Items to insert. Remove current item, return it and select next element. Remove current item, return it and select next element. The removed item. Remove the item at a position relative to the current element. Remove the item at a position relative to the current element. Position of the item to remove. The removed item. Select and return the next element. Select and return the next element. The next item. Select and return the previous item. Select and return the previous item. The previous item. Return the current element. Return the current element. The currently selected element. Get number of items in the buffer Get number of items in the buffer Number of items in the buffer. Yay, free software: Copyright (c) 2010 Matthias Richter Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software. Except as contained in this notice, the name(s) of the above copyright holders
- shall not be used in advertising or otherwise to promote the sale, use or
- other dealings in this Software without prior written authorization. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE. You can view and download the individual modules on github: vrld/hump.
- You may also download the whole packed sourcecode either in
- zip or
- tar formats. You can clone the project with Git by running:
- Yay, free software: Copyright (c) 2010 Matthias Richter Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. Except as contained in this notice, the name(s) of the above copyright holders shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. '
+ if c == '[' then return element(out, next) end
+ out[#out+1] = c
+ return block(out, next)
+ end
+
+ function block(out, next)
+ local c = next()
+ if not c then out[#out+1] = 'hump
- Helper Utilities for More Productivity
-
-
-Introduction^ top
-
-
-
- Documentation^ top
-
-
hump.gamestate^ top
A gamestate encapsulates independent data an behaviour into a single entity.hump.gamestate = require "Gamestate"
Module overview
Gamestate Callbacks
init()
switch()
.
-enter(previous, ...)
switch()
.
-leave()
switch()
.
-update()
draw()
focus()
keypressed()
keyreleased()
mousepressed()
mousereleased()
joystickpressed()
joystickreleased()
quit()
registerEvents()
, all these callbacks will receive the same
- arguments as the LÖVE callbacks do.menu = Gamestate.new()
+
hump Helper Utilities for More Productivity
Introduction^ top
Documentation^ top
hump.gamestate^ top
Gamestate = require "hump.gamestate"
Module overview
Gamestate Callbacks^ top
init()
switch()
.enter(previous, ...)
switch()
.leave()
switch()
.update()
draw()
focus()
keypressed()
keyreleased()
mousepressed()
mousereleased()
joystickpressed()
joystickreleased()
quit()
registerEvents()
, all these callbacks will receive the same arguments as the LÖVE callbacks do.menu = Gamestate.new()
function menu:init() -- run only once
- self.background = love.graphics.newImage('bg.jpg')
+ self.background = love.graphics.newImage('bg.jpg')
Buttons.initialize()
end
@@ -106,9 +18,9 @@ function menu:draw()
end
function menu:keyreleased(key)
- if key == 'up' then
+ if key == 'up' then
Buttons.selectPrevious()
- elseif key == 'down' then
+ elseif key == 'down' then
Buttons.selectNext()
elseif
Buttons.active:onClick()
@@ -119,13 +31,11 @@ function menu:mousereleased(x,y, mouse_btn)
local button = Buttons.hovered(x,y)
if button then
Button.select(button)
- if mouse_btn == 'l' then
+ if mouse_btn == 'l' then
button:onClick()
end
end
-end
function new()^ top
menu = Gamestate.new()
function switch(to, ...)^ top
to
...
Gamestate.switch(game, level_two)
function update(...)^ top
function draw(...)^ top
function focus(...)^ top
function keypressed(...)^ top
function keyreleased(...)^ top
function mousepressed(...)^ top
function mousereleased(...)^ top
function joystickpressed(...)^ top
function joystickreleased(...)^ top
function quit(...)^ top
...
function love.update(dt)
+end
function new()^ top
menu = Gamestate.new()
function switch(to, ...)^ top
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.to
...
Gamestate.switch(game, level_two)
function update(...)^ top
function draw(...)^ top
function focus(...)^ top
function keypressed(...)^ top
function keyreleased(...)^ top
function mousepressed(...)^ top
function mousereleased(...)^ top
function joystickpressed(...)^ top
function joystickreleased(...)^ top
function quit(...)^ top
...
function love.update(dt)
Gamestate.update(dt)
end
@@ -136,63 +46,31 @@ end
function love.keypressed(key, code)
Gamestate.keypressed(key, code)
-end
function registerEvents()^ top
local old_update = love.update
-function love.update(dt)
- old_update(dt)
- Gamestate.current:update(dt)
-end
love.load()
or any other function that is executed
-after the whole file is loaded.function love.load()
+end
function registerEvents()^ top
local old_update = love.updatefunction love.update(dt) old_update(dt) Gamestate.current:update(dt)end
love.load()
or any other function that is executedafter the whole file is loaded.function love.load()
Gamestate.registerEvents()
Gamestate.switch(menu)
-end
hump.timer^ top
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.hump.timer = require "Timer"
Module overview
function add(delay, func)^ top
delay
seconds
- have elapsed, given that update() is called every frame.func
will receive itself as only parameter. This is useful to implement
- periodic behavior (see the example).delay
func
-- grant the player 5 seconds of immortality
+end
hump.timer^ top
Timer = require "hump.timer"
Module overview
function add(delay, func)^ top
delay
seconds have elapsed, given that update() is called every frame.func
will receive itself as only parameter. This is useful to implement periodic behavior (see the example).delay
func
-- grant the player 5 seconds of immortality
player.isInvincible = true
-Timer.add(5, function() player.isInvincible = false end)
-- print "foo" every second. See addPeriodic.
-Timer.add(1, function(func) print("foo") Timer.add(1, func) end)
function addPeriodic(delay, func, count)^ top
count
times every delay
seconds.count
is omitted, the function will be called until it returns false
- or clear() is called.delay
func
count
(optional)Timer.addPeriodic(1, function() lamp:toggleLight() end)
Timer.addPeriodic(0.3, function() mothership:spawnFighter() end, 5)
-- flicker player's image as long as he is invincible
+Timer.add(5, function() player.isInvincible = false end)
-- print "foo" every second. See addPeriodic.
+Timer.add(1, function(func) print("foo") Timer.add(1, func) end)
function addPeriodic(delay, func, count)^ top
count
times every delay
seconds.count
is omitted, the function will be called until it returns false
or clear() is called.delay
func
count
Timer.addPeriodic(1, function() lamp:toggleLight() end)
Timer.addPeriodic(0.3, function() mothership:spawnFighter() end, 5)
-- flicker player's image as long as he is invincible
Timer.addPeriodic(0.1, function()
player:flipImage()
return player.isInvincible
-end)
function cancel(func)^ top
add()
/addPeriodic()
to cancel a timer.func
function tick()
- print('tock')
+end)
function cancel(func)^ top
func
function tick()
+ print('tick... tock...')
end
handle = Timer.addPeriodic(1, tick)
-
-- later
-Timer.cancel(handle) -- NOT: Timer.cancel(tick)
function update(dt)^ top
dt
function love.update(dt)
+Timer.cancel(handle) -- NOT: Timer.cancel(tick)
function clear()^ top
Timer.clear()
function update(dt)^ top
dt
function love.update(dt)
do_stuff()
Timer.update(dt)
-end
function clear()^ top
Timer.clear()
function update(dt)^ top
dt
function love.update(dt)
- do_stuff()
- Timer.update(dt)
-end
function Interpolator(length, func)^ top
- where function wrapper(dt, ...)
dt
is the time that has passed since the last call of the wrapper
- and ...
are arguments passed to the interpolating function. It will return
- whatever the interpolating functions returns if the interpolation is not yet
- finished or nil if the interpolation is done.
- where function interpolator(fraction, ...)
fraction
is a number between 0 and 1 depending on how much time has
- passed and ...
are additional arguments supplied to the wrapper.length
func
fader = Timer.Interpolator(5, function(frac, r,g,b)
+end
function Interpolator(length, func)^ top
where function wrapper(dt, ...)
dt
is the time that has passed since the last call of the wrapper and ...
are arguments passed to the interpolating function. It will return whatever the interpolating functions returns if the interpolation is not yet finished or nil if the interpolation is done.
where function interpolator(fraction, ...)
fraction
is a number between 0 and 1 depending on how much time has passed and ...
are additional arguments supplied to the wrapper.length
func
fader = Timer.Interpolator(5, function(frac, r,g,b)
love.graphics.setBackgroundColor(frac*r,frac*g,frac*b)
end)
function love.update(dt)
fader(dt, 255,255,255)
-end
function Oscillator(length, func)^ top
- function wrapper(dt, ...)
function oscillator(fraction, ...)
oscillator()
returns.length
func
mover = Timer.Oscillator(10, function(frac)
+end
function Oscillator(length, func)^ top
function wrapper(dt, ...)
function oscillator(fraction, ...)
oscillator()
returns.length
func
mover = Timer.Oscillator(10, function(frac)
return 400 + 300 * math.sin(2*math.pi*frac)
end)
@@ -202,116 +80,112 @@ function love.update(dt)
end
function love.draw()
- love.graphics.circle('fill', xpos, 300, 80, 36)
-end
hump.vector^ top
A handy 2D vector class providing most of the things you do with vectors.hump.vector = require "vector"
vec.x
and vec.y
.Module overview
Arithmetics and relations
__add
, __mul
and other metamethods:vector + vector = vector
vector - vector = vector
vector * vector = number
number * vector = vector
vector * number = vector
vector / number = vector
true
, if a.x == b.x
and a.y == b.y
.
-true
, if a.x <= b.x
and a.y <= b.y
.
-true
, if a.x < b.x
or a.x == b.x
and a.y < b.y
.
--- acceleration, player.velocity and player.position are vectors
+ love.graphics.circle('fill', xpos, 300, 80, 36)
+end
hump.vector^ top
vector = require "hump.vector"
vec.x
and vec.y
.Module overview
Arithmetics and relations^ top
__add
, __mul
and other metamethods:vector + vector = vector
vector - vector = vector
vector * vector = number
number * vector = vector
vector * number = vector
vector / number = vector
true
, if a.x == b.x
and a.y == b.y
.true
, if a.x <= b.x
and a.y <= b.y
.true
, if a.x < b.x
or a.x == b.x
and a.y < b.y
.-- 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 new(x,y)^ top
x,y
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 isvector(v)^ top
v
true
if v
is a vector, false
otherwiseif not vector.isvector(v) then
+player.position = player.position + player.velocity * dt
function new(x,y)^ top
x,y
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 isvector(v)^ top
v
true
if v
is a vector, false
otherwiseif not vector.isvector(v) then
v = vector(v,0)
-end
function vector:clone()^ top
a = vector(1,1) -- create vector
-b = a -- b references a
-c = a:clone() -- c is a copy of a
-b.x = 0 -- changes a,b and c
-print(a,b,c) -- prints '(1,0), (1,0), (1,1)'
copy = original:clone
function vector:unpack()^ top
x,y = pos:unpack()
love.graphics.draw(self.image, self.pos:unpack())
function vector:permul(other)^ top
result = vector(a.x * b.x, a.y * b.y)
.other
scaled = original:permul(vector(1,1.5))
function vector:len()^ top
math.sqrt(vec.x * vec.x + vec.y * vec.y)
.distance = (a - b):len()
function vector:len2()^ top
vec.x * vec.x + vec.y * vec.y
.-- get closest vertex to a given vector
+end
function vector:clone()^ top
a = vector(1,1) -- create vectorb = a -- b references ac = a:clone() -- c is a copy of ab.x = 0 -- changes a,b and cprint(a,b,c) -- prints '(1,0), (1,0), (1,1)'
copy = original:clone
function vector:unpack()^ top
x,y = pos:unpack()
love.graphics.draw(self.image, self.pos:unpack())
function vector:permul(other)^ top
result = vector(a.x * b.x, a.y * b.y)
.other
scaled = original:permul(vector(1,1.5))
function vector:len()^ top
math.sqrt(vec.x * vec.x + vec.y * vec.y)
.distance = (a - b):len()
function vector:len2()^ top
vec.x * vec.x + vec.y * vec.y
.-- 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
+ if temp < dsq then
closest, dsq = vertices[i], temp
end
-end
function vector:dist(other)^ top
(a - b):len()
.other
-- get closest vertex to a given vector
+end
function vector:dist(other)^ top
(a - b):len()
.other
-- 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
+ if temp < dist then
closest, dist = vertices[i], temp
end
-end
function vector:normalized()^ top
direction = velocity:normalized()
function vector:normalize_inplace()^ top
vector:normalized()
.normal = (b - a):perpendicular():normalize_inplace()
function vector:rotated(phi)^ top
phi
-- approximate a circle
+end
function vector:normalized()^ top
direction = velocity:normalized()
function vector:normalize_inplace()^ top
normal = (b - a):perpendicular():normalize_inplace()
function vector:rotated(phi)^ top
phi
-- 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
function vector:rotate_inplace(phi)^ top
vector:rotate()
phi
-- ongoing rotation
-spawner.direction:rotate_inplace(dt)
function vector:perpendicular()^ top
vec:rotate(math.pi/2)
normal = (b - a):perpendicular():normalize_inplace()
function vector:projectOn(v)^ top
v
velocity_component = velocity:projectOn(axis)
function vector:mirrorOn(v)^ top
v
deflected_velocity = ball.velocity:mirrorOn(surface_normal)
function vector:cross(other)^ top
other
parallelogram_area = a:cross(b)
hump.class^ top
A small, fast class implementation with multiple inheritance supporthump.class = require "Class"
Module overview
function new{constructor, name = the_name, inherits = super}^ top
object:is_a()
.new()
(see example).constructor
(optional)theclass.construct(object, ...)
the_name
(optional)tostring()
.super
(optional)Class = require 'hump.class' -- `Class' is now a shortcut to new()
+end
function vector:rotate_inplace(phi)^ top
phi
-- ongoing rotation
+spawner.direction:rotate_inplace(dt)
function vector:perpendicular()^ top
vec:rotate(math.pi/2)
normal = (b - a):perpendicular():normalize_inplace()
function vector:projectOn(v)^ top
v
velocity_component = velocity:projectOn(axis)
function vector:mirrorOn(v)^ top
v
deflected_velocity = ball.velocity:mirrorOn(surface_normal)
function vector:cross(other)^ top
other
parallelogram_area = a:cross(b)
hump.vector-light^ top
vector = require "hump.vector-light"
hump.vector
. Instead of a vector class, hump.vector-light
provides functions that operate on numbers.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
.Module overview
function str(x,y)^ top
(x,y)
.x,y
print(vector.str(love.mouse.getPosition()))
function mul(s, x,y)^ top
function div(s, x,y)^ top
x*s, y*s
and x/s, y/s
. The order of arguments is chosen so that you can chain multiple operations (see example).s
x,y
velx,vely = vec.mul(dt, vec.add(velx,vely, accx,accy))
x,y = vec.div(self.zoom, x-w/2, y-h/2)
function add(x1,y1, x2,y2)^ top
function sub(x1,y1, x2,y2)^ top
x1+x2, y1+y2
or x1-x2, y1-y2
respectively. Meant to be used in conjunction with other functions.x1,y1
x2,y2
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 permul(x1,y1, x2,y2)^ top
x1*x2, y1*y2)
.x1,y1
x2,y2
x,y = vector.permul(x,y, 1,1.5)
function dot(x1,y1, x2,y2)^ top
x1*x2 + y1*y2
.x1,y1
x2,y2
cosphi = vector.dot(rx,ry, vx,vy)
function det(x1,y1, x2,y2)^ top
function cross(x1,y1, x2,y2)^ top
x1*y2 - y1*x2
.x1,y1
x2,y2
parallelogram_area = vector.det(ax,ay, bx,by)
function eq(x1,y1, x2,y2)^ top
function le(x1,y1, x2,y2)^ top
function lt(x1,y1, x2,y2)^ top
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
x1,y1
x2,y2
...
function len(x,y)^ top
math.sqrt(x*x + y*y)
.x,y
distance = vector.len(love.mouse.getPosition())
function len2(x,y)^ top
x*x + y*y
.x,y
-- 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 dist(x1,y1, x2,y2)^ top
vector.len(x1-x2, y1-y2)
.x1,y1
x2,y2
-- 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 normalize(x,y)^ top
x,y
dx,dy = vector.normalize(vx,vy)
function rotate(phi, x,y)^ top
phi
x,y
-- 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 perpendicular(x,y)^ top
vector.rotate(math.pi/2, x,y)
x,y
nx,ny = vector.normalize(vector.perpendicular(bx-ax, by-ay))
function project(x,y, u,v)^ top
x,y
u,v
vx_p,vy_p = vector.project(vx,vy, ax,ay)
function mirror(x,y, u,v)^ top
x,y
u,v
vx,vy = vector.mirror(vx,vy, surface.x,surface.y)
hump.class^ top
Class = require "hump.class"
Module overview
function new(constructor, the_name, super)^ top
object:is_a()
.new()
(see example).constructor
theclass.construct(object, ...)
the_name
tostring()
.super
Class = require 'hump.class' -- `Class' is now a shortcut to new()
--- define class without a name
+-- define class with implicit name 'Feline'
Feline = Class{function(self, size, weight)
self.size = size
self.weight = weight
end}
-print(Feline) -- prints '<unnamed class>'
+print(Feline) -- prints 'Feline'
-- define class method
function Feline:stats()
- return string.format("size: %.02f, weight %.02f", self.size, self.weight)
+ 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'
+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)
+-- 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)
-print(Feline, garfield) -- prints 'Feline <instance of Feline>'
-
Class = require 'hump.class'
+print(Feline, garfield) -- prints 'Feline
Class = require 'hump.class'
A = Class{}
function A:foo()
- print('foo')
+ print('foo')
end
B = Class{}
function B:bar()
- print('bar')
+ print('bar')
end
-- single inheritance
C = Class{inherits = A}
instance = C()
-instance:foo() -- prints 'foo'
+instance:foo() -- prints 'foo'
-- multiple inheritance
D = Class{inherits = {A,B}}
instance = D()
-instance:foo() -- prints 'foo'
-instance:bar() -- prints 'bar'
-
function class.construct(object, ...)^ top
object
self
....
Class = require 'hump.class'
+instance:foo() -- prints 'foo'
+instance:bar() -- prints 'bar'
+
function class.construct(object, ...)^ top
object
self
....
Class = require 'hump.class'
Shape = Class{function(self, area)
self.area = area
end}
function Shape:__tostring()
- return "area = " .. self.area
+ return "area = " .. self.area
end
Rectangle = Class{inherits = Shape, function(self, width, height)
@@ -321,14 +195,14 @@ Rectangle = Class{inherits = Shape, function(self, width, height)
end}
function Rectangle:__tostring()
local strs = {
- "width = " .. self.width,
- "height = " .. self.height,
+ "width = " .. self.width,
+ "height = " .. self.height,
Shape.__tostring(self)
},
- return table.concat(strs, ", ")
+ return table.concat(strs, ", ")
end
-print( Rectangle(2,4) ) -- prints 'width = 2, height = 4, area = 8'
+print( Rectangle(2,4) ) -- prints 'width = 2, height = 4, area = 8'
Menu = Class{function(self)
self.entries = {}
end}
@@ -352,14 +226,7 @@ Submenu = Class{inherits = {Menu, Entry}, function(self, title)
-- redirect self:execute() to self:display()
Entry.construct(self, title, Menu.display)
end}
-
function class:inherit(...)^ top
class:inherit()
doesn't actually care if the arguments supplied are
- hump classes. Just any table will work....
Class = require 'hump.class'
+
function class:inherit(...)^ top
class:inherit()
doesn't actually care if the arguments supplied are hump classes. Just any table will work....
Class = require 'hump.class'
Entity = Class{function(self)
GameObjects.register(self)
@@ -370,194 +237,95 @@ Collidable = {
if self.collision_handler[other.type])
return collision_handler[other.type](self, other, dx, dy)
end
- return collision_handler["*"](self, other, dx, dy)
+ return collision_handler["*"](self, other, dx, dy)
end,
- collision_handler = {["*"] = function() end},
+ collision_handler = {["*"] = function() end},
}
Spaceship = Class{function(self)
- self.type = "Spaceship"
+ self.type = "Spaceship"
-- ...
end}
-- make Spaceship collidable
Spaceship:inherit(Collidable)
-function Spaceship:collision_handler["Spaceship"](other, dx, dy)
+function Spaceship:collision_handler["Spaceship"](other, dx, dy)
-- ...
end
-
function object:is_a(cls)^ top
cls
true
if the object is an instance of the class, false
otherwiseClass = require 'hump.class'
+
function object:is_a(cls)^ top
cls
true
if the object is an instance of the class, false
otherwiseClass = 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
+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
-
Caveats
__add
or __mul
: If subclass
- 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:
- Class = require 'hump.class'
__index
metamethod of the class, this
- 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().
- But beware that this won't affect subclasses:
- Class = require 'hump.class'
hump.camera^ top
Depends on hump.vectorhump.camera = require "Camera"
Module overview
function new(pos, zoom, rot)^ top
camera.pos
, the zoom using camera.zoom
and the rotation using
- camera.rot
.new()
.pos
(screen center)zoom
(1)rot
(0)camera = require 'hump.camera'
-vector = require 'hump.vector'
+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
+
Caveats^ top
__add
or __mul
: If subclass 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: Class = require 'hump.class'
__index
metamethod of the class, this 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(). But beware that this won't affect subclasses: Class = require 'hump.class'
hump.camera^ top
Camera = require "hump.camera"
Module overview
function new(x,y, zoom, rot)^ top
camera.x, camera.y
, the zoom using camera.zoom
and the rotation using camera.rot
.new()
.x,y
zoom
rot
camera = require 'hump.camera'
-- camera looking at (100,100) with zoom 2 and rotated by 45 degrees
-cam = camera(vector(100,100), 2, math.pi/2)
-
function camera:rotate(angle)^ top
camera.rot = new_angle
.camera.rot = camera.rot + angle
.angle
function love.update(dt)
+cam = camera(100,100, 2, math.pi/2)
+
function camera:rotate(angle)^ top
camera.rot = new_angle
.camera.rot = camera.rot + angle
.angle
function love.update(dt)
camera:rotate(dt)
end
function love.update(dt)
- camera:rotate(dt):move(dt)
-end
function camera:move(v)^ top
function camera:move(x, y)^ top
camera.pos = some_vector
or camera.pos.x, camera.pos.y = new_x, new_y
.camera.pos = camera.pos + v
.v
x, y
function love.update(dt)
- camera:move(dt * velocity)
-end
function love.update(dt)
+ camera:rotate(dt):move(dt,dt)
+end
function camera:move(dx,dy)^ top
camera.x,camera.y = new_x,new_y
.camera.x,camera.y = camera.x+dx, camera.y+dy
.dx,dy
function love.update(dt)
camera:move(dt * 5, dt * 6):rotate(dt)
-end
function camera:attach()^ top
camera:detach()
as if looking through the camera.function love.draw()
+end
function camera:attach()^ top
camera:detach()
as if looking through the camera.function love.draw()
camera:attach()
draw_world()
cam:detach()
draw_hud()
-end
function camera:detach()^ top
function love.draw()
+end
function camera:detach()^ top
function love.draw()
camera:attach()
draw_world()
cam:detach()
draw_hud()
-end
function camera:draw(func)^ top
camera:attach()
/camera:detach()
pair:
- cam:attach()
-func()
-cam:detach()
func
function love.draw()
+end
function camera:draw(func)^ top
camera:attach()
/camera:detach()
pair: cam:attach()func()cam:detach()
func
function love.draw()
camera:draw(draw_world)
draw_hud()
-end
function camera:worldCoords(v)^ top
function camera:worldCoords(x, y)^ top
function camera:cameraCoords(v)^ top
function camera:cameraCoords(x, y)^ top
v
x, y
target = camera:worldCoords( vector(love.mouse.getPosition()) )
-selectedUnit:plotPath(target)
-
pos = cam:toCameraCoords(player.pos)
-love.graphics.line(pos.x, pos.y, love.mouse.getPosition())
-
function camera:mousepos()^ top
camera:worldCoords(vector(love.mouse.getPosition()))
.target = camera:mousepos()
-selectedUnit:plotPath(target)
-
hump.ringbuffer^ top
A ring-buffer is a circular array: It does not have a first nor a last item,
- but it has a selected or current element.hump.ringbuffer = require "Ringbuffer"
Module overview
function new(...)^ top
...
Ringbuffer = require 'hump.ringbuffer'
+end
function camera:worldCoords(x, y)^ top
function camera:cameraCoords(x, y)^ top
x, y
x,y = camera:worldCoords(love.mouse.getPosition())
+selectedUnit:plotPath(x,y)
+
x,y = cam:toCameraCoords(player.pos)
+love.graphics.line(x, y, love.mouse.getPosition())
+
function camera:mousepos()^ top
camera:worldCoords(vector(love.mouse.getPosition()))
.x,y = camera:mousepos()
+selectedUnit:plotPath(x,y)
+
hump.ringbuffer^ top
Ringbuffer = require "hump.ringbuffer"
Module overview
function new(...)^ top
...
Ringbuffer = require 'hump.ringbuffer'
rb = ringbuffer(1,2,3)
-
function ringbuffer:insert(...)^ top
...
rb = RingbuffeR(1,5,6) -- content: 1,5,6
+
function ringbuffer:insert(...)^ top
...
rb = RingbuffeR(1,5,6) -- content: 1,5,6
rb:insert(2,3,4) -- content: 1,2,3,4,5,6
-
function ringbuffer:remove()^ top
rb = Ringbuffer(1,2,3,4) -- content: 1,2,3,4
+
function ringbuffer:remove()^ top
rb = Ringbuffer(1,2,3,4) -- content: 1,2,3,4
val = rb:remove() -- content: 2,3,4
-print(val) -- prints `1'
-
function ringbuffer:removeAt(pos)^ top
pos
rb = Ringbuffer(1,2,3,4,5) -- content: 1,2,3,4,5
+print(val) -- prints `1'
+
function ringbuffer:removeAt(pos)^ top
pos
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 ringbuffer:next()^ top
rb = Ringbuffer(1,2,3)
+
function ringbuffer:next()^ top
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 ringbuffer:prev()^ top
rb = Ringbuffer(1,2,3)
+print(x) -- prints `1'
+
function ringbuffer:prev()^ top
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 ringbuffer:get()^ top
rb = Ringbuffer(1,2,3)
+print(x) -- prints `1'
+
function ringbuffer:get()^ top
rb = Ringbuffer(1,2,3)
rb:next() -- content: 2,3,1
-print(rb:get()) -- prints '2'
-
function ringbuffer:size()^ top
rb = Ringbuffer(1,2,3)
-print(rb:size()) -- prints '3'
+print(rb:get()) -- prints '2'
+
function ringbuffer:size()^ top
rb = Ringbuffer(1,2,3)
+print(rb:size()) -- prints '3'
rb:remove()
-print(rb:size()) -- prints '2'
-
License^ top
-
- Download^ top
- git clone git://github.com/vrld/hump
- Once done, tou can check for updates by running
- git pull
- License^ top
Download^ top
'..rest..'
' end
+ if cmd == '%' then return ''..rest..'
' end
+ if cmd == '*' then return ''..rest..'' end
+ if cmd == '!' then return ''..rest..'' end
+ return m
+ end)
+end
+
+
+-- PREPARE DOCUMENTATION MARKUP
+local DOC = { short = {}, long = {} }
+
+function Module(M)
+ for _,field in ipairs{'name', 'title', 'short', 'long'} do
+ assert(M[field], "Module: Required field `"..field.."' is missing")
+ end
+
+ DOC.short[#DOC.short+1] = ('%s = require "%s"
', M.title:gsub("^(%w+)%W.+", "%1"), M.name)
+ F(markup(M.long))
+ F('')
+ F(M.example[i])
+ F('
')
+ end
+ F('%s
')
+ F(M.example[i])
+ F('
')
+ end
+ F('Helper Utilities for a Multitude of Problems is a set of lightweight helpers for the awesome LÖVE Engine.
It features
hump differs from other libraries in that every component is independent of the remaining ones (apart from camera.lua, which does depends on vector.lua). hump's footprint is very small and thus should fit nicely into your projects.
Yay, free software:
Copyright (c) 2010 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.