Skip to content
David Hayes edited this page Jan 5, 2023 · 5 revisions

Squeak

A small, opinionated game framework.

Overview

My intent for the framework is to stay extremely simple and opinionated. It is not made for every game ever. I tend to reject generic, super-configurable solutions in favor of custom-written ones. Hence this thing.

Although I've only ever used this to write games in LÖVE it has no LÖVE-specific code in it.

Squeak Fundamentals

If you squint you might mistake it for an ECS, but it's not: there are no separate systems, only very smart Component instances registered with dumb GameObject instances.

Nearly everything in the framework has an update method.

How To Start

I'm going to write this like I'm writing a LÖVE game. I happen to really love LÖVE, so I like to convince other people to use it.

In your main.lua file you'd probably start with this:

function love.load()
end

function love.update(dt)
end

function love.draw()
end

First, you'd need a SceneManager instance. It takes an argument of an eventBus. That's my fancy name for a global-ish instance of EventEmitter. That way things in your code can know that there are things happening they might be interested in.

local eventBus
local sceneManager

function love.load()
  eventBus = EventEmitter()
  sceneManager = SceneManager(eventBus)
end

You'd probably next create a class derived from Scene. Let's pretend like that class is called InGame. Let's add it to the manager:

local InGame = Scene:extend()

local eventBus
local sceneManager

function love.load()
  eventBus = EventEmitter()
  sceneManager = SceneManager(eventBus)
  local inGame = InGame()
  sceneManager:add(inGame)
end

Your InGame scene probably creates a new GobsList. Let's call that list gobs.

local InGame = Scene:extend()

function InGame:new()
  self.gobs = GobsList()
end

In your update method for your InGame class, you probably do this:

function InGame:update(dt)
  self.gobs:update(dt)
end

Now any GameObjects that you add to the list will be updated correctly. Let's do this for draw, too:

function InGame:draw()
  self.gobs:draw()
end

Super. But nothing is hooked up yet. We have to make sure the SceneManager instance we made before is hooked up:

function love.update(dt)
  sceneManager:update(dt)
end

function love.draw()
  sceneManager:draw()
end

That's a fancy-looking skeleton you have there.

How To Keep Going

  • When are assets loaded?
    • In their own Scene, perhaps. Once they're done loading that Scene can transition to InGame.
  • What about input?
    • Squeak has nothing to say about input because it can't help make it easier, it would just get in the way of your custom solution.
  • What about globals?
    • Ew, yuck. You probably want a Registry instead.
    • Or not, I dunno. The Registry might go away soon.

But I Want an ECS!

You're in luck, the community is very talented:

I've used both of these and they're great. Lots of good docs, too.