Void Particle: A Retrospective Log


Hello to those stumble into here!

Approximately a month ago, I entered the raylib slo-jam and created 'Void Particle' for its theme. This log serves to provide a retrospective look on its development process. Everything written here will be based on my fuzzy memories, the notes I have lying around, and git commits.

Why did I join the jam?

For those who are unaware, I have been using raylib to make the SomeGameEngine prototype as a learning project for the past one year. Long story short, it is the reason that brought me out of a programming burnout and made me enjoy game programming again (Thanks Ray!). When the jam was announced, the drive within me is still hot. I thought it would be nice to side-track from my main project to enter this. Furthermore, this jam looks pretty laid back, plus I actually can somewhat commit to it due to its long submission period. So, maybe things will work out this time around.

The First Consideration : Time

Even though the deadline was roughly a month away, the actual time for development was definitely NOT one month. Due to life circumstances, I can  only attend to this jam in my spare time. It was estimated that I would only have a full week to do this. Given that it was in December, that means there would be more events that usual, cutting down more of the estimated time. This consideration has definitely affected most of my decision when making the game.

Early Vision and Initial Design

A personal decision I made for this project is to not feel bad/awful working on it. Although there will be difficulties, there shouldn't a point where I begin to hate my existence. This is mostly a little safeguard against burnout and catching myself early just in case. It serves as a compass when it comes to scoping and workload management.

Another personal decision I've made is to create the majority assets. Although it would be smart to public assets and focus more on feature implementation and polishing, I just prefer to add more of myself to the game so that I can happily call it mine.

The next part was to figure out what kind of game am I designing. I am not really an innovative person. I am fairly risk-averse and would rather do something tried and true. It would make more sense to make an arcade-y game for game jams, where endgame design is not a major factor, since you could just make it an endless game (like highscore attack).  However, I had decided to have an end to the game, just as an experiment.

Initially, I wanted the game to be a action rougelite (think Nuclear Throne), with the player going through stages until a final stage with a 'boss'. I deemed that too ambitious for the jam. So, I settled on a simpler wave-based game, like Vampire Survivors and 20 Minutes Till Dawn. Both types of game features a levelling system where the player is forced to select an upgrade upon achieving some sort of milestone (like an EXP system). I had instead opted to have a shop system where the player always know what can be upgraded and it is up to player to determine when to upgrade.

The next step was to flesh out the actual gameplay.

What makes Asteroids ... 'Asteroids'?

When I think about Asteroids, I remember its movement and control scheme, and the asteroids. Apparently, there are also flying saucers who shoot at you, but that must have slipped my mind.

The movement system is tank-like: the ship accelerates AND shoots in the direction it is aiming. The ship rotates at a fixed rate. The ship is also not subjected to friction (or subject to very little of) due to the space setting. While the control scheme works fine in its original medium, I actually dislike this control scheme. I find this scheme frustrating and rather restrictive for the game I was going for. Furthermore, the friction-less environment is somewhat counter-intuitive (although technically correct) to how we typically experience acceleration since people typically don't go to space on a regular basis. Due to these reasons, I've opted to use the typical WASD + mouse control and introduced a small amount of friction in the ship's movement for the initial implementation. With the more permissive movement scheme, I could also bump up the asteroid counts and allow some wilder asteroid behaviours, such as homing asteroids, and allow smarter enemies (if I actually get around to them).

The Initial Work: Movement

The first step of development was to reuse anything from my previous work: SomeGameEngine. That project was mainly to teach myself about ECS and general game engine concepts. However, that was written specifically for SomeGameEngine (i.e. not a general game engine). So, I had to take whatever I can and strip down whatever is not applicable. After that, it's time to implement the basic movement. In a few days, I was able to get the movement and screen wraparound working. I added a boost mechanic (or as I called it, 'insta-redirect') to allow players to redirect themselves in a pinch.

I then proceed to go on a vacation that was planned way before the announcement of the jam. I didn't do any development work during this time. However, I did note down what potential features can be added and some planning for the development work ahead. This was also the time where I decided on the wave-based gameplay.

