diff --git a/doc.lua b/doc.lua index bd2f07e..43a0678 100644 --- a/doc.lua +++ b/doc.lua @@ -233,7 +233,7 @@ Module { name = "hump.timer", {"function", "func", "The function to be delayed."}, }, returns = { - {"function", "The timer handle."} + {"table", "The timer handle."} }, example = { [===[ @@ -261,7 +261,7 @@ Timer.add(1, function(func) print("foo") Timer.add(1, func) end)]===], {"number", "count", "Number of times the function is to be called.", optional = true}, }, returns = { - {"function", "The timer handle."} + {"table", "The timer handle."} }, example = { "Timer.addPeriodic(1, function() lamp:toggleLight() end)", @@ -274,6 +274,39 @@ end)]===], }, }, + 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 = { + [===[Timer.do_for(3, function() screen:shake() end)]===], + [===[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() + player.visible = true -- make sure the player is visible after three seconds + player.isInvincible = false +end)]===] + }, + }, + Function { name = {"cancel", "instance:cancel"}, short = "Cancel a scheduled function.", long = [===[ @@ -284,7 +317,7 @@ end)]===], {*Never} use this inside a scheduled function.]===], params = { - {"function", "func", "The function to be canceled."}, + {"table", "handle", "The function to be canceled."}, }, returns = {}, example = { @@ -320,75 +353,6 @@ Timer.cancel(handle) -- NOT: Timer.cancel(tick)]===] function love.update(dt) do_stuff() Timer.update(dt) -end]===], - }, - - Function { name = "Interpolator", - short = "Create a new interpolating function.", - long = [===[ - 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: - [%function wrapper(dt, ...)] - where {#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. - - The prototype of the interpolating function is: - [%function interpolator(fraction, ...)] - where {#fraction} is a number between 0 and 1 depending on how much - time has passed and {#...} are additional arguments supplied to the - wrapper.]===], - params = { - {"number", "length", "Interpolation length in seconds."}, - {"function", "func", "Interpolating function."}, - }, - returns = { - {"function", "The wrapper function."} - }, - example = [===[ -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 { name = "Oscillator", - short = "Create a new oscillating function.", - long = [===[ - Create a wrapper for an oscillating function, which is basically a - looping interpolating function. - - The function prototypes are the same as with {#Interpolator()}: - [%function wrapper(dt, ...)] - [%function oscillator(fraction, ...)] - - As with {#Interpolator}, the wrapper will return whatever - {#oscillator()} returns.]===], - params = { - {"number", "length", "Length of one interpolation period."}, - {"function", "func", "Oscillating function."}, - }, - returns = { - {"function", "The wrapper function."} - }, - example = [===[ -mover = Timer.Oscillator(10, function(frac) - return 400 + 300 * math.sin(2*math.pi*frac) -end) - -local xpos = 100 -function love.update(dt) - xpos = mover(dt) -end - -function love.draw() - love.graphics.circle('fill', xpos, 300, 80, 36) end]===], }, } diff --git a/index.html b/index.html index 8a1425b..b168a50 100644 --- a/index.html +++ b/index.html @@ -56,14 +56,23 @@ end
Note: Only works when called end
function love.load()
Gamestate.registerEvents{'draw', 'update', 'quit'}
Gamestate.switch(menu)
-end
Timer = require "hump.timer"
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.
If you don't need multiple independent schedulers, you can use the global/default timer (see examples).
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.
Note: Timer instances use the colon-notation (e.g. instance:update(dt)
), while the global timer uses the dot-notation (e.g. Timer.update(dt)
).
menuTimer = Timer.new()
Schedule a function. The function will be executed after delay
seconds have elapsed, given that update(dt)
is called every frame.
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.
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
Timer = require "hump.timer"
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.
If you don't need multiple independent schedulers, you can use the global/default timer (see examples).
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.
Note: Timer instances use the colon-notation (e.g. instance:update(dt)
), while the global timer uses the dot-notation (e.g. Timer.update(dt)
).
menuTimer = Timer.new()
Schedule a function. The function will be executed after delay
seconds have elapsed, given that update(dt)
is called every frame.
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.
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)
menuTimer:add(1, finishAnimation)
Add a function that will be called count
times every delay
seconds.
If 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)
mothership_timer:addPeriodic(0.3, function() self:spawnFighter() end, 5)
-- flicker player's image as long as he is invincible
+Timer.add(1, function(func) print("foo") Timer.add(1, func) end)
menuTimer:add(1, finishAnimation)
Add a function that will be called count
times every delay
seconds.
If 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)
mothership_timer:addPeriodic(0.3, function() self:spawnFighter() end, 5)
-- flicker player's image as long as he is invincible
Timer.addPeriodic(0.1, function()
player:flipImage()
return player.isInvincible
-end)
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 inside a scheduled function.
func
function tick()
+end)
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.
delta
func
will be called.func
update(dt)
.after
(optional)delta
seconds.Timer.do_for(3, function() screen:shake() end)
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()
+ player.visible = true -- make sure the player is visible after three seconds
+ player.isInvincible = false
+end)
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 inside a scheduled function.
handle
function tick()
print('tick... tock...')
end
handle = Timer.addPeriodic(1, tick)
@@ -71,23 +80,6 @@ handle = Timer.addPeriodic(1, tick)
Timer.cancel(handle) -- NOT: Timer.cancel(tick)
Remove all timed and periodic functions. Functions that have not yet been executed will discarded. Never use this inside a scheduled function.
Timer.clear()
Update timers and execute functions if the deadline is reached. Use this in love.update(dt)
.
dt
function love.update(dt)
do_stuff()
Timer.update(dt)
-end
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:
function wrapper(dt, ...)
where 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.The prototype of the interpolating function is:
function interpolator(fraction, ...)
where 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
Create a wrapper for an oscillating function, which is basically a looping interpolating function.
The function prototypes are the same as with Interpolator()
:
function wrapper(dt, ...)
function oscillator(fraction, ...)
As with Interpolator
, the wrapper will return whatever oscillator()
returns.
length
func
mover = Timer.Oscillator(10, function(frac)
- return 400 + 300 * math.sin(2*math.pi*frac)
-end)
-
-local xpos = 100
-function love.update(dt)
- xpos = mover(dt)
-end
-
-function love.draw()
- love.graphics.circle('fill', xpos, 300, 80, 36)
end
vector = require "hump.vector"
A handy 2D vector class providing most of the things you do with vectors.
You can access the individual coordinates by using vec.x
and vec.y
.
Vector arithmetic is implemented by using __add
, __mul
and other metamethods:
vector + vector = vector
vector - vector = vector
vector * vector = number
number * vector = vector
vector * number = vector
vector / number = vector
Relational operators are defined, too:
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