|Pedro Gimeno 9d078dbe39 Adjustments to README||9 months ago|
|.gitignore||10 months ago|
|8queens.lua||10 months ago|
|Nqueens.lua||10 months ago|
|README.md||9 months ago|
|conf.lua||10 months ago|
|main.lua||10 months ago|
|queen-black-40x40.png||10 months ago|
|queen-black-64x64.png||10 months ago|
This is a Löve program that allows you to use the Löve framework, but instead of using event callbacks, you poll the events via function calls.
It requires a love2d version from 0.9 up.
It was inspired by forum member Neku, who was used to PyGame and had trouble with event-oriented programming when applied to the visualization of the algorithms he wrote for solving certain tasks.
And that's indeed the main application of this library: algorithm visualization. Even if you're deep in nested loops or recursion levels, calling
sleep() will update your display thanks to the magic of coroutines.
A lot of inspiration for this version also came from the TimelineEvents library by Babulous, regarding the design and implementation of the whole event set instead of just a very limited set of functions and events.
Just place your code in the file
mycode.lua. Alternatively, you can call love2d with the name of the Lua file to run; for example, invoking
love . 8queens.lua from the directory where this repository is, will execute
A window is NOT automatically created; your code needs to call
love.graphics.setMode first before calling any window functions.
Most Löve functions can be called directly. Note that there's an underlying canvas used as the framebuffer in which your graphics are rendered, therefore using
love.graphics.setCanvas() may result in unintended consequences. This framebuffer canvas is available via a global variable called
love.event.pump have been patched to work properly with this canvas, but other functions may not work as intended; let me know in case of problems so I can add a workaround.
NOTE: Redefining love2d events can have unintended consequences.
In addition to Löve functions, there are several additional global functions:
sleep(t): Stops execution of your script during the given amount of time. Any events that happened during the sleep period are lost.
pause(t): Similar to
sleep, but if the user presses any key or a mouse button, it will return before the time expires, and if the user presses ESC, the program will be immediately closed.
wait.<eventname>(): This is actually a table with functions. For each Löve event, there is a corresponding function in this table. The function will stop execution of your script until the corresponding event is triggered, and then it will return whatever the arguments were for that event. These functions don't take any arguments.
wait.keypressed()will wait until the
keypressedevent is triggered, and will return the
isRepeatvalues that are the arguments of love.keypressed.
peek: Another table with functions. Similar to
waitbut this one will return nothing instead of blocking your script, and will return the boolean
truefollowed by the event's arguments if the current event is that one. Note, however, that calling a
peekfunction will not advance to the next event; you need to call a function that does so yourself. For example, if you call
peek.inside a loop without calling an event advancing function such as
wait.<something>(), and your loop depends on some event in order to be interrupted, your program will hang indefinitely.
peekcontain another function called
event. You can pass the name of an event to this function, and it will do the same as the function with the name of that event. Internally, every other function in the table calls this function. For example,
wait.event("keypressed")do the same. Note that the functions
peek.event()should not be confused with the global function
poll()advances to the next event.
poll()but it also returns the event name and its parameters. For example, if the next event to trigger is
keypressed, and you call
event(), it will return a tuple of the form
"keypressed", key, scancode, isRepeat.
timer(seconds)allows you to set a timer that will expire after the given number of seconds have passed (with 1 frame granularity) and generate the
quit()immediately quits the program. It's a shortcut for
love.event.quit(); wait.quit(); poll().
In addition to the normal Löve events, there are three more events:
newframe- Triggered at the start of a new frame. No parameters.
timer- Triggered when
timer()expires. No parameters.
sleep- Generated internally by the
The functions that advance events all accept return parameters for the current event. The actual signatures are:
void sleep(t, ...)[*]
void pause(t, ...)[*]
void wait.event(eventname, ...)[*]
The functions marked with [*] may skip more than one event. In that case, the return value only applies to the first event.
Note that as of this writing, only the
quit event handles a return value.
draw event is called after drawing the framebuffer, but before the frame is displayed. This allows you to draw to the screen directly rather to the framebuffer, as long as you unset the canvas first with
love.graphics.setCanvas(). Remember to restore the framebuffer if necessary by calling
Here's one example of the use of the
love.window.setMode(800, 600) timer(3) love.graphics.print("** Background", 0, 8) -- drawn to the framebuffer repeat poll() if peek.draw() then -- We're in the draw event love.graphics.setCanvas() -- Unset the canvas -- This text overlaps the background temporarily: love.graphics.print("I appear for 3 seconds", 30, 0) love.graphics.setCanvas(fbcanvas) -- Restore the framebuffer end until peek.timer() -- keep looping until the timer expires love.graphics.print("Done", 0, 40) -- drawn to the framebuffer again pause() quit()
print("We're at the top level") wait.load() -- Wait for love.load() to trigger print("Now we're inside love.load") local dt = wait.update() -- Wait for love.update() to trigger print("Now we're inside love.update(), dt is " .. dt) love.event.quit() -- Send quit event wait.quit() -- Wait for love.quit() to trigger print("Now we're inside love.quit(), but we don't want to quit") poll(true) -- Return true to love.quit, thus blocking the quit print("See? We're still here"); love.event.quit() -- Send quit event again wait.quit() -- Wait for love.quit() once more print("Now we're inside love.quit() again, but this time we're quitting") poll() -- Return nothing to love.quit; this allows it to really quit print("You can't see this!") -- Program has terminated; this isn't reached
The example file
8queens.lua is a program to solve the Eight Queens problem by brute force, with visualization of the intermediate positions and solutions found, using eight nested loops for demonstration purposes. An event-oriented version of this program would need to progress in small increments, making it less trivial to make than this straightforward version.
The example file
Nqueens.lua is similar, but it implements a simple input function (with no cursor movement) to specify the number of queens, then solves the problem for any given number of queens from 4 to 16 instead of being fixed to 8. This variant is recursive and does N nested recursive calls.
Every file in this repository, including the images, is donated to the public domain or, if your jurisdiction does not contemplate donating things to the public domain, you have my permission to do anything you want with the files to the maximum extent permitted by law.