Game Development Game Jams Software Development

Ludum Dare 38-40 Postmortem

It’s been nearly a year since I participated in Ludum Dare 38, which was my first ever game jam. I finished the game, and received decent ratings (I mean, not great over all, but given it was my first one), placing me between the 500th and 700th place in the rankings. I also participated in Ludum Dare 39, which unfortunately never made it to the playable stage by the 72 hour deadline. Ludum Dare 40 I likewise did not finish, however it was much more finished than 39, and was more technically advanced than either of the previous attempts.

Ludum Dare 41 is coming up in less than a month, and as I try to prepare my game engine implementations, now seems like as good a time as any to do a postmortem on each of my experiences.

Ludum Dare 38 – Asteroid Field

Let’s start with a simple explanation of my concept for Ludum Dare 38. The theme was “A Small World.” My game was called “Asteroid Field,” and was a game wherein you play as the planet earth, firing missiles into space to blow up large asteroids that are careening randomly toward your tiny planet. As time progresses, so does the average size, number, and speed of asteroids. The more points you score, the better your missiles get.

It was written in JavaScript using ES6 and transpiled and bundled with Webpack and Babel. The game engine was Phaser CE 2.

The majority of my time was spent learning the Phaser engine, which I had never used before. I had especially debilitating delays caused by issues with collision physics and particle emitters as implemented in Phaser then. I ended up implementing the physics collision math myself instead of going through the game engine, as the built-in arcade physics that I had initially intended to use gave strange behavior, as everything was expected to be a square, whereas my assets were generally better represented as circles. Unfortunately, my reliance on circles for hitboxes resulted in performance-killing trigonometry in the inner loop, which makes it difficult to play on older computers. I also made the mistake of starting the project without using the pushdown game state system, which resulted in having to significantly refactor my code when I decided I needed a game over screen.

My next biggest use of time was late-phase debugging, which I think is largely due to the fact that I went into this challenge knowing very little about the library I was using. I spent very little time on creating assets, game design, and play testing/balancing.

Overall, I would say I did a great job of limiting the scope of the project to make it realistic for my experience level with the tools, format, and process. Right from the start, my strategy was to create a game design with minimum complexity of mechanics, but with a lot of potential for cosmetic and very simple gameplay additions that could improve on the barebones concept. This strategy worked well for a first game.

Aside from inexperience, which can only be remedied over time, I think the primary lesson that I learned from this experience was that I needed to plan things more effectively. I think more complete mockups of the design, as well as figuring out the requirements for things like the physics engine going into the project would have helped me to avoid many roadblocks.

Ludum Dare 39 – Blackout (Incomplete, Unplayable)

A few months after Asteroid Field, I participated in Ludum Dare 39, for which the theme was “Running Out of Power.” My game was called “Blackout”, and the premise was that you would play as a dispatcher for a power company, and your screen would be a control panel showing a city and providing notices when the city’s power grid was damaged. Your job would be to dispatch your repair crews as effectively as possible to keep the power on for the greatest number of people. If you were not powering part of the city, that part would not be paying you, and if enough people are without power, the power company loses money. You lose when your company runs out of money.

This game was built on the same tech stack as Asteroid Field.

During this project, I spent the majority of my time, disappointingly, designing the digital representation of a city. This project was a lot more ambitious than my last one. From the design perspective, it didn’t seem that much more complex, certainly not enough to prevent me from completing the game on time. What I underestimated, however, was the complexity of the “street node” system, and the difficulty of implementing both the rendering and the physics of the vehicles travelling along said street nodes. I did get so far as determining that there needed to be object representations of “intersections” and “roads.” Intersections would contain references to each road that connected to them, and each road would contain references to each intersection acting as an endpoint. Additionally, roads would contain data on the amount of traffic, the speed of the road, and sometimes control points, through which a Catmull-Rom spline would travel to create curved or windy roads. The vehicles would be dispatched by passing their origin, destination, and the city grid to an A* pathfinding function, which would spit out the turn-by-turn directions. An update loop callback would then be responsible for moving the vehicle along this path based on the speed and traffic values for the street upon which the vehicle is currently traveling.

