Ludum Dare 36 — Post Mortem

It’s that time of year again. If you haven’t read my last post-mortem, this is a slight continuation of it since the last time I’ve jammed. In here I’ll summarize my thoughts and other things I’ve discovered during Ludum Dare. Hopefully, you’ll learn as much as I did this Jam in this post. But by far, this was the most fun Jam I’ve done with this Engine.

Ancient Fire Clicker — A short clicker game about fire

Speaking of which, if you haven’t tried out our game yet, I really encourage you! Leave some feedback, as I’d love to hear your thoughts on anything! What do you think I could of done better? How was the experience for you? Did you like it?

The fun of the Jam, for me, comes not only with the theme and time restrictions but also, what can we make with our engine limitations. I’ll once again talk about some of the woes that come with working with an engine, some conveniences I really wish I had, as well as some of more poorer choices I made during the Jam.

Custom Engine Limitations:

Good news! I didn’t rewrite the engine from scratch, so most of the bits and components are still the same from last time, and even improved a little bit here and there. I mentioned a whole list of things I didn’t like, and I actually fixed most(ish) of them since the last time! I’ll talk about these in the next section.

For this portion, I’ll once again talk about scoping, as I believe this is a difficult task for any project. If you want your project to succeed, you need to scope, and cut, then scope again. This by far combined with working with software, with people nefariously full of giving bad estimates is a great recipe for disaster around every corner. In order to do scope well you need to understand your problem-set you are trying to solve, luckily it was something that was kept in mind entering this Jam.

Given that the engine has become better, but is still far from perfect we have to deal with a new level of problems that come.

  • No animations

I didn’t plan for any animations, sprite-sheets, or any of the fancy tileworks that other engines might give for free. There were some instances I regret not having sprite animations, such as animating the flame in the center, as well as animating the buttons (on hover/on press/on release).

