Skip to content

Instantly share code, notes, and snippets.

@erinlin
Last active March 14, 2016 06:39
Show Gist options
  • Save erinlin/5916293 to your computer and use it in GitHub Desktop.
Save erinlin/5916293 to your computer and use it in GitHub Desktop.
coronaSDK-coroutine-statemachine
--[[
statemachine.lua
Copyright (c) 2013 Erin Lin
erinylin.blogspot.com
Licensed under the MIT license.
Usage:
local sm = require("statemachine")
local process = sm.new(function(self, time)
self:sleep(100)
print("hello")
self:sleep(100)
print("hehe...")
self:sleep(100)
print("end")
end)
process:run()
local process1 = sm.new(function(self, time)
local txt = display.newText( "Press Me", display.contentCenterX, display.contentCenterY, native.systemFont, 32)
txt:addEventListener("touch", function(evt)
self:continue()
end)
self:waiting()
txt.text = "Hello!"
self:sleep(200)
txt.text = "Bye Bye!"
end)
process1:run()
]]--
local StateMachine = {}
local StateMachine_mt = { __index = StateMachine }
local coroutine = {
yield = coroutine.yield,
resume = coroutine.resume,
create = coroutine.create,
status = coroutine.status
}
function StateMachine:sleep(msec)
self._wakeup = system.getTimer() + msec
while self._wakeup > 0 do
coroutine.yield()
end
end
function StateMachine:enterFrame(event)
if self._wakeup > 0 then
if event.time > self._wakeup then
self._wakeup = 0
end
else
local state = coroutine.status(self._co)
if state == "suspended" then
coroutine.resume(self._co, self)
elseif state == "dead" then
if self._isLoop then
self._co = coroutine.create( self._callback )
else
Runtime:removeEventListener("enterFrame", self)
self._co = nil
end
end
end
end
function StateMachine:pause()
self._stopTime = system.getTimer()
Runtime:removeEventListener("enterFrame", self)
end
function StateMachine:resume()
if self._co then
if self._wakeup > 0 then
self._wakeup = self._wakeup + system.getTimer() - self._stopTime
end
Runtime:addEventListener("enterFrame", self)
else
self:run()
end
end
-- you can loop this.
function StateMachine:run(isLoop)
self._isLoop = isLoop
if not self._co then
self._wakeup = 0
self._stopTime = 0
Runtime:addEventListener("enterFrame", self )
self._co = coroutine.create( self._callback )
end
end
function StateMachine:isRunning()
return self._co ~= nil
end
function StateMachine:destroy()
Runtime:removeEventListener("enterFrame", self )
self._callback, self._co, self = nil, nil, nil
end
function StateMachine:cancel()
Runtime:removeEventListener("enterFrame", self )
self._co = nil
end
function StateMachine:waiting()
self._isPass = false
while not self._isPass do
coroutine.yield()
end
end
function StateMachine:continue()
self._isPass = true
end
local function new(callback)
local ds = {}
setmetatable(ds, StateMachine_mt)
ds._callback = callback
ds._wakeup = 0
return ds
end
return {new=new}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment