Last active
March 14, 2016 06:39
-
-
Save erinlin/5916293 to your computer and use it in GitHub Desktop.
coronaSDK-coroutine-statemachine
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
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