Ludum Dare 51

This past weekend it was Ludum Dare time again! This time in the lead up I made the biggest pre-event change I have made yet, did almost no prep work, failed to take any meaningful screenshots during the event, and ordered a lot of pizza. Time to dive in.
Run Up
Ahead of Ludum Dare 51, but not directly due to the event I replaced the computer that I typically do these events on - gone is the quirky i7-5775c monster made from spare parts, and in its place is a must more stable 5600G-powered machine. This would usually be a straight swap and not worth mentioning, except for one detail:
I am now working entirely from Linux instead of using both a Linux and a Windows system.
This is not too big of a change, but it means some of my tooling has changed slightly. Most notably I was previously using a Windows computer to power drive a drawing tablet/display, and am no longer. Things like Aseprite are now running on the same Linux machine the rest of the work is done on, and thankfully I realised this meant I needed to install Aseprite about 20 minutes before the event started. It also meant I needed to move the hosting container over to the new system while performing the traditional my traditional pre-Ludum Dare checks and updates. Nothing crazy. Overall this would have been a pretty small change if I had remembered to prepare ahead of time. It also means I no longer have access to Bfxr, but that is a problem I was willing to solve as the event went on.
Theme Voting

This time around I was a lot more opinionated on the theme, and that reflected in my final round voting. The first 4 ideas were all roughly the same idea, only "Shelter" would have caused me to shift my plans substantially.

The top 4 non-negative themes were all destined to become a twin-stick shooter, while Shelter was going to be an economy simulator building on the things I learned in Humble Homestead. I did toy with the idea of this theme being an economy simulator for a few minute, but the thought did not go very far.


Fun fact, the idea of a twin-stick shooter came up during Ludum Dare 50 for one of the themes, and I had been thinking about it ever since. There was a very strong chance this game was going to turn into a twin-stick shooter regardless of what the theme was.
Event Start
The start of the event was pretty typical, for about 2 minutes.
Looking back at Ludum Dare 50, I see I wrote the following:

As I probably could have predicted, I did not do this. What I did do was pull the first commit from my Ludum Dare 50 repository to use as a template - I remembered writing something of a template for 50, so it made sense that it was probably the first commit.
10 minutes later I deleted the folder and started again. I made a ton of discoveries and "updates" to the systems I first started using in Ludum Dare 49, and those happened throughout Ludum Dare 50.
So instead I started from the Ludum Dare 50 repository and stripped out a bunch of the Forest Run mechanics. Items and shops are noticeably absent from DecaRun, which were fairly large systems that were outright deleted.
Day 1
First Task: Map Generation
I toyed with a couple designs and mechanics for a map that would have been both interactive and a core part of the game. The one that I spent the majority of this time on involved the playable area being a long, somewhat narrow hallway that switched directions every 10 seconds. Functionally it was most of the way there, but the code I was using from Ludum Dare 50 just was not designed with a morphing playing area in mind. After 2 or 3 hours of trying to modify the existing tile rendering system to fit the idea I ended up throwing it out and falling back to the standard square room that is present in the final game. Simplifying the room also meant I could simplify the tile rendering and border detection that is used to draw the walls, thereby fixing the issue Forest Run had with drawing some corner pieces at the edges of the map.
I eventually dropped the idea of a morphing map entirely - redrawing the map was a problem I did not have the willpower to tackle after my initial attempts did not work.
Second Task: Player Movement
The momentum-based movement I used in Forest Run drew some positive comments among those that were unfortunate enough to have played it, so I knew that was going to make a return. The only real difference is pointing the character to face the mouse instead of pointing them in the direction of their momentum. Thankfully this is really similar to the momentum based method, you only have to set the angle
property of the sprite on every update:
this.angle = Phaser.Math.RadToDeg(Phaser.Math.Angle.Between(window.innerWidth / 2, window.innerHeight / 2, mousePositionX, mousePositionY))
The rest of the movement system is roughly the same, so one big plus for using template code.
Third task: Basic Shooting
The last task I wanted to accomplish on the first day was to get some basic shooting implemented for the player. This should be really similar to the player code since it is just angle and (higher) velocity, and indeed the implementation really is that simple. The direction uses a similar angle calculation and applies a speed that is faster than the player. It is painfully obvious that the momentum values are completely unrelated based on being almost able to outrun the projectiles if shooting and moving in the same direction, but they are projectiles all the same. Three core pieces of the game hashed out in the first night, overall a pretty successful first 7 hours to this Ludum Dare.
Interlude
One of the hardest things about game jam type events is trying to figure out when to code systems "properly", and when to throw them together in the fastest way possible. For example, in the final source code:

