I didn't post a Day One update, so I'll take the chance to make an introduction, and then get into the journal
Introduction
I've long wanted to make small games on the side, and I really love Clojure, so I'm making a game I've codenamed fossa. (Yes, foobardog is me, I've been moving some of my online presence to my new name, chimerror.) I have a title in mind, but I like using a codename first.
My main goal for this jam is to get better at avoiding my major vice of over-engineering and feature creep. I'm a fastidious kitty, and I often deep-dive too often. So the advice on keeping it simple is well taken, I just need the practice.
The basic idea for this game builds off a riddle I saw on TED-Ed they called The Temple Riddle . I've decided to change the flavor and iterate through this riddle a few times to make a longer game of it. Basically, this will be a type of logic game where you need to determine which members of your party are liars so you can escape the temple (well, cross-universe anomaly in my flavor). I may also expand the game by having certain party members having certain tools or abilities that are necessary to explore successfully (like a flashlight, or something).
I'm writing this in ClojureScript using phzr, which are bindings for the Phaser JavaScript library for ClojureScript. I am using brute, an entity-component system library for dependency management purposes. I'm keeping track of tasks and things on this Trello board. When I get to some interesting gameplay coding, I may do some streaming on my Twitch Channel .
Days One and Two Journal (Monday, 2016-Aug-01 to Tuesday, 2016-Aug-02)
So my first task was to figure out phzr and brute. In the pre-work, I managed to implement the Phaser tutorial, which is in JavaScript in ClojureScript. While phzr tries to make things more Clojure-like, that tutorial had me using a lot of global atoms, which I don't think is in the spirit of functional programming, so I was going to pull in brute to manage things in a cleaner way.
I first spun up a basic window, with just a background image and a sprite, using the patterns I had figured out from the pre-work. After that, I began trying to understand how brute could be integrated in. Phaser divides running a game into three stages (well, more than three, but I'm only using three): Preload, Create, and Update. Preload is used to load assets, Create actually creates game entities, and Update is called on every frame of the game loop.
brute is a bit more general than that. You create a system, add entities to that system, and add components to those entities. You then define a chain of system functions (for example, rendering, input, AI) and the system is passed through that chain. Each system function gets the entities and components it needs and handles updating them for their particular purpose.
The
brute demo code defines most of its components as Clojure records, as brute handles keeping track of entities. brute exposes a few methods to get all entities with a particular type of component. For this purpose it uses the ClojureScript type
function. (Well, when running in ClojureScript. For Clojure, it uses the class
function.) Internally, it uses the type information as keys into a map.
So I realized that I would need a way to keep track of which components had actions for which stages. For example, if I was going to have a sprite component, it should make sure to load the image during Preload, and create the sprite during Create. Clojure protocols seemed the perfect abstraction. And it would have worked, perhaps... In Clojure.
The main issue is that ClojureScript does not have as strong run-time reflection support for protocols as Clojure, and that the use of the
type
function didn't really expose what I can do there. The satisfies?
function exists to check protocol satisfaction, but that works on an individual object, not the type information as brute was using for keys. Additionally, it's really a macro and must take a known symbol at compile time. Clojure extends?
is what I would have wanted, but that's not available in ClojureScript.
Day 1 was basically lost figuring all this out. I spent the first half of Day 2 continuing trying to make it work. When deciding to cut my losses, I had the realization that I really was not representing my case accurately. I split the Preload functions into an Asset
protocol, and added an get-assets
to the Component
protocol. I completely ignored the brute way of getting components to just doseq
through all entities. I didn't want to break brute's contract, but I didn't want to completely discard it. I also wanted to add some defensive coding to my processing functions, but I couldn't get it working, and cut my losses. After all, I didn't get into this to write an entity-component system!
So a frustrating two days, but I'm through that. And yes, this was a little bit of ratholing, but I've been able to cut it off way better than I've ever done in the past. Onward to actually interesting parts!