updated demo to beholder 2.0.0

This commit is contained in:
Enrique García Cota 2012-01-29 14:21:59 +01:00
parent 333b25c40c
commit 7095da9ed1
3 changed files with 66 additions and 70 deletions

Binary file not shown.

View File

@ -1,4 +1,4 @@
-- beholder.lua - v1.0.1 (2011-11) -- beholder.lua - v2.0.0 (2011-11)
-- Copyright (c) 2011 Enrique García Cota -- Copyright (c) 2011 Enrique García Cota
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
@ -13,33 +13,36 @@ end
-- private Node class -- private Node class
local Node = { local nodesById = nil
_nodesById = setmetatable({}, {__mode="k"}) local root = nil
}
function Node:new() local function newNode()
local node = { callbacks = {}, children = setmetatable({}, {__mode="k"}) } return { callbacks = {}, children = setmetatable({}, {__mode="k"}) }
return setmetatable( node, { __index = Node } )
end end
function Node:findById(id) local function initialize()
return self._nodesById[id] root = newNode()
nodesById = setmetatable({}, {__mode="k"})
end end
function Node:findOrCreateChild(key) local function findNodeById(id)
self.children[key] = self.children[key] or Node:new() return nodesById[id]
end
local function findOrCreateChildNode(self, key)
self.children[key] = self.children[key] or newNode()
return self.children[key] return self.children[key]
end end
function Node:findOrCreateDescendant(keys) local function findOrCreateDescendantNode(self, keys)
local node = self local node = self
for i=1, #keys do for i=1, #keys do
node = node:findOrCreateChild(keys[i]) node = findOrCreateChildNode(node, keys[i])
end end
return node return node
end end
function Node:invokeCallbacks(params) local function invokeNodeCallbacks(self, params)
local counter = 0 local counter = 0
for _,callback in pairs(self.callbacks) do for _,callback in pairs(self.callbacks) do
callback(unpack(params)) callback(unpack(params))
@ -48,94 +51,87 @@ function Node:invokeCallbacks(params)
return counter return counter
end end
function Node:invokeAllCallbacksInSubTree(params) local function invokeAllNodeCallbacksInSubTree(self, params)
local counter = self:invokeCallbacks(params) local counter = invokeNodeCallbacks(self, params)
for _,child in pairs(self.children) do for _,child in pairs(self.children) do
counter = counter + child:invokeAllCallbacksInSubTree(params) counter = counter + invokeAllNodeCallbacksInSubTree(child, params)
end end
return counter return counter
end end
function Node:invokeCallbacksFromPath(path) local function invokeNodeCallbacksFromPath(self, path)
local node = self local node = self
local params = copy(path) local params = copy(path)
local counter = node:invokeCallbacks(params) local counter = invokeNodeCallbacks(node, params)
for i=1, #path do for i=1, #path do
node = node.children[path[i]] node = node.children[path[i]]
if not node then break end if not node then break end
table.remove(params, 1) table.remove(params, 1)
counter = counter + node:invokeCallbacks(params) counter = counter + invokeNodeCallbacks(node, params)
end end
return counter return counter
end end
function Node:addCallback(callback) local function addCallbackToNode(self, callback)
local id = {} local id = {}
self.callbacks[id] = callback self.callbacks[id] = callback
Node._nodesById[id] = self nodesById[id] = self
return id return id
end end
function Node:removeCallback(id) local function removeCallbackFromNode(self, id)
self.callbacks[id] = nil self.callbacks[id] = nil
Node._nodesById[id] = nil nodesById[id] = nil
end end
------ beholder table
local beholder = {}
-- beholder private functions -- beholder private functions
local function falseIfZero(n) local function falseIfZero(n)
return n > 0 and n return n > 0 and n
end end
local function checkSelf(self, methodName)
assert(type(self)=="table" and self._root, "Use beholder:" .. methodName .. " instead of beholder." .. methodName)
end
local function extractEventAndCallbackFromParams(params) local function extractEventAndCallbackFromParams(params)
assert(#params > 0, "beholder:observe requires at least one parameter - the callback. You usually want to use two, i.e.: beholder:observe('EVENT', callback)") assert(#params > 0, "beholder.observe requires at least one parameter - the callback. You usually want to use two, i.e.: beholder.observe('EVENT', callback)")
local callback = table.remove(params, #params) local callback = table.remove(params, #params)
return params, callback return params, callback
end end
local function initialize(self)
self._root = Node:new()
end
------ Public interface ------ Public interface
local beholder = {} function beholder.observe(...)
function beholder:observe(...)
checkSelf(self, 'observe')
local event, callback = extractEventAndCallbackFromParams({...}) local event, callback = extractEventAndCallbackFromParams({...})
return self._root:findOrCreateDescendant(event):addCallback(callback) local node = findOrCreateDescendantNode(root, event)
return addCallbackToNode(node, callback)
end end
function beholder:stopObserving(id) function beholder.stopObserving(id)
checkSelf(self, 'stopObserving') local node = findNodeById(id)
local node = Node:findById(id)
if not node then return false end if not node then return false end
node:removeCallback(id) removeCallbackFromNode(node, id)
return true return true
end end
function beholder:trigger(...) function beholder.trigger(...)
checkSelf(self, 'trigger') return falseIfZero( invokeNodeCallbacksFromPath(root, {...}) )
return falseIfZero( self._root:invokeCallbacksFromPath({...}) )
end end
function beholder:triggerAll(...) function beholder.triggerAll(...)
checkSelf(self, 'triggerAll') return falseIfZero( invokeAllNodeCallbacksInSubTree(root, {...}) )
return falseIfZero( self._root:invokeAllCallbacksInSubTree({...}) )
end end
function beholder:reset() function beholder.reset()
checkSelf(self, 'reset') initialize()
initialize(self)
end end
initialize(beholder) initialize()
return beholder return beholder

View File

@ -44,8 +44,8 @@ function checkCollision(a,b)
local ax1, ay1, ax2, ay2 = a.x, a.y, a.x+16, a.y+16 local ax1, ay1, ax2, ay2 = a.x, a.y, a.x+16, a.y+16
local bx1, by1, bx2, by2 = b.x, b.y, b.x+16, b.y+16 local bx1, by1, bx2, by2 = b.x, b.y, b.x+16, b.y+16
if ax1 < bx2 and ax2 > bx1 and ay1 < by2 and ay2 > by1 then if ax1 < bx2 and ax2 > bx1 and ay1 < by2 and ay2 > by1 then
beholder:trigger("COLLISION", a, b) beholder.trigger("COLLISION", a, b)
beholder:trigger("COLLISION", b, a) beholder.trigger("COLLISION", b, a)
end end
end end
@ -91,7 +91,7 @@ end
function gameOver() function gameOver()
print("braains") print("braains")
beholder:reset() beholder.reset()
love.event.push('q') love.event.push('q')
end end
@ -107,12 +107,12 @@ function createPlayer()
} }
setmetatable(player, {__tostring = function(t) return 'player' end}) setmetatable(player, {__tostring = function(t) return 'player' end})
for dir,_ in pairs(directions) do for dir,_ in pairs(directions) do
beholder:observe("KEYPRESSED", dir, function() startMoving(player, dir) end) beholder.observe("KEYPRESSED", dir, function() startMoving(player, dir) end)
beholder:observe("KEYRELEASED", dir, function() stopMoving(player, dir) end) beholder.observe("KEYRELEASED", dir, function() stopMoving(player, dir) end)
end end
beholder:observe("KEYPRESSED", " ", activateMine) beholder.observe("KEYPRESSED", " ", activateMine)
beholder:observe("COLLISION", player, gameOver) beholder.observe("COLLISION", player, gameOver)
table.insert(entities, player) table.insert(entities, player)
end end
@ -141,12 +141,12 @@ function createMine()
} }
setmetatable(mine, {__tostring = function(t) return 'mine' end}) setmetatable(mine, {__tostring = function(t) return 'mine' end})
beholder:observe("COLLISION", mine, function(zombie) beholder.observe("COLLISION", mine, function(zombie)
if not mine.exploded then if not mine.exploded then
mine.exploded = true mine.exploded = true
mine.color = {50,50,50} mine.color = {50,50,50}
zombie.dead = true zombie.dead = true
beholder:trigger("KILLED", zombie) beholder.trigger("KILLED", zombie)
end end
end) end)
@ -177,11 +177,11 @@ function love.draw()
end end
function love.keypressed(key) function love.keypressed(key)
beholder:trigger("KEYPRESSED", key) beholder.trigger("KEYPRESSED", key)
end end
function love.keyreleased(key) function love.keyreleased(key)
beholder:trigger("KEYRELEASED", key) beholder.trigger("KEYRELEASED", key)
end end
function love.load() function love.load()
@ -196,34 +196,34 @@ function love.load()
createZombie() createZombie()
end end
beholder:observe(print) -- print every event on the terminal beholder.observe(print) -- print every event on the terminal
-- prints the last pressed key on the screen -- prints the last pressed key on the screen
lastPressedKey = "<none yet>" lastPressedKey = "<none yet>"
beholder:observe("KEYPRESSED", function(key) beholder.observe("KEYPRESSED", function(key)
lastPressedKey = key lastPressedKey = key
end) end)
-- binds escape to the gameOver function (quit game) -- binds escape to the gameOver function (quit game)
beholder:observe("KEYPRESSED", "escape", gameOver) beholder.observe("KEYPRESSED", "escape", gameOver)
-- handle pause -- handle pause
beholder:observe("KEYPRESSED", "pause", function() beholder.observe("KEYPRESSED", "pause", function()
all(entities, pause) all(entities, pause)
local id local id
id = beholder:observe("KEYPRESSED", function() id = beholder.observe("KEYPRESSED", function()
all(entities, unpause) all(entities, unpause)
beholder:stopObserving(id) beholder.stopObserving(id)
end) end)
end) end)
-- victor is triggered if enough kills are done -- victor is triggered if enough kills are done
beholder:observe("KILLED", function() beholder.observe("KILLED", function()
killCount = killCount + 1 killCount = killCount + 1
if killCount == zombieCount then if killCount == zombieCount then
print("You win!") print("You win!")
beholder:reset() beholder.reset()
love.event.push('q') love.event.push('q')
end end
end) end)