Rick Posted February 18, 2018 Share Posted February 18, 2018 [EDIT] Added better error checking. If an error happens in a coroutine Leadwerks doesn't report on it and the game doesn't stop, but I checked for an error and get the message and write it to console/log and fail the app saying to check out the console so it acts more like a normal error instead of it just not working. I'm using this for the competition so thought others might find it handy. Coroutines can be handy to allow you to do tasks over time but do them sequentially in 1 function. For example I could code something like the below where each function is done sequentially and we'd see/hear the results on the screen. If you did the below inside UpdateWorld() you'd only see the end result after that 1 iteration. function MyFunction() MoveToPoint() PlaySound() TypeText() end A state machine is a way to control flow between different states (or ideas). When you combine the 2 (coroutines and state machine) you can get some pretty powerful functionality. With this, each state has 3 functions. Enter/Leave/Update. Enter and Leave are coroutine enabled and Update() is like UpdateWorld() where it runs each frame. If you want more ideas on how to use feel free to ask. if StateManager ~= nil then return end StateManager = {} function StateManager:Create(container) local obj = {} obj.container = container obj.currentState = "" obj.nextState = "" obj.coLeave = nil obj.coEnter = nil for k,v in pairs(StateManager) do obj[k] = v end return obj end function StateManager:changeState(state) self.nextState = state -- if this is the first state then don't call a leave state if self.currentState ~= "" then local onLeaveMethod = self.container[self.currentState.."_Leave"] if onLeaveMethod ~= nil then self.coLeave = coroutine.create(onLeaveMethod) end end local onEnterMethod = self.container[self.nextState.."_Enter"] if onEnterMethod ~= nil then self.coEnter = coroutine.create(onEnterMethod) end self.currentState = self.nextState end function StateManager:update() if self.coLeave ~= nil then if coroutine.status(self.coLeave) ~= "dead" then local ret, err = coroutine.resume(self.coLeave, self.container) if ret == false then System:Print("Error: "..err) error("Check console/log for error") end return else self.coLeave = nil end end if self.coEnter ~= nil then if coroutine.status(self.coEnter) ~= "dead" then local ret, err = coroutine.resume(self.coEnter, self.container) if ret == false then System:Print("Error: "..err) error("Check console/log for error") end return else self.coEnter = nil end end -- call the update if we have one defined and aren't doing an enter/leave local onUpdateMethod = self.container[self.currentState.."_Update"] if onUpdateMethod ~= nil then onUpdateMethod(self.container) end end 1 Quote Link to comment Share on other sites More sharing options...
Rick Posted February 18, 2018 Author Share Posted February 18, 2018 I suppose I should give usage :). Often times before a level you may want to do a small something, then give control to the player, then at the end of the level do a little something else. This would work perfect for that situation. You'd have 3 states, PreGame, PlayGame, & PostGame. Each one has an Enter/Update/Leave for you to do things in and because Enter/Leave are coroutine enabled you can show progress while staying inside that function. You can wait 1 second, increase a number over time that's tied to the UI so it shows it going up over time, then wait then do whatever. function Script:Start() self.stateMgr = StateManager:Create(self) -- when you change states the state manager looks for functions with that state name and _Enter() _Leave() _Update() and if found will call them. self.stateMgr:changeState("PreGame") self.text = "" end function Script:PreGame_Enter() WaitForSeconds(2) -- these functions have yield in them self.text = "Ready" self:PlayBeepSound() WaitForSeconds(1) self.text = "Set" self:PlayBeepSound() WaitForSeconds(1) self.text = "Go!!" self:PlayBeepSound() self.stateMgr:changeState("PlayGame") end function Script:PreGame_Leave() -- not doing anything here but showing you can have it end function Script:PreGame_Update() -- don't need this but showing it anyway end function Script:PlayGame_Enter() end function Script:PlayGame_Update() -- do your game code here and when finsihed call self.stateMgr:changeState("PostGame") end function Script:PlayGame_Leave() -- maybe remove control? end function Script:PostGame_Enter() -- tween in your end game UI here and do some counting that updates the UI -- changing states could happen from a button click event function perhaps to continue end -- don't need to define Update()/Leave() for a function if you don't want to function Script:PostRender(ctx) ctx:DrawText(self.text, 0, 0) end function Script:UpdateWorld() self.stateMgr:update() end function WaitForSeconds(interval) local tm = Time:GetCurrent() while Time:GetCurrent() < tm + (interval * 1000) do coroutine.yield() end end Quote Link to comment Share on other sites More sharing options...
Rick Posted March 23, 2018 Author Share Posted March 23, 2018 I added a script to the workshop which you can get from the LE editor Workshop->Browse Workshop. I also did 3 video tutorials on usage from beginner to more advanced coroutine usage within the states. Don't ask me why the 2nd video link didn't show up in this post. No clue. http://steamcommunity.com/sharedfiles/filedetails/?id=1338038813 https://www.youtube.com/watch?v=AXiJ0DhDV7w 3 Quote Link to comment Share on other sites More sharing options...
josk Posted March 23, 2018 Share Posted March 23, 2018 Will get from the workshop, thanks for this and the videos. 1 Quote Elite Cobra Squad Link to comment Share on other sites More sharing options...
havenphillip Posted March 23, 2018 Share Posted March 23, 2018 Aw man it's saying video unavailable on YouTube as well. This seems cool but I'm still a noob I need those baby steps. Quote Link to comment Share on other sites More sharing options...
Rick Posted March 23, 2018 Author Share Posted March 23, 2018 1 minute ago, havenphillip said: Aw man it's saying video unavailable on YouTube as well. This seems cool but I'm still a noob I need those baby steps. Really? So you can't see them? Josk can you see them? Quote Link to comment Share on other sites More sharing options...
gamecreator Posted March 23, 2018 Share Posted March 23, 2018 Middle one (the one that's just a link) says it's unavailable. Never clicked it before. I guess that explains why it can't embed it. The other two are ok. Quote Link to comment Share on other sites More sharing options...
Rick Posted March 23, 2018 Author Share Posted March 23, 2018 12 minutes ago, gamecreator said: Middle one (the one that's just a link) says it's unavailable. Never clicked it before. I guess that explains why it can't embed it. The other two are ok. Hmm it plays for me. I'll have to dig into some youtube menus where I can't find anything. OK, it was private. Changed to public. Try now please. Quote Link to comment Share on other sites More sharing options...
havenphillip Posted March 24, 2018 Share Posted March 24, 2018 Yeah it's working now 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.