That design was straightforward enough. Unfortunately, that is more or less the entirety of the implementation that I had even figured out, let alone implemented. A number of problems appeared this time around. First of all, how do I draw this city? Well what I did was literally to draw it on a sheet of paper, and then draw a grid on top of it and manually write out a big long JavaScript object containing the intersections and streets and their coordinates as they appeared on the sheet of paper that I drew up. This took an ENORMOUS amount of time. I spent over a day and a half doing just this. With this task figured out, I also needed to implement the preloading system and game menu. Fortunately, I was able to complete those things, and I do have a menu complete with the ability to name your power company. After that, I needed to render the city. I had initially determined that a Catmull-Rom spline would be the best way to implement curves in the roads, since I could simply give it coordinates that fell on the path instead of off-path control points which Bezier curves need. Unfortunately, after completing the map, I found that the game engine I was using had already implemented Bezier curves, but not Catmull-Rom, which were more complex. At this point, I realized that I needed to implement the curve algorithms myself. This was about where I was when 72 hours came to an end. The extent of playability is that you can load the game, name your company, and start the disappointingly blank screen that is the “playing” state, even though somewhere in your browser’s memory is an invisible and very complex street map that I painstakingly wrote out by hand.

I think that the biggest lesson here, is, once again, to learn how to better plan ahead of time, better consider the technical limitations of the game engine at the time of the contest, and to better assess the difficulty and depth of the gameplay elements. I think this might have also gone better if I had been able to adapt the design as issues appeared, which might have been possible if I had more often benchmarked my progress according to a schedule.

Ludum Dare 40 – Speed Fishing (Incomplete, Kind Of Playable, Pretty Neat)

Okay, Ludum Dare 40 was the best of times, and the worst of times for me. I had hyped myself up for this challenge, for which the theme was “The More You Have, The Worse It Is.” I’m not going to lie, I hated the theme for this one. But that’s how Ludum Dare goes sometimes, and that’s what’s so cool about it. You show your adaptability by taking the theme and working with it, regardless of your feelings towards it. And so I did.

My game was called “Speed Fishing,” and its premise was that you are a fisherman in a fishing boat. You must collect as many fish as you can in a specific time limit. Before the timer is up, you must return to the starting place. You drive your motorized boat out into the water, avoiding obstacles such as land, sharks, and battleships, and collect the fish as you go. The more fish your boat contains, the more difficult it is to accelerate, brake, and turn, thus making travel more perilous.

This time, I broke from the web stack and decided to implement this game in C++ using SFML. I had already been working on the engine for a Minecraft-like game called Territory, and I ported much of the code from that, refactoring it to use SFML instead of GLFW. I chose SFML over GLFW because of its relative simplicity for 2D games, whereas GLFW was chosen for Territory because of its more do-it-yourself nature, and its support for Vulkan.

I spent a good part of my time working on real game features, believe it or not. That said, a few things took longer than expected because I had come from the web stack and expected functionality to be present that simply wasn’t, even in as high-level a framework as SFML. Namely, I had to figure out how to place elements on the screen correctly using direct coordinates (which I did in the previous games, but there seemed to be more helper functions available there to do things like center an asset), and I had to handle click events myself to determine if clickable elements had in fact been clicked. This click event handling was the biggest shock of all to me, although I was able to figure it out, and fortunately determining if a click lands inside a rectangle is fairly straightforward math. I also expected SFML to implement game states and associated functionality, but that was also left to me. Fortunately, I had already done most of that in the Territory project. As in the last Ludum Dare, however, the complexity of the game map implementation was one of the biggest consumers of time. In this case, I wanted the world to be mostly ocean with some land, and I wanted everything to be generated procedurally using perlin noise. I also needed to guarantee that the boat would spawn in water. Additionally, I needed to use the flyweight pattern for the rendering of the map itself, as I didn’t want to have millions of instances of multi-byte objects eating up large swaths of fragmented memory and slowing down the rendering because of CPU prefetch misses. I also needed to be able to move the player entity around through the world, all while keeping the camera centered on it. Because the world was larger than the screen, I also didn’t want to have to render the tiles that were outside of the visible screen area.