This was where the first worry about gameplay pop up: can the player camp at the edges? If a player stay near an edge, they could abuse the wraparound and avoid enemies basically indefinitely, especially if there are 'chaser' enemies. In such cases, the enemy AI need to be smart enough to recognise this option and not blindly chase the player towards the edge. I had thought of some countermeasure for this, if it ever comes to it.

The Starting Point

The state of the 'game' before going on vacation

The Post-Vacation Work: Weapons & Damage

Upon returning from my vacation, I resumed work and implement the basic gameplay. There's asteroids that the player can shoot, and the asteroids break apart on destruction.  After that, it is time to add weapon variety. Initially, I wanted to add in 5 or 6 weapons, with one of them being a laser weapon. For technical reasons, I had narrow down to two additional weapons. So, the ship is expected to have three weapons:

  • Automatic single shot weapon as default
  • Shotgun for close-range burst damage
  • Homing for long range, hard-to-catch targets

When thinking of these weapons, I wanted them to be 'side-grades' and not overshadowing the default weapon, which I think I was successful with. The homing weapon was the hardest to balance as it is easy to over-tune/under-tune the weapon, resulting in either a useless weapon or a brainless weapon to use.

There is one fundamental design rule I chose here: everything is a circle. This makes collision checks so much easier since I don't need to care about rotation. Although the hitbox/hurtbox may not match the sprite drawn later on, as long as it feels good in motion, it should be good enough. I've also planned for the player hurtbox to be smaller than its sprite. This was taken from Bullet Hell games to give the feeling of near-misses.

At one point, I thought of doing broad-phase collision detection to cull out collision checks, but I quickly drop that after considering the amount of entities that is expected to be present in the field, which was not enough to justify that feature. If it does affect the game later on, I'll just need to tune the number of active entities.

During this time, I also wanted to name these weapons, rather than calling them by their generic name. I guess I was feeling a little edgy and decided to call them Nails, Thumper, and Maws respectively. This aspect is lightly influenced by Quake. As for the other weapons, I decided to put them on the chopping board and only implement them if I have time.

Gameplay emerging

Enemies added

The Christmas Work - Upgrade + Shop System

Then came the game progression system: the shop system. It was fine for the most part. I did change the engine to support scene-in-scene handling. Following the footsteps of the Vampire Survivors-like games, the player needs to collect 'experience' dropped by enemies. This actually somewhat remedy the camping problem mentioned before, since the player is now forced to get out of their camping spot to get the necessary items for progression. The enemy spawning logic was reworked to have it scale based on difficulty level,  with the difficulty level increasing as the game progresses. I opted to hand tune the spawn settings for each difficulty level, rather than reducing it to an equation or some sort. It was time-consuming for sure and definitely will not scale well, but it was fine for the scope of the game.

The shop is placed next to the arena. I wanted the player to always have access to the shop and the playing field at the same time. Originally, I wanted to render the shop on top of the field. Instead, I chose to let the player have an overview of the field while in the shop, which can either be helpful or anxiety-inducing, depending on when the player paused on. This meant that the playing field will be smaller. Now that I looked at it, I could have make the shop smaller to allow a larger playing field, but what's done is done.

A thought came up when implementing this: will the player abuse the pause to make things easier (like pausing rapidly to allow fine movement)? I decided that if they can do that and find fun in it, sure. It's not like there is a leaderboard or anything like that planned. So, if a player goes nut with it, so be it. Plus. it really funny to think about it too.

This was also where the aesthetics of the game takes shape. Originally, I wanted the setting to be an undisclosed eldritch location, with most of the graphics have some eldritch nature to them. Unfortunately, that couldn't happen due to lack of artistic abilities. So, I had  to settle on simple hand-drawn icons and graphics. Vector art was out of the picture as I don't know how to do them. I thought about doing the art via coding, but thought that was maybe a bit much.

VFX and SFX were also added around this time. For VFX, I just reuse my existing particle effect system (with some patching). I settled on simple effects with lines and shapes as they are faster to work with. SFX also uses the existing system. I thought of making actual sound effects with whatever items I have lying around, but I have no idea how. So, I just settled on using rfxGen to generate them. Most sound effects uses two layer of sound effects, which were edited with Tenacity (a fork of Audacity). The process is mostly trial-and-error and Feeling~ to get the sound I want.

