--[[ -- When the application calls the main #loop the application becomes event oriented and all action is taken inside this module. -- There are four internal events responsible for all the dynamic of an application. -- They are generated automatically and the programmer should not bother. -- -- -- The only type of event that needs programmer interaction is for input handling. -- A handler is a table in which the entries are [event_type] = handler_function pairs, whenever an event_type happens its associated handler_function is called: -- -- handler = { [DFEC_INPUT] = -- function (evt) -- if evt.key_symbol == DIKS_CURSOR_UP then ship:move( 0,-5) -- elseif evt.key_symbol == DIKS_CURSOR_DOWN then ship:move( 0, 5) -- elseif evt.key_symbol == DIKS_CURSOR_LEFT then ship:move(-5, 0) -- elseif evt.key_symbol == DIKS_CURSOR_RIGHT then ship:move( 5, 0) -- elseif evt.key_symbol == DIKS_SPACE then ship:shoot() -- end -- } -- table.insert(gui.handlers, handler) -- -- The above code creates a handler for input events, ship is a Draw.lua object and the handler makes it moving on screen. --]] local _G = _G local coroutine = coroutine local assert = assert local table = table local EVENT = event local CANVAS = canvas module (...) local gui = _G.require(_PACKAGE..'gui') -- posted = {} -- last = nil -- Main handler for gui.lua#handlers, responsible for the dynamics of application after a call to #loop. -- Handles stop, draw, time and collision events. handler = {} -- handler = { user = function (evt) posted[evt.type] = false local f = handler.user_table[evt.type] if f then return f(evt) end end; user_table = { -- DRAW draw = function (evt) gui.draws:draw() CANVAS:flush() return true end; -- COLLISION collision = function (evt) gui.draws:collisions(evt.data) return true end; -- TIMER timer = function (evt) local now = EVENT.uptime() local diff = (last and (now - last)) or 0 last = now assert( coroutine.resume(gui.timers.co, gui.timers, diff) ) return true end; }; } -- --local _col = {class='user', type='collision', data=nil} --local _usr = {class='user', type=nil, data=nil} -- TEMP: optimize function post (type, data) -- TEMP: deveria ser postado apos draw? if (type == 'draw') and data and data.collide and data.visible then --_col.data = data --EVENT.post('in', _col) EVENT.post('in', {class='user', type='collision', data=data}) end if posted[type] then return end if (type=='draw') or (type=='timer') then posted[type] = true end --_usr.type, _usr.data = type, data --EVENT.post('in', _usr) EVENT.post('in', {class='user', type=type, data=data}) end -- Exits main #loop giving the control back to the application. -- ret: value returned by main #loop function stop (ret) --EVENT.wake(ret) EVENT.post('out', { class='ncl', type='presentation', area='', transition='stops' }) end function listener (evt) --_G.collectgarbage'collect' -- searches for a single handler for the event -- iterates top->down, whenever func returns true, stops for i=#gui.handlers, 1, -1 do func = gui.handlers[i][evt.class] if func then if func(evt) then break end -- handler 'handled' the event, so break end end end EVENT.register(listener) -- Enters main loop. -- Every application should call this function after initialization. function loop () posted.timer, posted.draw = false, false post('draw') post('timer') return EVENT.sleep() end