All of these features, I was able to implement, and just in time for the deadline no less. Unfortunately, things like the menu, score-keeping, fish entities, enemy entities, land collision, timer, and boat movement physics did not get completed within the time limit.

This time around, I will say that I had more distractions than before, and therefore I could have put more focus into this project than I did. Despite that, however, this project has more lines of hand-written code than both previous projects, and despite being incomplete, it is more technically complex than the completed Asteroid Field game, and I am truly proud of it. In all 3 Ludum Dare experiences, this one is the one of which I am the most proud. So that’s the good. The bad, however, is that the last day is one of which I did not sleep one minute. In fact, when the 72-hour mark was met, I had been awake for 30-something hours. I felt awful and tired. There were many moments between the 24-hour mark and the end that I was absolutely suffering. But I was determined to finish something, to be proud of something. I succeeded at that, and I am grateful.

I think one of the things that I learned with Speed Fishing was that I loved C++ more than I loved JavaScript. I also learned that code reuse is a beautiful and helpful thing, and I need to be doing more of that. This project, Speed Fishing, is the origin of a game engine I created called “ArcticWolf,” which comes after “TimberWolf,” which is the one that I used in Territory. Each of them is a specialization of a very deliberately similar API. I will be able to use these engines in not only future Ludum Dare projects, but also in free and commercial games that I will be releasing via my game company “Danger Zone Games.” So in a way, Ludum Dare 40 was the beginning of Danger Zone Games, it was the beginning of me making modular and reusable game engines, and created the ArcticWolf game engine (which was originally borrowed code from TimberWolf, which was borrowed code from Territory).

The Future!

I am very excited to participate in future Ludum Dare jams, and I am very excited to be creating games at long last. It’s been a dream of mine for a very long time, and it’s been a wild ride getting to where I am now. Even though I’m not making money on my games yet, I still love it. For me, game development isn’t a job or an industry. Game development is an amazing art. It incorporates technical skill through programming, graphic art and musical talent through game assets, and psychology through gameplay design. When you’re on your own, you have to be a skilled artist and technician in each of these fields. When you work with others, you may only need to specialize in one, but as a team your talents must stay in sync. I am proud to be a part of this community, and I am excited to see what we can all achieve in the coming years.

Programming Languages Software Development Web Development

JavaScript: Love, Hate, and Standardization

Recently, I’ve read a lot of hate toward JavaScript (which is easy to explain, see my previous post titled “Programming Language Wars“), and specifically there are a number of people who would request that browser vendors and the web standards organizations implement additional/alternative programming languages. This is a very naive request that I believe stems from lack of respect for standardization and the challenges facing browser development.

First of all, “JavaScript”, AKA ECMAScript AKA ECMA-262 AKA ISO/IEC 16262, exists primarily as a standardization, and that’s the important part here. Despite its origins, JavaScript has been around for decades, and likely will persist as such for decades, maybe even centuries to come. It was selected to be the core of the programming side of the standardized web. This standardization has been of particular benefit to making the web more or less completely compatible between a variety of browsers. JavaScript is defined in clearly written specifications, and as a result, each implementation, from Firefox’s Spidermonkey, to Chrome’s V8, to the dozens of other complete implementations, can be implemented separately and therefore be mutually independent from one another, while at the same time each supporting the same code so long as the developers making these products follow the standards correctly. This also affords freedom for competition to create distinct implementations instead of relying on a centralized one, which cultivates innovation.

There are many different languages that have a similar standardization and specification process, but this is not the only important characteristic of JavaScript. As a language designed for the web, it cannot make any presumptions of the architecture on which it will run. This means it would need to be provided as a scripting language (which JavaScript is), or a language of virtual machine bytecode (which WebAssembly is, which I’ll get into later). In addition to this, the language is supposed to be entirely forward compatible, so that code written a long time ago is capable of running on newer engines without modification. On some languages, this requirement can be, and is, safely ignored. Allowing things to be routinely deprecated and changed breaks old code. Often in these cases, the solution is simply to run the code on an outdated interpreter. This is not an option for browser vendors, however, whose releases already push several hundred megabytes in size, to say nothing of the nightmare of deciding which versions are still to be shipped, or the support nightmare of requiring end-users to manually choose their interpreter versions. These characteristics rule out a number of other possible languages.

Yet another issue with implementing other languages is the prevalence of JavaScript. Whether or not you like it, which is really not of concern here, JavaScript is arguably the most popular programming language in the world right now. Its forgiving nature cultivates ease of use for the beginner, largely due to being untyped and having automatic garbage collection. Additionally, the massive amount of development done due to the importance of the web has made JavaScript very performant. It also has a very C-like syntax, which is very popular and familiar to many developers.

Some people are hasty to criticize a language or library for catering to the needs of the less-experienced. These people usually complain about the loss of quality by making programming more accessible. But as is usually the case, ease of use does not preclude advanced functionality. JavaScript is a very mature language, and as such, it has a large user base that demands access to more advanced features and the ability to optimize performance more than an entry-level user requires.

And finally, and in my opinion, the biggest reason against implementing new languages for the browser is maintainability. As I write this, the Chromium JavaScript implementation, V8, has 1350 open bug reports. This is the number for a single programming language. If the web standards were to mandate the addition of another language, this would have to be implemented in yet another system of roughly equal complexity, and this would cripple the progress of development teams that even now are hard at work steadily advancing the single language implementation they have to maintain already.

All of these arguments aside, however, I fully understand the desire for developers to work in a language that suits their own style. I know the struggle of being forced to work with a programming language that I don’t like. So if I believe that, why do I still deny that other languages should be implemented in the web standards? First of all, I believe the benefit is greatly outweighed by the detrimental effect it would have on the speed of development for the open web standards. Second of all, if new languages are implemented, sooner or later, even those languages will come under fire for essentially the same reasons.

What we need isn’t to explicitly modify those standards to include languages, but to provide a common foundation on which new languages can be founded without requiring modification to the central standard itself. The simple answer to this is an intermediate language or virtual machine.

So far, JavaScript itself has acted as this intermediate language. Languages such as TypeScript, CoffeeScript, and Dart transpile into simplified JavaScript with boilerplate to implement missing features. Emscripten has even allowed the transpiling of languages such as C or C++ into JavaScript.

More recently, however, there is a new standard known as WebAssembly, which I believe solves this problem even better. One of the main purposes of WebAssembly was to provide an avenue for higher performance computing in a browser environment. One of the lowest levels of abstraction of an execution environment is assembly language. It encodes the primitive computational operations of the hardware itself, and has very few, if any, high level features. This lower level of abstraction also means that instructions written in it have little to no overhead. Due to the requirement for web languages to be architecture-neutral and to have some level of access control security, this had to be implemented in a virtual machine architecture that is conceptually close to a CPU architecture, but with a universal specification, and the ability to restrict the execution context to resources that it should have access to. This design is remarkably similar to the design of the Java virtual machine.

In the future, I suspect that many more programming languages will have either integrated or third-party backends that allow software to be compiled to run in this environment. This will require a fair amount of work to get this completed for each language, but I think it is the best way forward. With this method, any language could become a web-compatible language in the future, without needing to be integrated into the web standards, and without requiring extra work by the browser developers. By funneling all languages into the same intermediate language, it also ensures compatibility between them. And finally, because this method requires a compilation step, it means that if the programming language is updated and breaking changes implemented, previously compiled code will continue to function as normal until recompiled. The breaking changes may therefore still impact the developer, but not the end-user.

So to sum up: NO, new languages should not be integrated into web standards, but YES, developers of other languages should utilize transpiling and WebAssembly to make their languages available for web development. Other web-friendly programming languages should not be competing with JavaScript, they should rather see JavaScript and WebAssembly as their natural choice for an intermediate compilation target.