I made a fairly important decision here: I changed the movement scheme to be mouse-centric. While the standard WASD + mouse movement is good and comfortable, I felt like it lost some of the 'asteroid' feel. It was then I realised the original movement of accelerating and shooting in the aiming direction is part of the charm. So, I decided to compromise and make the mouse control the movement, Left Click to shoot, and Right Click to accelerate. Practically, this still provide the flexibility of the mouse movement but retain the 'clunkiness' of the original Asteroid. I wasn't sure if that was the right choice at that time, but I think it worked out in the end and really solidified the Asteroids influence.

The New Year's Eve Work: End Game

With the progression system done, it was time to work on the end game. I decided to have the player 'buy' their end game via an item in the shop. That way, the player is given agency on whether to work towards the end goal, or to delay it for an upgrade now and maybe make the end a little easier.

Originally, I wanted the end game to be an actual boss, with telegraphed pattern to dodge. That didn't happen mostly due to technical skill issue and time. What it ended up is another asteroid, but much more durable and is repelled by the player. It is also the only other entity that has the ability to wraparound the playing field.

Some notes on the end item:

- The final item does not hurt the player on contact. This is intentional since the field will be filled with other asteroids that having that would just frustrate the player more than necessary.

- The final item will bump the difficult to the maximum. Originally, I wanted a difficulty past the current maximum that is only accessible via the final item. However, the current maximum is actually good enough that I didn't do that. Now that I think about it, I could have impose a hidden timer on the final item where the 'killscreen' mode activates once the timer expires, where the spawn rate becomes ridiculous. That would be pretty cruel.

- I wanted the final item to be able to shoot the player. However, I didn't implement any other enemies that shoots at the player due to time. So, this was scraped along with it.Christmas + New Year's Progress

Aesthestics Added!

The Final Stretch: Polish

At this stage, any features that I originally wanted to add have to be dropped. All focus was on bug catching, fixing, and tune up any aesthetics. I actually finished it one day before the deadline. Most of the UI changes occured here. There is one significant gameplay-related changes that occured here:

  • The damage upgrade was removed as I found it not useful enough.
  • Asteroids were given hitpoints based on their size. I found that one-hitting a big asteroid didn't feel right, so I scaled their health based on their sizes. However, I can't really go too crazy since I've removed the damage upgrade and I wasn't about to revert that decision.

The only problem I had was I didn't have any feedback on the game itself. It took one comment on release day to make me realised this. Shoutouts to Long Legs Inc. This is probably why you shouldn't be the only one playtesting the game, since you will be used to whatever quirk your game that may be detrimental to the actual experiences (particularly UI/UX stuff). As such, I asked my colleagues to play the game and gave me immediate feedback. With those, I added in last minutes changes on the day of the deadline.  Early feedback is something that I need to get better at, but better late than never.

With those final changes, the game was released for real into the jam.

Was It Worth It?

Yes. The game was received positively. Most design intentions were noticed by the players, which I am very glad about. There are some UI hiccups based on the feedback (which is what I get for not playtesting a little earlier), but overall it is good.

Closing Thoughts

All in all, I did well for the jam. I managed to achieve what I set out to do. Although there are many things I would love to add onto the game, I still can feel a sense of closure with the existing state of the game. The one thing that I need to get better would be to figure out a way to get early feedback.

I will move on from this game. Maybe one day I will make a 'follow-up' game that implement the things I want. For now, I do want to get back to my original project. See you next time!

Oh yeah, here's the source code for the game (assets not included): https://github.com/BeardedBread/raylib_slojam

Also, here's an image of the single paper used to sketch out any ideas for the jam.

Single Paper Sketch

The same paper used throughout the jam

Here's another image of the initial idea of the asteroid spawn configurations.

Spawning Configurations

Numbers...

Get Void Particle

Leave a comment

Log in with itch.io to leave a comment.