But Stephen, you can fake animations by deleting the old sprite and replacing it with a new one! Well, I thought that too going into this Jam, unfortunately, there was another bug where we can’t sort what order sprites get drawn in. This means we can’t just delete and re-add the sprites :(.

So anything involving animations were cut, there just wasn’t enough time. Let alone, I wasn’t fully on art during the Jam, so I couldn’t afford extra artwork. Overall I think the game could have been better had an animation been in place, oh well, maybe next Jam!

  • No physics-heavy game

The physics system is -very- inefficient. With lots of moving objects on a scene, Box2D slows down terribly. I get horrible FPS drops once I reach around 500 active objects. Part of it is because I don’t have an object recycler, so its pretty expensive to move/create/destroy objects at the moment. There’s lots of work here to be ironed out, but I’m starting to hit the “this might be a library limitation” wall soon.

During the Jam I discovered just how horrible it is trying to move 500 entities in the same region all at once is. I figured out “Its best just to avoid physics simulation all-together when possible”. This might apply to every physics system out there. I’m sure some systems have that optimization built in.

The result was there is little that’s been done in Physics this jam. The mouse is physics simulated (for collisions), but that’s about it. At one point we had every spawned object collide with the fire, to trigger an event to do other stuff. This proved to be too much for Physics. That was cut from the game, and likely was for the better!

  • No experience with ‘real’ python

Surprise! Both me and my team, this time, was writing a game in a language none of us are familiar with. I mean, we’ve touched Python scripts before to say update a variable here, and change the output there. But we’ve never written stuff in Python from the ground up before. There were lots of things in the Python language we didn’t take advantage of like optional named parameters, coroutines, enum class, the python standard library, and free typeless variables. Partly because most of our programming knowledge comes from C++, so most of those concepts are things that don’t come for free in the language for us.

This is something that can only get better with time, as we learn more language features we can more quickly solve problems by taking advantage of Python.

Some pretty horrible hacks were put in, I don’t even understand how I got there.

Not to mention some of the horrible Jam hacks we’ve put in which I can talk about in a separate post one day.

That being said, we went with “lets not do anything too complicated” route here. That was fine. I think getting the math right is, and should be the hardest part for programming during a Jam. We shouldn’t be fighting to get language features correct. Stick to the basics, and just do it well enough to get it working.

  • No resource pre-loading

Yeah, my bad here! I dropped the ball a bit going into this Jam for adding the pre-loader. We wanted sounds, and we wanted sprites. We got them both! But now we have an issue where resources are loaded from disk during the game. This sometimes might cause a large FPS drop! That’s bad.

Luckily we don’t have many resources in the game, but it definitely held us back from going crazy with the number of things we wanted to add. The biggest asset we have is the ending ‘tada’ and we don’t mind a bit of FPS drop to display the credits there.

  • Very poor in-game editor

Last Jam I complained there was no visual way to debug systems. So I've added a number of things since the last Jam such as a in-game entity viewer, as well as a Box2D Physics Visualizer. Unfortunately the solution I thought might of been good-enough ended up not being very useful at all :(. There were a couple of cases where it solved a few bugs for us, so its -not- totally rubbish! But its definitely far from the useful that I envision!

Some things I want to see in the future:

  • The ability to name entities in the debugger
Yeah.. are you confused at who entity1 and entity10 is? So am I!
  • The ability to load from a snapshot (savestates)

Going back to SNES emulation days, the ability to save and load from state was one the most useful thing that the emulator provided. This has some very useful debugging use in game too.

  • Better workflow when working with scripts

Sometimes I just want to change a magic number in a script and see what it does. Maybe the next point might be fix this…

  • The ability to edit entities + scripts in game

This would be nice to be able to edit entities while the game is still running, then hot-reload the entity into the game, but only possible once we have savestates!

  • Only one real day to work on it ( ~12hours )

As with every scoping issue, you have to realize your main resource which is time, and how much of that time you need to spend on stuff (cost). We were limited to one day to really get everything together, then scattered hours here and there to get the rest done. So it was important for us to focus on getting the things we felt were most important done first.

This time we actually have a game that you can finish as a result!! We had more time to do testing, as well as had more time to re-iterate over some ideas that didn’t pan out too well.

Things I liked:

  • We really went into the “lets jam” mindset, lots of hacks left, right, and center

This is our third Jam. Some great takeaways is: go into the Jam with the mindset of “just deliver it, don’t worry about maintaining it”. There’s lots of training from people who work in Software do to “not make your code horrible for others”.

This is something that comes with Jam experience, is just the ability to undo that training to get stuff done. Know where you can take shortcuts, and know your definite life-cycle of everything you do.

For example I needed an event system that can play text when events happen. I made a miniature event system that plays text at one speed. This was more than enough for me to solve my issue, and getting the text to play on time can be offloaded by a ton of copy/paste sequencing. This was OK because I never ever going to have more than the 20 lines of text I had planned for the game. If I needed more I could add a few more copy-pasted lines, but it will never explode.

However outside of Jam settings, I want a more maintainable way to deal with text. What if I wanted more text? What if I needed text to be animated too? How do I deal with non-English text?

  • Python scripting proved to be invaluable improvement on iteration time

There were lots of valuable conversations we had this time around where we said “just try this instead” and we tried it to see if it worked. Being able to iterate fast was the reason we added Python. And boy did it show!

We were able to do tones of things entirely in python, without needed to do a long 1–2 minute recompile. We were able to prototype 2–3 different solutions for one problem and just pick which one worked better.

We spent a surprising amount of time to get the mouse working just right, but it turned out that was a different issue altogether, so we threw together a hack to get the result we needed. Which by the way, if you full-screen it will break the mouse. Hopefully people won’t play in full-screen right?

Overall very happy with this result! Also very happy with the combination of the serialization system, I can easily add new bindings to Python. This is still a pain, but definitively would be more-of-a-pain if it wasn’t there.

  • Dialog system

I was able to quickly throw together a text input system during the jam. Although the “jam” quality of the input system kind of showed near the end where I couldn’t -exactly- control the dialog. One speed dialog, but no ability to sequence strings came at a slight cost.

Add random whitespaces ahoy!

I’m hoping to integrate something like YARN into the engine update so I can have a easier time managing text prompts. This is actually going to be very exciting for me, as it will likely be the first pure-python/combined system I’m providing.

  • More time for art and non-programming stuff

Being able to spend my first 2–3 hours of the Jam just concept-ing and doing all the art assets was actually quite fun. As well as spending time to write up the story was fun too. I think games that are meaningful are the ones that will stick most with people. Video games combines visual, auditory and interactive elements to convey meaning to the player. This is something not many other mediums can do as easily and is what I love most about games!

Show your support

Clapping shows how much you appreciated Stephen Ma’s story.