beholder.lua - event observation in Lua

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

beholder.lua - event observation in Lua

Post by kikito »

Hi there!

I've just released a new lib - it's called beholder.lua.

Github page:

https://github.com/kikito/beholder.lua

This lib basically allows you to handle "events" - it's mostly useful when you have "something important for an entity in your game happenning outside the code of that entity".

The most obvious example is in LÖVE's callbacks. By default, these callbacks force you to put potentially different kinds of code in the same place. The code for handling the player movement is next to the code for showing the exit menu.

With beholder, you do something similar to this:

Code: Select all

beholder = require 'beholder'

...

function love.keypress(key)
  beholder.trigger("KEYPRESS", key)
end
What I've done there is making sure that every time a key is pressed, an "event" is "triggered" (or "fired"). That event will be composed of two parts - the "KEYPRESS" string followed by the key code. This is completely flexible: it could have been a longer or shorter event, containing functions, tables, numbers etc. But for this case, a couple strings will be enough.

Once the triggers are in place, you can "register" to the keyboard events anywhere you want; in your player code, you can move to the left when the left key is pressed like this:

Code: Select all

function movePlayerLeft()
...
end

function createPlayer()
...
  beholder.observe("KEYPRESS", "left", movePlayerLeft)
...
end
And you can handle the "escape" and "pause" keys on the game loading code:

Code: Select all

function love.load()
  ...
  beholder.observe("KEYPRESS", "escape", function() love.event.push('q') end)
  beholder.observe("KEYPRESS", "pause", pauseEverything)
end
Again, don't forget that we have used events composed by two strings here, but beholder can be used to trigger/observe events of any length or kind.

It's also worth noting that the events are inclusive. For example, now it's possible to log all the key presses with this:

Code: Select all

function activateKeyLogger()
  beholder.observe("KEYPRESS", function(key) log("key pressed: ", key) end)
end
Notice that in this case, we were observing a "subset" of the event. Beholder is intelligent enough to convert the rest of the event in parameters, and pass them on to the callbacks of longer events.

Input handling is however just one of the possible examples. Others could be resource loading, network signals, or collisions in the physics system.

I've made a very stupid demo showing some of the uses this lib can have. It shows:
  • An extended version of the "distributed" keyboard handling shown on this post. Includes player movement, esc for exiting and pause key for pausing the action.
  • Collision-related actions are also near their respective objects - the collision detection function just triggers an event.
  • A logic-related event (KILLED) is triggered each time an enemy is killed. That info is used by the love.load function to know when the game is won
Demo instructions:
You are being chased by a group of zombies.
  • Use the movement keys for moving around.
  • Space plants a mine on the ground.
You can't place another mine on the ground until the previous one has been exploded by a zombie.

Zombies kill you. Mines kill them. If they touch you, you are dead. If they touch a mine, they are dead. Make them all touch a mine to win.

The zombies initial position is random. If you die instantaneously after launching the demo, launch it again; I did not check that zombies didn't materialize on top of you right at the start.

This demo prints a lot of info on the console - launching it from the console is recommended.
Beholder is one of the parts of middleclass-extras that I'm re-releasing after releasing middleclass 2.0. However, beholder has now become middleclass-independant. I'm considering creating a "mixing" for tighter middleclass integration, but I'm not sure about that yet. In any case, you can use beholder without touching middleclass (beholder doesn't reference/require middleclass in any way)

I have not used OOP, several files, etc on the demo. This was on purpose (and very difficult for me!). I wanted to make this as accessible to everyone as possible. When (if) I do the middleclass integration, I'll go full OOP on you.

Regards!

Edit: In version 2.0.x you must use the dot instead of colons to invoke beholder methods: beholder.trigger() instead of beholder:trigger() . I've updated this post to show that, and also updated the demo
Attachments
beholder-demo.love
Updated to 2.1.1. Using dt
(4.17 KiB) Downloaded 481 times
Last edited by kikito on Wed Mar 07, 2012 12:27 am, edited 4 times in total.
When I write def I mean function.
User avatar
josefnpat
Inner party member
Posts: 955
Joined: Wed Oct 05, 2011 1:36 am
Location: your basement
Contact:

