Ludum Dare 35 — Post Mortem

Stephen Ma
10 min readApr 23, 2016

--

Game jams are fun because of all the problems you encounter along the way. As a developer, encountering and learning how to deal with all of these problems will ultimately make you better. This Ludum Dare JAM I came in with a bit more experience, as well a more complete engine compared to the last one. Even with all that under my belt, I still encountered problems.

This is especially important when you’re going in writing something at a low level, like writing a game engine

To summarize I will talk about:

  1. Custom Engine Woes
  2. Scoping our Game Design to fit the JAM

Most of this is written for myself, as well as anyone interested in what work went into the engine. If none of those seem interesting to you, then read no further as this article is not for you. Otherwise prepare for a read.

Custom Engine Woes

The engine was completely rewritten since the last Ludum Dare. It is now more feature complete, but not ‘User Friendly’ yet. It’s still missing critical items still to be considered a real ‘commercial engine’. But knowing how to work with this fact was a crucial experience from the last JAM. Learning to plan early and around engine limitations, and produce a well polished game within those limitations was key to success.

The engine has come a long ways. Its been roughly a year’s worth of weekends and sleepless nights to get it this far. This by far, is just the tip of the iceberg, of the deep rabbit hole of writing a game engine. There are many problems still to be unearthed. Many of those with solutions bound to be solved in one way or another.

This section will talk about the goods, and the bads that has come out of this JAM.

To begin, here are some good things that was put in since the last JAM:

  • Easy Serializers for All the Game Objects

Templated out a ton of code, I managed provide a easy way to serialize game objects to text, and read text back into a game object. This was possible before, but now its much easier to write a brand new one (just in a few lines).

During the Jam this was used to write a serializer for two components that would have taken longer to write without the templates.

  • Global Configuration File

Providing variables configured via text file, no need to recompile the Engine to change the speed something. Games involve a surprising number of magic numbers to work ‘smoothly’, lets make them adjustable easily. The configuration file was deployed this greatly to make everything adjustable without a long recompile.

The main complaint there was no way to do automatic smoothing/tweening of these numbers based on value of other numbers. For example using Shapetris: the drop speed would have been nice to express as a function of the number of lines cleared.

  • Solid Input System

Inputs and Input Events were completely rewritten in the new engine. This is written as a ‘push’ delivery model, rather than a ‘pull’ model. This means when a input is registered, the input event is translated to a in-game-event then immediately pushed (but not processed) to all objects that are listening for inputs.

This hopefully helps sort out what system does what in the long run, although we have to duplicate event keys. I didn’t quite anticipate having to deal with a map of lambdas to be confusing, I may consider wrapping this differently in the next iteration.

  • Packaging and Releasing

The game engine now has a script that will build a deliverable and playable zip’d exe file along with all the resources. This speaks for itself, being able to build shippable is crucial, last Jam I didn’t have this and had to manually and hastily create zips to send out. This was a nightmare when I had to bug fixes, and often forget to include libraries and dlls required for the game to run.

With all the good things that are solved from the previous JAM, we always follow up with a pile of the new problems that occur in the next JAM:

  • Lack of Text/UI Systems

The previous version of the engine managed to hack something together to get a ‘UI’ display in game. Unfortunately this system was never ported to the new engine. The result was there wasn’t time to have live updated UIs to display level or write “GAME OVER” on the screen. This was a complaint from the last JAM, and there just wasn’t enough time to address.

In Shapetris almost all of the UI did not exist. There was a static backdrop drawn in the background to serve as eye candy. There was the game’s title sketched in using MS paint. There was a hacked-together title bar that displayed the current number of lines and FPS. This wasn’t clean, but it got enough of a point across to be ‘usable’ to those who understood where to look. However a utter failure on the engine’s part to provide.

SFML does us some help for this, but there was a large learning curve that during a JAM time constraints it would risk the entire project. UI is a very hard task to ‘get’ right, hopefully next JAM there will be better solutions.

  • No Visual Debugger for New Systems

This really bites, for Shapetris a new psudo-physics system during was added during the JAM. This was because Box2D was a bit overkill in a world of very finite movement physics. So we dropped Box2D in favor of writing our own physics simulations for Tetris-like. This in turn means we dropped all the nice debugging feature Box2D also provided.

But there was no visual-way to debug where the objects where. It would of been nice-to-have to provide ways to print the current state of this new system to screen or a second client before crashing.

We would often see a crash, but the crash happened before the render update. So what we see on screen, didn’t line up with what the game logic was.

Even providing a catch-all crash dump would of been handy too, since it would be nice to get the state of the game without having to have a debugger attached to it.

  • No Sounds

This was a main complaint about this last JAM that large portion of polish needs sounds. There was a system for sounds put in, but it couldn’t get re-ported to the new engine in time. So for this JAM sounds got cut too! Very disappointing. Hopefully can be addressed in time for the next JAM.

  • Python Scripting Wasn’t Ready

If you’re clever, you may have noticed that Shapetris shipped with a python27.zip. This zip contained everything needed to run standard python system libraries. At one point during the JAM, the Python system was fully hooked up and running a short update component’s position’ script. This was all scrapped due to a design decision we’ve made during the JAM.

The decision was made mostly due to the little amounts of working examples provided for this brand new technology. The engine just didn’t provide enough ‘get you started’ code to help new adopters (us) get it used in a partial sense. This is crazy considering the person that put the Python System together, was the person that said ‘we’re dropping Python for this JAM’.