Weapons
directory in the source codeThere were initially plans for multiple types of weapons, which might have required different types of projectiles - some of the thoughts were for weapons that fired multiple projectiles at once, or shot their projectiles in ways that did not follow standard physics (in an arc, or following a wave). Instead the final version only uses the base classes for everything - which is perfectly fine, but there were a couple of considerations that could have been done faster if there was no plan to expand on them in the future. Instead, the framework is there in the source for anyone who wants to play around with it - which makes it not a total loss, but not an efficient use of "jamming" time.
Second Day
The majority of the development happened in the second day, since it was the longest of the 3 days involved. Without reliving the entire day, some highlights:
- Sounds were added via jsfxr
- Background sound was created via BeepBox. Notably the background sound loop is 10 seconds long, so the act of advancing to the next wave should happen at the same point in the loop each time - a nice coordination touch.
- Added some recoloured skins to the enemies for some variations
- Made dying/losing health functional
- Added an "aggro range" where an enemy would begin to chase you once you were within. It is not a perfect solution since you can just have a 4K monitor and see stationary enemies outside of the range, but the alternative is the entire map swarming you every 10 seconds.
- Added some additional weight to the border walls to make it harder to get stuck in them. It is still possible, but I am going to live with it as the built in Phaser functionality being used seems to be related to it and the time/return does not seem valuable.
- Popup messages for upgrades
- The usual laundry list of fixes, tweaks, and refactors
Final Day
Usually I like to think I do an alright job of taking frequent breaks and making healthy decisions during these events, but that was not the case on the final day. The last 5 hours of the event were an absolute blur, and saw a bunch of bonus changes make it in as a result:
- Breakable items for bonus upgrades
- Melee enemies
- Wandering NPCs when not focused on player
- Better bullet momentum calculations to take player momentum into account
- Bullet momentum as an upgrade
- Weapon fire rate as an upgrade
- Scaling difficulty (enemy health/count per wave)
- The traditional rounds of bug testing and fixing
Without this blur of last minute additions the final submission would have been a lot more bare than it otherwise ended up being. Intended to be a quick game that did not last more than a couple minutes, it ended up being exactly that - the perfect length for the number of features involved.

Continuing Thoughts
Overall, another successful Ludum Dare for sure. As always, a 48 hour limit means some things get cut or never considered for implementation. From my original scribbles, the following two points were originally considered and did not make it in, both would be good spots to revisit outside of the competition:

As with any twin-stick shooter or bullet hell (which the later rounds quickly turn the game into) there is a near infinite number of creative shooting patterns that can be implemented, and the weapon numbers can be tweaked indefinitely. Additional enemy variety, some map variations, the potential modifications for a game like this are quite numerous. One update I did consider during development that did not make it in was a "safe zone" around the player that an enemy could not spawn within. Currently enemies can spawn anywhere on the map which can lead to some unfortunate incidental contact as the wave increments. A buffer zone would fix this issue, but I was afraid that it might also make the game much easier, and I did not want to spend the time implementing the feature to then have to remove it, and waste the development time that was already at a premium.
In theory it would be easy to implement though - get the random position on the map the enemy is destined for, get the current player position, calculate the difference, and if the difference is less than a threshold either do the whole loop again or move the enemy to the nearest position that is not within the threshold.
Conclusion
With this post, my Ludum Dare 51 is completed sans some additional game playing. Looking forward to the next one - as much as I enjoy this, some part of me is glad these only come around every 6 months.
Oh.

January. We will see. In the meantime:

Looks like the informational website did not quite get the memo.
#LDJAM "did" come less often. Keep an eye out for Ludum Dare 52 on January 6th, then Ludum Dare 53 at the end of April. https://t.co/KqjRhrvOvM pic.twitter.com/dSGhEJi9ve
— Ludum Dare (@ludumdare) October 5, 2022
LDJam: https://ldjam.com/events/ludum-dare/51/decarounds
Gitlab: https://gitlab.com/tharbagroup/ludum-dare-51/
itch.io: https://tharbakim.itch.io/decarounds