Multiple love.run game states (The power of coroutines!)

Showcase your libraries, tools and other projects that help your fellow love users.
Post Reply
User avatar
markgo
Party member
Posts: 190
Joined: Sat Jan 05, 2013 12:21 am
Location: USA

Multiple love.run game states (The power of coroutines!)

Post by markgo »

A very simple (but powerful) module that can create multiple run states. You can have multiple game states! A simple case where this could be useful is to freeze the main thread and start another run state with a terminal. I hope Lafolie forgive me for borrowing his demo, it was the first thing on the first page.

When you call enter/resume, the coroutine will exit exactly right where you entered!. Additionally, when you resume a state, it will resume exactly where you exited!

Code: Select all

Usage

run = require 'run'
run2 = run() -- call to create new state

-- define callbacks like you would for love
function run.update(dt)
end
...
function run.draw()
end

-- resume the coroutine and pass (once) arg to run.load callback 
-- return true if the coroutine ran successfully plus additional parameters
boolean,... = run.enter(arg)

-- yield the coroutine and pass any additional parameters when yielding
run.exit(...)
The module (latest updates are here):

Code: Select all

local resume= coroutine.resume
local yield = coroutine.yield
local insert= table.insert
local unpack= unpack

local function getEvents(t)
	local __eventqueue = {}
	if love.event then
		love.event.pump()
		for e,a,b,c,d in love.event.poll() do
				insert(__eventqueue,{e,a,b,c,d})
		end
	end
	return __eventqueue
end

local function pushEvents(t)
	if love.event then
		local eq = t.__eventqueue
		for i = 1,#t.__eventqueue do
			love.event.push(unpack(eq[i]))
			eq[i] = nil
		end
	end
end

local function swapEvents(t)
	local __eventqueue = getEvents(t)
	pushEvents(t)
	t.__eventqueue = __eventqueue
end

local function new()
	local t = {__eventqueue = {}}
	local run = coroutine.create(function(arg)
		if t.load then t.load(arg) end
		while true do
			if love.event then
				love.event.pump()
				for e,a,b,c,d in love.event.poll() do
					if e == "quit" then
						if not t.quit or not t.quit() then
							-- if love.audio then -- manually handle audio per state
								-- love.audio.stop()
							-- end
							swapEvents(t)
							return
						end
					end
					if t[e] then t[e](a,b,c,d) end
				end
			end
			if love.timer then
				love.timer.step()
				dt = love.timer.getDelta()
			end
			if t.update then t.update(dt) end
			if love.graphics then
				love.graphics.clear()
				if t.draw then t.draw() end
			end
			if love.timer then love.timer.sleep(0.001) end
			if love.graphics then love.graphics.present() end
		end
	end)
	
	local function exit(...)
		swapEvents(t)
		yield(...)
	end
	
	local function enter(arg)
		swapEvents(t)
		return resume(run,arg)
	end
	
	t.enter  = enter
	t.exit   = exit

	return t
end

return setmetatable(new(),{__call = function(self) return new() end})
EDIT: Omitted love.audio.stop when quitting. Do manual handling instead
Attachments
ltype_forum.love
(68.83 KiB) Downloaded 85 times
Post Reply

Who is online

Users browsing this forum: darkfrei and 58 guests