It allows to define different configurations for different phases of a game (menu, in game, pause screen, etc...), and to define related things in one place.
Polygamy.keyboard and Polygamy.state are now available (see the release notes at the end of this post for the details), and Polygamy.timer is in the works (supporting multiple timelines and the ability to pause, stop and delete repetitive timers).
Polygamy.keyboard
- allows to bind keys to callbacks in a declarative fashion,
- supports multiple, switchable configurations
- supports configuration (single) inheritance.
- supports useful ranges ([f-j] is expanded to f, g, h, j) and other patterns inspired by the Lua patterns library.
- allows to treat the keyboard as a key matrix (full support for US qwerty keyboards only at the moment, but the common subset of qwerty, azerty and qwertz can be used universally (sorry, dvorak users))
- is freindly with both imperative and OO coding styles.
- allows to design each game state as if it were a full LÖVE app (custom update and draw callbacks),
- supports state transitions (through before( from, to, ... ) and after( from, to, ... ) callbacks)
TOC:
- A dummy game using Pölygamy.
- Polygamy.keyboard tutorial
- Polygamy.keyboard API reference
- Polygamy.state API reference
- Change Log
- TODO
- the polygamy.love 0.4.0 file
A dummy game using Pölygamy:
Code: Select all
require "path.to.Polygamy.init" -- must be outside the load callback.
-- since it creates a custom love.run loop
Code: Select all
local state, goto, pkeyboard = Polygamy.state, Polygamy.state.goto, Polygamy.keyboard
-- Load your ressources, initialize your code... then :
Code: Select all
title = state( "Title Screen" )
--============--
function title.before() pkeyboard.use( "title" ); print"menu" end
function title.update(dt) --[[ your title update callback ]] end
function title.draw() --[[ draw your fine title here ]] end
pkeyboard( "title" ):setConfig( "pressed", {
[{" ", "return"}] = function() goto("In Game") end,
escape = function() love.event.push('q') end,
})
Code: Select all
ingame = state( "In Game" )
--=======--
function ingame.before( from, to, ... )
if from == "Title Screen" then --[[Game.state.reset()]] end
Polygamy.timer:resume()
pkeyboard.use( to ) -- to == "In game" in this case
print "In Game"
end
function ingame.update( dt ) --[[ instill life in your game world ]] end
function ingame.draw() --[[ and render it in its full glory ]] end
Code: Select all
function ingame.after( from, to, ... )
Polygamy.timer:pause()
if to == "Pause Screen" then
-- dim the screen, take a screenshot
end
end
Code: Select all
pkeyboard("In Game"):setConfig("pressed", {
[" %arrows "] = { held = function(key,_,_,dt) Hero:move(key,dt); end },
[" "] = function() Hero:shoot() end,
escape = function() goto( "Title Screen" ) end,
p = function() goto( "Pause Screen" ) end
})
Code: Select all
pause = state( "Pause Screen" )
--============--
function pause.before() pkeyboard.use( "pause" ); print"Pause" end
function pause.update(dt) end -- if you don't define it, the previous callback remains active.
function pause.draw() --[[ display "Paused" on top of the screenshot.]] end
pkeyboard( "pause" ):setConfig( "pressed", {
escape = function() goto( "Title Screen" ) end,
p = function() goto( "In Game" ) end
})
Code: Select all
function love.load()
goto("Title Screen")
print"Start"
end
Polygamy.keyboard tutorial:
Here's a basic keyboard configuration:
Code: Select all
Polygamy.keyboard("ingame"):setconfig( "held", {
left = function(dt) hero.position=hero.position - dt * 10 end,
right = function(dt) hero.position=hero.position + dt * 10 end,
up = hero.jump
[" "] = {
pressed = hero.shoot,
held = hero.accumulateEnergy,
released = hero.unleashDevastativeBlow
},
esc = {pressed = game.pause},
[Polygamy.default] = function(key) menu.type(key) end -- useful if the current field is a text field.
} )
The special [Polygamy.default] entry is passed every key not explicity assigned.
You can activate a configuration with:
Code: Select all
Polygamy.keyboard.use( "configuration handle" )
Code: Select all
Polygamy.keyboard("the Lost Vikings, in game"):setConfig( "pressed", { esc = pause } )
for _, viking in ipairs[ olaf, eric, baleog ] do
Polygamy.keyboard( viking ):setConfig("held", { -- You can use any type of object as a configuration name.
[ "%arrows" ] = viking.move -- expanded to "up", "down", "left" and "right"
-- these strings are passed to viking.move
[" "] = viking.action
})
Polygamy(viking):setParent("the Lost Vikings, in game")
end
Polygamy.keyboard.use( olaf ) -- the keys move Olaf, esc pauses the game
Polygamy.keyboard.use( erik ) -- now Erik is active, and esc still works.
You can modify an existing configuration by using keyboardObject:ssetConfig(<string> defaultAction, <table> actions), The default action only applies to the table assigned at that moment.
See the second page of this thread for the details about the various patterns [%arrows], etc...
The deggenerate case (one configuration, only the default "pressed" and "released" callbacks) implements the basic love.keypressed and .keyreleased callbacks.
Code: Select all
Polygamy.keyboard("default"):setConfig("pressed",{
[Polygamy.delault] = {
pressed = function(key) --[[ your code here ]] end,
released = function(key) --[[ your code here ]] end
}
})
Polygamy.keyboard API:
- Polygamy.keyboard( <any> configName ) => keyboardObject
- returns a keyboard object. Creates a new one if needed. - keyboardObject:setConfig( <string> defaultAction, <table> actions )
- creates or change a keyboard configuration. - keyboardObject:setParent(<any> otherConfigName)
- Polygamy.keyboard.use(<any> configName)
- enables a configuration.
The action table structure is as follows
Code: Select all
{
key = {
pressed = function( key, row, column, unicode ) ... end,
released = function( key, row, column ) ... end,
held = function( key, row, column, dt ) ... end
},
key = function(key, row, column, [ unicode | dt ]) ... end, -- the function is assigned to the default action.
-- "dt" is only relevant if the default mode is "held".
key = "whatever except a function or a table", -- deletes the key.
[Polygamy.default] = any of the above.
}
The Polygamy.state API:
- Polygamy.state( <any> stateName ) => stateObject
- returns a state object. Creates a new one if needed. - Polygamy.state.goto( <any> stateName )
- Schedules the switch to a given state and the Execution of the after() callback of the source state, and the before() callback of the target state. These changes are then handled at a safe point in the main loop. - stateObject.before( <any> from, <any> to, ... )
- stateObject.update( <delta> dt )
- stateObject.draw()
- stateObject.after( <any> from, <any> to, ... )
Change log:
v0.4.1 (2010/02/17)
- First release of Polygamy.state
- Simplification of the Polygamy.keyboard API
- Custom love.run loop with the ability to insert custom callbacks in the main loop
- The modules are loaded on the fly when needed, and their corresponding callbacks are inserted in the main loop automatically.
- Removed the per config typematic support.
- Polygamy.timer is also bundled, but it's untested and certainly buggy
v0.3.1 (2010/02/03)
- First working version published .
- [q-r] => {q, w, e, r} (horizontal). -- [x-5] => {x, d, r, 5} (diagonal) -- [6-h] => {6, y, h} (vertical) -- [f1-f10] => {f1, f2, ... , f10} -- Assumes an US qwerty keyboard at the moment.
- Simplified the callbacks a bit.
- Don't use doto().replaceWith() at the moment if inheritance is involved (known bug).
- /!\ Still not tested (and completely broken)
- TypeMatic (key repeat).
- Unicode.
- Track the active context (to reset options).
- Reset options on doto actions.
- Pattern matching.
- pass key coordinates to all callbacks.
- "Before" blocks.
- Extensive code documentation.
- Complete rewrite of Polygamy.keyboard.
- New API
- Extensive documentation
- initial release of Polygamy.keyboard.
TODO
- Debug Polygamy.timer
- Revamp and simplify the custom love.run loop
- test keyboard and state.makeLove
- Implement inheritance in Polygamy.state, which may require to...
- ... create a custom polyupdate callback instead of overwriting love.update??
- Document Polygamy.nop and how to mask a parent key in a descendant.
- Document the keyboard patterns, the keyboard as a grid and the before keyboard callback.
- Keyboard config serialization to disk.
- ??Learn how to turn Pölygamy into a real Lua 5.1 Module