From 333b25c40c9badc0895b916cdcdfb7467c1b6831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Garc=C3=ADa=20Cota?= Date: Sun, 29 Jan 2012 13:03:33 +0100 Subject: [PATCH] added the demo files --- README.textile | 17 ++++ beholder-demo.love | Bin 0 -> 3497 bytes beholder.lua | 141 +++++++++++++++++++++++++++ love.conf | 3 + main.lua | 233 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 394 insertions(+) create mode 100644 README.textile create mode 100755 beholder-demo.love create mode 100755 beholder.lua create mode 100755 love.conf create mode 100755 main.lua diff --git a/README.textile b/README.textile new file mode 100644 index 0000000..62e598e --- /dev/null +++ b/README.textile @@ -0,0 +1,17 @@ +h1. beholder.lua demo + +This is a demo of the beholder.lua library. It shows how the library can be used to capture and manage different kinds of events. + +The demo requires "LÖVE":http://love2d.org + +h2. Instructions + +* Download and install LÖVE +* Download/uncompress this repo to a folder +* Execute with LÖVE +
+cd folder/where/this/repo/is
+love .
+
+ + diff --git a/beholder-demo.love b/beholder-demo.love new file mode 100755 index 0000000000000000000000000000000000000000..7513b6785b9beca05fc322a6b69021effb51bac3 GIT binary patch literal 3497 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 s=l 0 and n +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) + 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) + return params, callback +end + +local function initialize(self) + self._root = Node:new() +end + +------ Public interface + +local beholder = {} + +function beholder:observe(...) + checkSelf(self, 'observe') + local event, callback = extractEventAndCallbackFromParams({...}) + return self._root:findOrCreateDescendant(event):addCallback(callback) +end + +function beholder:stopObserving(id) + checkSelf(self, 'stopObserving') + local node = Node:findById(id) + if not node then return false end + node:removeCallback(id) + return true +end + +function beholder:trigger(...) + checkSelf(self, 'trigger') + return falseIfZero( self._root:invokeCallbacksFromPath({...}) ) +end + +function beholder:triggerAll(...) + checkSelf(self, 'triggerAll') + return falseIfZero( self._root:invokeAllCallbacksInSubTree({...}) ) +end + +function beholder:reset() + checkSelf(self, 'reset') + initialize(self) +end + +initialize(beholder) + +return beholder diff --git a/love.conf b/love.conf new file mode 100755 index 0000000..0a7cb24 --- /dev/null +++ b/love.conf @@ -0,0 +1,3 @@ +function love.conf(t) + t.console = true +end diff --git a/main.lua b/main.lua new file mode 100755 index 0000000..f6a76e7 --- /dev/null +++ b/main.lua @@ -0,0 +1,233 @@ + + +beholder = require 'beholder' + +local directions = { + up = {dx = 0, dy = -1}, + down = {dx = 0, dy = 1}, + left = {dx = -1, dy = 0}, + right = {dx = 1, dy = 0} +} + +function startMoving(entity, direction) + entity.want[direction] = true +end + +function stopMoving(entity, direction) + if not direction then + entity.want = {} + else + entity.want[direction] = nil + end +end + +function pause(entity) + entity.paused = true +end + +function unpause(entity) + entity.paused = false +end + +function move(entity, dt) + if not entity.paused then + for dir,delta in pairs(directions) do + if entity.want[dir] then + entity.x = entity.x + delta.dx * entity.speed + entity.y = entity.y + delta.dy * entity.speed + end + end + end +end + +function checkCollision(a,b) + 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 + if ax1 < bx2 and ax2 > bx1 and ay1 < by2 and ay2 > by1 then + beholder:trigger("COLLISION", a, b) + beholder:trigger("COLLISION", b, a) + end +end + +function draw(entity) + love.graphics.setColor(unpack(entity.color)) + love.graphics.rectangle("line", entity.x, entity.y, 16, 16) +end + +function relativePosition(entity) + local position = {} + local dx = entity.target.x - entity.x + local dy = entity.target.y - entity.y + table.insert(position, dy > 0 and 'down' or dy < 0 and 'up') + table.insert(position, dx > 0 and 'right' or dx < 0 and 'left') + return position +end + +function chooseDirection(entity) + if entity.target then + stopMoving(entity) + for _,dir in ipairs(relativePosition(entity)) do + startMoving(entity, dir) + end + end +end + + +function all(collection, f,...) + for i=#collection,1,-1 do + f(collection[i], ...) + end +end + +function allWithIndex(collection, f) + for i=#collection,1,-1 do + f(collection[i], i, collection) + end +end + +function removeIfDead(entity, id, collection) + if entity.dead then table.remove(collection, id) end +end + +function gameOver() + print("braains") + beholder:reset() + love.event.push('q') +end + +entities, zombies = {},{} + +function createPlayer() + player = { + x = 400, + y = 300, + want={}, + color = {200,200,50}, + speed = 2 + } + setmetatable(player, {__tostring = function(t) return 'player' end}) + for dir,_ in pairs(directions) do + beholder:observe("KEYPRESSED", dir, function() startMoving(player, dir) end) + beholder:observe("KEYRELEASED", dir, function() stopMoving(player, dir) end) + end + beholder:observe("KEYPRESSED", " ", activateMine) + + beholder:observe("COLLISION", player, gameOver) + + table.insert(entities, player) +end + +function createZombie() + local zombie = { + x = math.random(20,780), + y = math.random(20,580), + want = {}, + color = {50,150,50}, + speed = math.max(math.random()/2, 0.4), + target = player + } + setmetatable(zombie, {__tostring = function(t) return 'zombie' end}) + table.insert(zombies, zombie) + table.insert(entities, zombie) +end + +function createMine() + mine = { + x = player.x, + y = player.y, + want = {}, + color = {100,100,200}, + speed = 0 + } + setmetatable(mine, {__tostring = function(t) return 'mine' end}) + + beholder:observe("COLLISION", mine, function(zombie) + if not mine.exploded then + mine.exploded = true + mine.color = {50,50,50} + zombie.dead = true + beholder:trigger("KILLED", zombie) + end + end) + + table.insert(entities, mine) +end + +function activateMine() + if mine.exploded then + mine.exploded = false + mine.color = {100,100,200} + mine.x,mine.y = player.x, player.y + end +end + +function love.update(dt) + all(zombies,chooseDirection) + all(entities,move) + all(zombies,checkCollision,player) + all(zombies,checkCollision,mine) + allWithIndex(zombies, removeIfDead) + allWithIndex(entities, removeIfDead) +end + +function love.draw() + all(entities,draw) + love.graphics.setColor(255,255,255) + love.graphics.print("Last pressed key: " .. lastPressedKey, 0, 580) +end + +function love.keypressed(key) + beholder:trigger("KEYPRESSED", key) +end + +function love.keyreleased(key) + beholder:trigger("KEYRELEASED", key) +end + +function love.load() + math.randomseed(os.time()) + + local zombieCount = 20 + local killCount = 0 + + createPlayer() + createMine() + for i=1,zombieCount do + createZombie() + end + + beholder:observe(print) -- print every event on the terminal + + -- prints the last pressed key on the screen + lastPressedKey = "" + beholder:observe("KEYPRESSED", function(key) + lastPressedKey = key + end) + + -- binds escape to the gameOver function (quit game) + beholder:observe("KEYPRESSED", "escape", gameOver) + + -- handle pause + beholder:observe("KEYPRESSED", "pause", function() + all(entities, pause) + local id + id = beholder:observe("KEYPRESSED", function() + all(entities, unpause) + beholder:stopObserving(id) + end) + end) + + + -- victor is triggered if enough kills are done + beholder:observe("KILLED", function() + killCount = killCount + 1 + if killCount == zombieCount then + print("You win!") + beholder:reset() + love.event.push('q') + end + end) + +end + +