[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Help with Lua Threads/Coroutines/(or something)
- From: Paul Du Bois <paul.dubois@...>
- Date: Thu, 24 Nov 2005 00:02:47 -0800
Well, rather than describe how I do it, why not post some code? If
you've ever programmed in UnrealScript, this will feel rather
familiar.
Here's the implementation (using coroutines; the implementation was a
lot messier when we used lua 4!) and a sample blocking call:
-- Called from some external place, once per tick
function Ob:onTick(dt)
local fn = rawget(self, 'current_statefunc')
if fn then
local bSuccess, result = coroutine.resume(fn, self, dt)
if not bSuccess then
Tracef("Error running state '%s':\n%s", self.current_state, result)
self:setState(nil)
else
if coroutine.status(fn) == "dead" then
self.current_statefunc = nil
end
end
end
end
-- pass string new_state
-- Similar to Psychonauts API
function Ob:setState(new_state)
-- Call endState__()
if not self.inEndState and self.current_state then
local lastStateName = self.current_state
local endfunc = self['endState' .. self.current_state];
self.inEndState = true
if endfunc then endfunc(self, new_state) end
self.inEndState = false
-- If the endfunc hijacked the transition to new_state by
-- calling setState(), don't continue on and call beginState;
-- it will be a duplicate call.
if self.current_state ~= lastStateName then return nil end
end
-- Call beginState__()
if type(new_state) == "string" then
self.current_state = new_state
-- create a coroutine for the function Ob:stateFoo()
-- this is the most important bit.
local func = self['state' .. self.current_state]
if func then
self.current_statefunc = coroutine.create(func)
end
local beginfunc = self['beginState' .. self.current_state]
if beginfunc then beginfunc(self) end
else
self.current_state = nil
self.current_statefunc = nil
end
return true
end
function Ob:sleep(time)
-- use ">=" so sleep() always yields at least once
while time >= 0 do
local _,dt = coroutine.yield()
time = time - dt
end
end
And some sample client code:
function Ob:stateWaitingToDie()
self:sleep(self.active_lifetime)
self:setActive(false)
self:sleep(self.inactive_lifetime)
self:killSelf()
end
p