lua-users home
lua-l archive

Re: Looking for examples: animation with coroutines

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi, Peter.
If your use case is as simple as the rabbit, then the timer is
probably the better option. But in more interesting cases you'll
probably have some state to track, along with more complex behaviors.
Say the carrot got moved around every now and then, the rabbit got
tired and took breaks, or was waiting for the wolf to disappear, and
so on. This can be a little (or a lot!) easier to manage via
coroutines than through a big state machine.
Typically you might build up some primitives based on whatever you do
often and to hide all the plumbing, e.g. (untested):
function Wait (time_lapse, update)
 local now = GetCurrentTime() -- some time function, os.time or
whatever, in whatever units you're using
 local last = now
 while true do
 local current = GetCurrentTime()
 if current - now >= time_lapse then
 break
 else
 if update then -- Call an update between yields, if desired
 update(current - last)
 end
 coroutine.yield()
 end
 last = current
 end
end
function WaitUntil (func, update)
 while not func() do
 if update then -- Same thing... could be folded into update too
 update()
 end
 coroutine.yield()
 end
end
-- And then, using the timer example from before...
setTimer(coroutine.wrap(function()
 local rabbit = PutRabbitSomewhere()
 local carrot = PutCarrotSomewhere()
 -- Move the carrot every so often
 setTimer(function()
 if carrot.consumed then
 return "cancel"
 end
 carrot:PutSomewhereElse()
 end, 10000, "repeating")
-- Chase the carrot until it's been consumed
 WaitUntil(function()
 return carrot.consumed
 end, function()
 local time = math.random(3500, 5000) -- The average time a rabbit
will chase a carrot before getting bored
 Wait(time, function(dt) -- Chase the carrot
 rabbit:Approach(carrot, dt)
 if Close(rabbit, carrot) then
 carrot.consumed = true
 end
 end)
 Wait(math.random(500, 1500) -- Take a break
 end)
end), 100, "repeating")
You can also invert the control flow a bit, say by yielding inside a
callback. I do something like that to draw a Hilbert curve inside an
incremental algorithm (uses Corona SDK):
https://github.com/ggcrunchy/corona-sdk-snippets/blob/master/samples/Hilbert.lua
https://github.com/ggcrunchy/corona-sdk-snippets/blob/master/fill/Hilbert.lua#L103
Updating a textbox, some number of characters per unit of time, as
they're being parsed (old version of Love, haven't updated it):
https://github.com/ggcrunchy/Old-Love2D-Demo/blob/master/Scripts/Class/UI/Widget/Textbox.lua#L30
These aren't great examples, but if you can run the Corona snippets,
there's some coroutine-driven movement going on (in the Wrap'd timers)
in these two samples:
https://github.com/ggcrunchy/corona-sdk-snippets/blob/master/samples/Hop.lua#L237
https://github.com/ggcrunchy/corona-sdk-snippets/blob/master/samples/Timers.lua#L125
There's some more stuff in that repository if you search for "flow_ops".
Hope that helps.

AltStyle によって変換されたページ (->オリジナル) /