There’s tons of problems I personally see that can be solved using Python Scripting. I didn’t consider trying to educate users being one of the major hurdles for adaptation of the system. Trying to show practical examples of what a PythonScriptComponent can do versus a PlayerRenderingSpriteComponent can do would of helped with this. Even in the naming alone a ‘PlayerSprite’ has more concrete description on what and where it will be used.

I’m very excited to see PyhtonScripting part of the engine. I want my next project to develop ground up by prototyping components as PythonScripts, then moving them to C++ as needed for speed. Workflow and examples will help, and is something that will go in bit by bit.

Scoping our Game Design to fit the JAM

I mentioned previously that I came into this JAM a bit more prepared knowing our limitations, then pushing them has hard as we could.

This time around, the JAM was seriously tough. I was very occupied with other things happening during the weekend, and had to squeeze in some extra engine polish before we even touched the game. So in reality I only had less than a day to work on it. The piled on programming fatigue gave me little hours to work on the game. The limited time it very hard plan a large scope. Making good games is already a huge and hard problem. But I came prepared and was able to squeeze something I’m proud of this time.

To begin, the project was looked at from the project management triangle. For a project to be successful, you need to manage the following:

Resources, Scope and Cost

Being a programmer my main resource would of been Time. Being unable to add additional Time to work on the JAM meant this was a option we couldn’t play with.

So I attacked where I could first: Cost. I got a second person in on the Project. This effectively doubled the amount of labor/hour we had on the project. Thank you very much Mitchell if you are reading this.

So this allowed the Jam to have a much higher quality project (by increasing the scope).

But Scope was a cost very limited by something else: The fairly incomplete game engine.

So what were our limitations we had to work with before we even considered what to do for the game?

  • The Rendering for the Sprite Drawing system was incomplete
  • There was no Sound System
  • There was no UI System
  • Controls were limited to Keyboard & Mouse
  • Box2D needed polish to make it work fluidly within the engine
  • We’re terrible at art, and was hard to find someone OK with us potentially failing horribly at the JAM

So out of the gate, a bit of our Time had to be allocated to finishing the Spriting system, and very limited in terms of what we can visually communicate to the player. This and during the JAM we had to leave very early (and often) to do other things, so it was difficult to find someone OK with all that and onto of potentially not finishing the JAM at all.

On top of this, since I’ve added a new person to the team there was a bit of learning that had to occur too. I had to factor the cost of having a JAM partner catching up on all the things I’ve added to the engine.

We haven’t even started talking about the JAM game, and we’re already strapped on time spent on the game itself. But there were a few intelligent choices we’ve made to the scoping the Game itself easier:

  • Restrict scope to a game that involves very primitive visual style
  • Restrict scope to a game that does not require sound to play
  • Restrict scope to a game whose we are mechanics very familiar with, and can be communicated though Keyboard & Mouse
  • Restrict scope to a game has primitive or no collisions at all
  • Pick a game has a short experience so we can reiterate and build on short experiences

So these were the five things in mind we had to choose something that meets all these criteria. No exceptions or the project will fail.

So during our brainstorm session with the Calgary Game Developers Ludum Dare Meetup we decided a Tetris-like game was the best fit to all these criteria. The most difficult part was Tetris-like physics which loosely met the ‘primitive collisions’ criteria. This meant this is something was a high-risk item that that would fail the project. Thus, was something that we had to focus most of our Resources (Time) on.

Even more on top of that we had to address ‘meeting criteria of the JAM theme’. I felt procedurally generating blocks would make our Tetris-like game much more interesting.

So the scope was mountainous for our limited time span, how did we decide this was something we could complete:

My JAM partner already made a Tetris-clone back in highscool. So he’s very familiar with Tetris Physics, and has solved most of the issues on approaching the problem. This experience definitely helped us in our application of our game, and really alleviated some of the risk of taking on this Project.

Additional Polish was something we considered to be part of the experience but were willing to abandon such as: Controls for Fast/Instant Drop, Being able to Rotate Pieces, Having a ‘ghost’ block display where the, Having a ‘next block’ display, Having a start menu, Having a game over screen/score screen, Being able to pause the game.

So our game scope was divided into major pieces:

  • Render blocks to screen
  • Make blocks fall
  • Make blocks disappear when they clear a line
  • Randomly generate blocks that fall

As well as the mandatory engine component we had to do early on:

  • Fix the Sprite rending system.

Based on our previous experiences, we estimated it was do-able in a day. There were a few ugly bugs that reared up in the middle of the project. A few math equations (I am horrible at math) that needed to be solved. We managed use the pair-down and track down and weed those issues quickly. In the end actually managed to get all done in our given time span! The project was a success, we had something playable!

But not to say: it wasn’t great project in terms of what makes a game ‘good’, there was extra polishing to do on top of all this. The extra polish you see in Shapetris all came in on Sunday when I found a bit of time to work on it. Tackling them in the order of difficulty I managed to get what I felt was crucial experience.

This made the game very much ‘playable’ at high speeds. Unfortunately there was a bug that made the game crash if a certain block generated outside the game-grid, so not many users experienced the extra polish. Something I will have to learn for next Jam too ...

There are many problems that arise and have to be addressed before, during or even after the JAM. I believe its these problems and the decisions that went into them are what that really make JAMs and working on games infinitely interesting. The people around it is what keeps it fun for everyone.

If you want to checkout Shapetris just go here (http://phen.itch.io/shapetris).

— Stephen Ma

--

--

Stephen Ma

Here on medium.com I write about my journey though gamedev and programming. May get technical!