Pölygamy: a collection of LÖVE helper libraries

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
pygy
Citizen
Posts: 98
Joined: Mon Jan 25, 2010 4:06 pm

Pölygamy: a collection of LÖVE helper libraries

Post by pygy »

Current version : 0.4.1 (for LÖVE 0.6.1, it should also work with 0.6.0)
Polygamy041.love
(13.69 KiB) Downloaded 899 times
Pölygamy is a collection of LÖVE helper libraries designed to help you simplify your (or at least my) code base.

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.
Polygamy.state
  • 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)
Please note that Pölygamy requires to use the bundled love.run() loop.

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
for convenience:

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
})
then get the ball rolling :-)

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 keys take either a function object or a table as parameter. When a function is passed, it is assigned to the default action for this definition (in this case "held", specified as the first parameter). "pressed", "held" and "released" are valid action values.

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" )
Inheritance works as follows:

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.
When a key is pressed, Polygamy looks for the key in the active table, then in the (grand-)parents tables. If it isn't found, Polygamy looks for the [Polygamy.default] key in the active table, then along the inheritance chain.

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.
}
Use Polygamy.Tools.nop (an empty function) if you want to shadow the action of a parent.

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 :megagrin:.
  • [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).
v0.3 (2010/02/02)
  • /!\ 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.
v0.2 (2010/01/28)
  • Complete rewrite of Polygamy.keyboard.
  • New API
  • Extensive documentation
v0.1: (2010/01/25)
  • initial release of Polygamy.keyboard.
[/size]

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
[/size]
Last edited by pygy on Wed Jul 21, 2010 9:02 am, edited 66 times in total.
Hermaphroditism is not a crime. -- LSB Superstar

All code published with this account is licensed under the Romantic WTF public license unless otherwise stated.
Geti
Party member
Posts: 112
Joined: Tue Oct 20, 2009 6:38 am

Re: Small keyboard input library: Request for feedback.

Post by Geti »

I need to read through it more, but it looks promising. If it can save me some time, I might use it, I'll look into it more later.
User avatar
pygy
Citizen
Posts: 98
Joined: Mon Jan 25, 2010 4:06 pm

Re: Small keyboard input library: Request for feedback.

Post by pygy »

I'm actually thinking of reversing the exposed table hierarchy to

Code: Select all

PoG.default={}
PoG.K.addPartner("ingame", {
	key = {
		pressed=function() ... end,
		released=...
	},
	key = ...,
	[PoG.default] = ... -- default behaviour
}
It makes more sense from a code organisation perspective. It would be transformed to the previous representation for internal use.
Hermaphroditism is not a crime. -- LSB Superstar

All code published with this account is licensed under the Romantic WTF public license unless otherwise stated.
User avatar
pygy
Citizen
Posts: 98
Joined: Mon Jan 25, 2010 4:06 pm

Re: Pölygamy: a collection of LÖVE helper libraries

Post by pygy »

Polygamy.keyboard v0.2, with extensive documentation has been added to the first post.
Hermaphroditism is not a crime. -- LSB Superstar

All code published with this account is licensed under the Romantic WTF public license unless otherwise stated.
iza
Prole
Posts: 10
Joined: Sat Jul 11, 2009 7:16 pm

Re: Pölygamy: a collection of LÖVE helper libraries

Post by iza »

Haha I love the name.
Geti
Party member
Posts: 112
Joined: Tue Oct 20, 2009 6:38 am

Re: Pölygamy: a collection of LÖVE helper libraries

Post by Geti »

looks damn nice. will test out as soon as i need keyboard input in more than one situation. would it be possible for you to upload the compiled "lib" as it were? for the lazies like me out here :)
User avatar
pygy
Citizen
Posts: 98
Joined: Mon Jan 25, 2010 4:06 pm

Re: Pölygamy: a collection of LÖVE helper libraries

Post by pygy »

Thanks,

I'll debug it first, it's absolutely untested as it is and I'm too tired to do that now.

What do you mean by "bundled"? as a .lua, or as a .love file?
What would be the point of distributing .love files for libraries that will be extracted anyway?
Hermaphroditism is not a crime. -- LSB Superstar

All code published with this account is licensed under the Romantic WTF public license unless otherwise stated.
Geti
Party member
Posts: 112
Joined: Tue Oct 20, 2009 6:38 am

Re: Pölygamy: a collection of LÖVE helper libraries

Post by Geti »

i mean compiled bytecode, from luac.
http://www.lua.org/manual/4.0/luac.html
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Pölygamy: a collection of LÖVE helper libraries

Post by bartbes »

Why bytecode?
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Pölygamy: a collection of LÖVE helper libraries

Post by Robin »

Geti wrote:looks damn nice. will test out as soon as i need keyboard input in more than one situation. would it be possible for you to upload the compiled "lib" as it were? for the lazies like me out here :)
The whole point of Lua is that you don't have to compile it to make it work.
Help us help you: attach a .love.
Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests