Created
May 23, 2017 18:42
-
-
Save mohiji/9e47a0af518bcaa364e885ae6f6bea0d to your computer and use it in GitHub Desktop.
Coroutine test in LÖVE
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
-- main.lua | |
-- This file contains the actual demonstration code. The stuff that implements waits and signals | |
-- is in wait_support. | |
wait_support = require("wait_support") | |
local georgeColor = {0, 255, 0, 255} | |
local bobColor = {255, 0, 255, 255} | |
local georgeText = "" | |
local bobText = "" | |
function George() | |
while true do | |
georgeText = "Hey there, Bob." | |
wait_support.waitSeconds(2) | |
wait_support.signal("go-ahead-bob-1") | |
wait_support.waitSeconds(0.5) | |
georgeText = "" | |
wait_support.waitSignal("go-ahead-george-1") | |
georgeText = "Can't complain. It's been raining. You?" | |
wait_support.waitSeconds(2) | |
wait_support.signal("go-ahead-bob-2") | |
wait_support.waitSeconds(0.5) | |
georgeText = "" | |
wait_support.waitSignal("go-ahead-george-2") | |
georgeText = "You too, Bob." | |
wait_support.waitSeconds(2) | |
georgeText = "" | |
wait_support.waitSeconds(2) | |
end | |
end | |
function Bob() | |
while true do | |
wait_support.waitSignal("go-ahead-bob-1") | |
bobText = "Hi George. How's it going?" | |
wait_support.waitSeconds(2) | |
wait_support.signal("go-ahead-george-1") | |
wait_support.waitSeconds(0.5) | |
bobText = "" | |
wait_support.waitSignal("go-ahead-bob-2") | |
bobText = "Same old, same old." | |
wait_support.waitSeconds(2) | |
bobText = "Looking forward to some snow." | |
wait_support.waitSeconds(2) | |
bobText = "Well, I best be going. Take care, George." | |
wait_support.waitSeconds(2) | |
wait_support.signal("go-ahead-george-2") | |
wait_support.waitSeconds(0.5) | |
bobText = "" | |
end | |
end | |
function love.load() | |
wait_support.runProcess(George) | |
wait_support.runProcess(Bob) | |
end | |
function love.update(dt) | |
wait_support.wakeUpWaitingThreads(dt) | |
end | |
function love.draw() | |
local georgeTable = { | |
color1 = georgeColor, | |
string1 = georgeText | |
} | |
local bobTable = { | |
color1 = bobColor, | |
string1 = bobText | |
} | |
love.graphics.setColor(georgeColor) | |
love.graphics.printf(georgeText, 40, 200, 200, "left") | |
love.graphics.setColor(bobColor) | |
love.graphics.printf(bobText, 40, 400, 200, "right") | |
end |
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
-- This file implements waitSeconds, waitSignal, signal, and their supporting stuff. | |
local wait_support = {} | |
-- This table is indexed by coroutine and simply contains the time at which the coroutine | |
-- should be woken up. | |
local WAITING_ON_TIME = {} | |
-- This table is indexed by signal and contains list of coroutines that are waiting | |
-- on a given signal | |
local WAITING_ON_SIGNAL = {} | |
-- Keep track of how long the game has been running. | |
local CURRENT_TIME = 0 | |
function wait_support.waitSeconds(seconds) | |
-- Grab a reference to the current running coroutine. | |
local co = coroutine.running() | |
-- If co is nil, that means we're on the main process, which isn't a coroutine and can't yield | |
assert(co ~= nil, "The main thread cannot wait!") | |
-- Store the coroutine and its wakeup time in the WAITING_ON_TIME table | |
local wakeupTime = CURRENT_TIME + seconds | |
WAITING_ON_TIME[co] = wakeupTime | |
-- And suspend the process | |
return coroutine.yield(co) | |
end | |
function wait_support.wakeUpWaitingThreads(deltaTime) | |
-- This function should be called once per game logic update with the amount of time | |
-- that has passed since it was last called | |
CURRENT_TIME = CURRENT_TIME + deltaTime | |
-- First, grab a list of the threads that need to be woken up. They'll need to be removed | |
-- from the WAITING_ON_TIME table which we don't want to try and do while we're iterating | |
-- through that table, hence the list. | |
local threadsToWake = {} | |
for co, wakeupTime in pairs(WAITING_ON_TIME) do | |
if wakeupTime < CURRENT_TIME then | |
table.insert(threadsToWake, co) | |
end | |
end | |
-- Now wake them all up. | |
for _, co in ipairs(threadsToWake) do | |
WAITING_ON_TIME[co] = nil -- Setting a field to nil removes it from the table | |
coroutine.resume(co) | |
end | |
end | |
function wait_support.waitSignal(signalName) | |
-- Same check as in waitSeconds; the main thread cannot wait | |
local co = coroutine.running() | |
assert(co ~= nil, "The main thread cannot wait!") | |
if WAITING_ON_SIGNAL[signalStr] == nil then | |
-- If there wasn't already a list for this signal, start a new one. | |
WAITING_ON_SIGNAL[signalName] = { co } | |
else | |
table.insert(WAITING_ON_SIGNAL[signalName], co) | |
end | |
return coroutine.yield() | |
end | |
function wait_support.signal(signalName) | |
local threads = WAITING_ON_SIGNAL[signalName] | |
if threads == nil then return end | |
WAITING_ON_SIGNAL[signalName] = nil | |
for _, co in ipairs(threads) do | |
coroutine.resume(co) | |
end | |
end | |
function wait_support.runProcess(func) | |
-- This function is just a quick wrapper to start a coroutine. | |
local co = coroutine.create(func) | |
return coroutine.resume(co) | |
end | |
return wait_support |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment