About 3 weeks ago, I participated in the Simple Jam on itch.io, for which the task was to make a game with a maximum of 5 rules and 5 assets. The result of this was Kryce, an analog stick bullethell game, which was of course made in Luxe!
The development of the game went surprisingly smoothly for my own standards, so I want to summarise the process in this post.
At the start of the jam, I had to look for an idea to start out with. For a while I had wanted to make a game that used a gamepad, specifically the analog inputs of it, such as the analog sticks and the triggers. These inputs can have a state anywhere in a range of values, instead of just being on or off like a key on a keyboard, and games rarely seem to use that information. The only common use I can think of is a slower walking speed when the analog stick isn't completely moved outwards.
I figured that this game jam would be a good opportunity to experiment with this idea, so I had my initial direction to go in.
What followed was a series of prototypes which all used the analog inputs in some way. Each of these I made in a separate branch in the game's repository, which allowed me to frequently switch between different ideas, and try out new things, without fearing that I might delete something I could need later. Doing this was certainly one of the major factors which made the development process more efficient and enjoyable for me.
The prototype that I started with simply contained two circles, each representing the position of the left or right analog stick. I then also added a line that would span between the two circles, which looked like this:
This turned out to be intriguing since the mapping between the circles and analog sticks felt quite tactile.
I expanded on this idea further by adding other shapes, such as a square or a circle. I imagined a game where you would switch between various shapes and print them onto the background to match a given image generated by the game. I got as far as implementing the shape printing, but then gave up on it as I couldn't think of any ways to actually make an interesting game out of this idea. Here's how that prototype looked like at the end:
The next prototype was based on the idea of using the connecting line from the first one as a paddle for a breakout-style game. Using the SAT collision detection classes at
luxe.collision, I made some very rough 'physics' interactions with a ball that bounced off the screen edges and the connecting line. I also added a bunch of blocks surrounding the central circle that the player had to hit. At this point, the prototype looked like this:
This idea was interesting to me at first, however I soon noticed two problems with it, which are even apparent in that gif:
- Angling the paddle in the middle precisely enough to hit a certain block was difficult and frustrating.
- The ball sometimes just bounced around without entering the inner circle, leaving the player to just wait and watch without any interaction.
I stopped working on this prototype for a bit, but later I came back to it and tried to fix the second problem by creating randomly spawning targets, and shooting one ball for each target directly towards the player's paddle. That idea ended in this state:
The ball now always moved in a way that the player could interact with it, which fixed problem 2 as I had aimed. The aiming was still just as difficult though, so this version of the prototype wasn't really any more fun than previous versions. However it was at least somewhat useful as it would eventually lead into the final version of the game.
Before getting to this point though, there were also some wildly different ideas that I had tested in-between working on the mentioned prototypes:
- In one idea, you controlled a spaceship by pulling the left and right triggers of the controller, which set the strength of the spaceship's left and right thrusters. This one didn't go very far because it would have taken too long to configure the properties of the physics simulation (in Nape) well enough to make it playable.
- The other idea was an arrow shooting mechanic which I remembered from a flash game called The Arrow Of Time. My idea was to make the analog stick movement be used like pulling back a bow, but it really just ended up feeling like standard aiming. In the end, the prototype didn't get beyond this barebones version:
Even though these prototypes didn't seem to end up leading anywhere, I still think that they were important for informing my final prototype idea, because now I knew what definitely wouldn't work for a game, or at least in this jam. Overall, I'm very happy that I explicitly did this prototyping process, instead of just picking one idea and sticking with it.
After all these prototypes, though, I finally got to the idea that would become the finished game. Using the breakout-style prototype as a basis, I removed the second circle controlled by the right analog stick, as well as the targets spawned on the outside. Instead of hitting targets, the goal of the game would simply be to dodge the shots from the spawner for as long as possible.
After the basics of this idea were implemented, I moved on to make the spawner shoot various shot patterns. This involved a lot of tweening of the spawners position and angle, so I initially used the standard Actuate tweening in Luxe, and later Delta. While sufficient for a while, I soon realised that for this game I needed to be able to easily handle several related tweens running at the same time. For example, I had to tween a spawner's position and angle, and have bullet shots be triggered periodically during those tweens. Since both Actuate and Delta are focused on handling simple sequences of tweens, I decided to not try and bend one of those systems to my needs, and just make my own. This system had the basic concept of a timeline, which would contain several tween objects. Any of these could overlap in time, and would be called simultaneously as needed.
Making this system was a surprisingly quick process, though as a result it ended up being a bit rough. The biggest problem with it was a rather clunky syntax, compared to just a chain of function calls like in Delta, but overall the system worked well for the game jam and made development a lot more efficient later on.
Once the tweening was handled, I had to actually figure out how to create and store different bullet patterns. Initially, I tried to use json files that described all the tweens and shots involved in a pattern, which would then be read by a system and converted into actual tweening commands in code. This worked for basic patterns, got messy with complex patterns, and I realised that it would take too long to get the system to support that complexity within the jam timeframe.
So instead, I just created the patterns directly in code, each being represented by one function. A pattern function now takes a spawner as an argument, and applies all the tweens necessary to run that pattern on the spawner. Using just functions ended up having some problems with code repetition, but it was quick to create new patterns in, and allowed for maximum flexibility (since it was just code).
An important consideration while making patterns were their parameters, such as timing values of movement, shot speeds, etc. Iterating on these values had to be smooth because I would alter them often to tweak a pattern's difficulty. To achieve quick iteration, I stored all of these parameters in a json configuration file, which each pattern then reads its parameters from. That way, I was able to simply alter that file while the game was running, reload it with a button press, and have the new values apply to the patterns.
Once the structure for patterns existed, I had to make the system that would repeatedly select one of the patterns at random and execute it, which is inspired by how I think Super Hexagon works. At the start I simply gave equal chance to each pattern, but as I added more patterns, I wanted to control when certain patterns were first introduced, and what their weighting was, in order to create a difficulty curve in the game.
I ended up creating a list of 'phases' in, again, a json file. A single phase looks like this:
The duration property specifies how long the game should stay in this phase, and the remaining properties are pattern names, associated with the probability that they should be selected.
The game moves through this list of phases as time progresses, and picks a patterns from the current phase.
That system looked like this in action, here shown using 3 different patterns:
Once the system was in place, I made more patterns sporadically during the rest of the jam, and I learned a few things doing so:
One thing I noticed was that a pattern could be repeatedly picked. This was annoying for some longer patterns, but actually intended for the single shot pattern, where consecutive shots from different directions would often be nicely challenging. Because of this, I couldn't simply implement a check to prevented a pattern to be repeatedly. Instead, I added some randomness in the pattern behaviours themselves. For example, most patterns that involve the spawner rotating around the centre can go clockwise or counterclockwise, which is randomly selected when the pattern is run. This way, each pattern gains its own variation, making consecutive executions of the same pattern more interesting to play.
Another feature that I found was very important once the random pattern selection existed was a manual testing mode. In this mode, each pattern was bound to a button on the gamepad, and I was able to trigger new patterns at will when I needed to test them, instead of waiting for them to be randomly selected. I ended up wrapping all of the code for this mode in a compiler define, so that the final version of the game didn't even contain my testing code.
Lastly, I wanted to introduce some interesting bullet movement apart from just flying in a straight line. To make that possible, I reworked my physics system to not simply move objects based on their velocity, but instead call their update function as you would with an entity. Then, each type of bullet was able to implement its own movement logic.
I used this system for bullets that wiggled side-to-side, and also later make a bullet that would aim at and hunt down the player. Both of these were additions late in the game jam timeframe, so I don't feel like I fully made use of all the possibilities, but I'm happy with having at least these two bullet types.
Interspersed with the work on patterns, I also started to improve the visuals of the game. For a bit, I experimented with the 'subtract' blend mode, which made some interesting, but very chaotic effects:
As it was obvious this wouldn't lead anywhere, I instead used Paletton to find some good colours for the game. As with all the other values in the game that would need tweaking, I put these in a json file and made a colour manager in the code to parse the values into luxe.Color objects. These were then used for all the objects in the game.
While this was useful to quickly load in different colour values, I realised that to really iterate small adjustments to the values quickly, it was best to simply import a screenshot of the game into Krita to see my changes immediately. Once I had done that I would simply copy out the hex values into my json file.
While I couldn't use the subtraction blending itself, I still liked the effect of a shape having different colours depending on what was drawn over or under it, especially if they were only partially covered. To somewhat mimic that effect, I created the colours of the concentric rings by making the background of the game a uniform red, and layering a mask of increasingly opaque black rings on top of the whole game. This way, anything closer to the centre and thus the player is brighter and appears more important. Apart from colours, I also changed the shape of the bullets to better indicate their movement direction.
The overall result of these improvements looked like this. Here you can also see the wiggling bullets described earlier in action, as well as the effect of the rings when the player circle overlaps the the inner ring border:
Surprisingly late in the project, I added the game timer, so the player would have a way to tell how long they survived. I did this so late because it wasn't a pressing feature for the game (though necessary for the final version), and also because I first had to find a font to use, which turned out to be a surprisingly long process. There's a lot of fonts out there, but finding the one that would fit what I imaged was difficult!
Once a font was found though, I also added some menus. With these I learned that it is very important to tween every transition, even if it is just a quick fade in or out. Subconsciously a tweened transition feels much better than just text appearing or disappearing in a frame.
Here's the game both with a menu screen and the timer:
Finally, in the last few days of the game jam, I started on sound effects and music for the game. Initially, I planned to make all of them using LSDJ, however my gameboy broke after a few minutes of use (great timing there), so I ended up using SunVox instead. Making the sound effects was surprisingly difficult, since for some of them, such as the generic shot sound, it was hard for me to imagine how I even wanted it to sound. I managed to make some okay sounds in the end, but this is certainly an area I have to learn more about.
Unfortunately, I wasn't able to make a background track for the game, as I didn't know SunVox very well, and din't have enough time to learn it.
After all of this, the rest of the jam time was spent adding miscellaneous functionality such as muting the game or switching which analog stick to use. Lastly, I created the itch.io game page and uploaded with about 15 minutes left to the jam deadline!
Overall, I'm very happy with the game and the development process of it. I gained a lot of experience not only in developing but also in releasing a game.
Thanks for reading, and let me know what you think in the comments or on twitter @Keymaster_!