Re: beholder.lua - event observation in Lua

Post by josefnpat »

This is great!

Your demo works wonderfully :)
Missing Sentinel Software | Twitter

FORCIBLY IGNORED.
<leafo> when in doubt delete all of your code
<bartbes> git rm -r *
<bartbes> git commit -m "Fixed all bugs"
<bartbes> git push
User avatar
adnzzzzZ
Party member
Posts: 305
Joined: Sun Dec 26, 2010 11:04 pm
Location: Porto Alegre, Brazil

Re: beholder.lua - event observation in Lua

Post by adnzzzzZ »

This is very [expletive] useful. I love it. :awesome:
User avatar
thelinx
The Strongest
Posts: 857
Joined: Fri Sep 26, 2008 3:56 pm
Location: Sweden

Re: beholder.lua - event observation in Lua

Post by thelinx »

Looks very interesting. I will probably use it in future projects.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: beholder.lua - event observation in Lua

Post by Robin »

The last zombie didn't die. :(
Help us help you: attach a .love.
User avatar
josefnpat
Inner party member
Posts: 955
Joined: Wed Oct 05, 2011 1:36 am
Location: your basement
Contact:

Re: beholder.lua - event observation in Lua

Post by josefnpat »

Robin wrote:The last zombie didn't die. :(
They pile on top of each other. There's like ten of them by the end in one pile.
Missing Sentinel Software | Twitter

FORCIBLY IGNORED.
<leafo> when in doubt delete all of your code
<bartbes> git rm -r *
<bartbes> git commit -m "Fixed all bugs"
<bartbes> git push
User avatar
hughes
Prole
Posts: 21
Joined: Fri Oct 28, 2011 3:10 am

Re: beholder.lua - event observation in Lua

Post by hughes »

This is awesome, and I love the name. Will definitely try using it in my next project.
User avatar
slime
Solid Snayke
Posts: 3132
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: beholder.lua - event observation in Lua

Post by slime »

Pfft... my own event system is totally s0 much bettar. :P

shameless plug <_< >_>
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: beholder.lua - event observation in Lua

Post by kikito »

Thanks for your kind comments, guys! I hope you find it useful!
slime wrote:Pfft... my own event system is totally s0 much bettar. :P
Yo, my lib has a demo with 1337 graphics, yo. :ultraglee:

Now seriously, one of the things I didn't like about most of the libs I saw is the separation of "event type" and "data". You end up with handles like this:

Code: Select all

function onEvent(event, data)
  if event == "TOUCH" then
     if data.player == player1 then
       doFoo()
     end
  else if event == "BAR" then
     doBar()
  end
end
The previous code has lots of repetitive ifs. The code to know if "player1 has touched a button" reads like this:

Code: Select all

An event happened!
Is it a button touch? (yes)
Get the player from the data structure
Is it player1 the player?(yes)
doFoo()
In beholder, you can remove most of that and concentrate in the essential stuff; This is beholder's equivalent to the code above.

Code: Select all

beholder:observe("TOUCH", player1, doFoo)
beholder:observe("BAR", doBar)
I like it because it reads much more like English; When player1 touches a button, doFoo - If "BAR" happens, doBar.

This "abstraction" puts some extra cycles on the machine, but not many more than the regular approach.

But hey, to each its own :)
When I write def I mean function.
User avatar
slime
Solid Snayke
Posts: 3132
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: beholder.lua - event observation in Lua

Post by slime »

With mine you have three options which can be mixed.
• Register events with a table containing the OnEvent method
• Register events with a table containing methods that are the same name as the events - this gets priority over OnEvent if both are there
• Register events with any function, like yours does
Post Reply

Who is online

Users browsing this forum: No registered users and 3 guests