I really think that this edition of the Ludum Dare went way better then I could have ever hoped for.
I think a little bit of context is in order for you guys.
I have been on an all down mood ever since early to mid first quarter of the last year, trying to learn as much gamedev stuff I could possibly absorb. But I have been on a severe burnout for maybe a year now, trying to keep myself afloat mental health wise. Ever since last november I've dropped coding and game engine entirely in order to do something else trying to change the mood, so I had picked pixel art and tileset making because of that.
But if you picked my game to play you might have realized there's no pixelart besides developer art in this game, so what gives?
I picked this game jam with a purpose in mind: To finish the game, entirely on my on, and publish the game in it's most complete form, even if it only had crude art and gameplay with absolutely no sound, particle effects (although I could make it) or any art assets dedicated to illustrate the scenario better.
And... I finished the game. I could finish the game and publish it and I think the game is kind of good enough, lacking sound and polish apart...
But you're here to know what I have done, not how I felt about it, right? So let's go them.
-=+ The First Hours and Idea Conception +=-
I... have a confession to make:
I didn't intend to enter this edition of LDJAM. At all.
I wasn't in my best shape to do anything meaninful these past weeks, but it came to my knowlegde that LDJAM would be happening this weekend by watching Game Dev Underground inviting people to enter the event the weekend before. I mostly brushed aside the idea of entering, but I logged on the site to keepup with the theme voting until the day it started. I made my entry reserve and went to eat out with my sister and came back home about an hour after the jam had started. The theme: "Combine 2 incompatable genres".
"Whataf#¢& was I suppose to do with that?" I thought. "I barelly know how to do one genre, and they want me to do TWO?" Needless to say, I was on a hard place. Then I refreshed the LDJAM site front page, and got and article with a "genre combination generator" and decided to try it out. The first stuff that appeared on it was "Tower Defense + Shoot'em Up". I don't know how "incompatable" these genres are, but even after I tryed to generate a dozen other combinations this one stuck with me.
I knew what kind of Shoot'em Up I wanted to do: one with a 360 degree aiming system. I had started playing a little game from a solodev called "Dark Old Sun" that had this exact control scheme, and I knew how to implement a quick and dirty version of it on my engine of choice.
The idea to make the ship itself invincible, but that needed to circulate an objective that needed defending came naturally and I just needed to learn how to code the towers and tower bases to make the game work. I had ideas about enemies that had diferent behavoirs, but some goofies on my part kept me from realizing any of them besides the fact that I dedicated most of my time to make sure the core of the game was functioning as perfectly as I possibly could.
-=+ First Day, First Challenges +=-
As I said before, a number of goofy decisions held me from doing other, more interesting stuff, with my game. The first one was the movement system... Yes, I know. How could you f#¢& up THIS early you dofus!? By trying to use an input system for movement that I personally wasn't much confortable with, but that proved to be interesting for my game in the end: a "Subtrative Input System". Wahtaheel is that!?
A "Subtrative Input System" is an input system that takes the inputs of your preferable devices and, instead of testing for each indivicual input to determine the action to be taken, takes the input comands and make a calculation to determine which force to apply to your character.
Like [var = InputA - InputB;]; If InputA registers it will always pass a positive to the variable, InputB will always pass a negative and if the two register at the same time they cancel each other out.
The problem with this method of input reading: It becomes kind of a nightmare to do friction coding on acceleration physics with this method of input because you're not testing each state of input separatelly to determine where is the force been applied and when do you need to reverse it, creating kind of a "Zero Gravity" situation. Since my game was going to be set in space anyways I could ignore this problem fairly easily.
I also set of collision with the first obstacle I created: The Central Generator. I can safely say that it was the most fun part of making this game: figuring out that doing a collision to stop was going to create a lot of inconveniences to the player, so I changed the collision to stop for a collision to bounce and that created a very funny scenario where if you speed too quickly towards the generator you bounce off of it at the same speed, creating a ping-pong effect on the ship. That is where I also started creating the enemy_parent object with a basic AI to float straight for the core, ignoring everything else in it's path kinda like a zombie. It was fun, specially when I started to implement the money system: kill an enemy to gain one coin.
It was at this moment that I realized that my movement system was starting to create a problem. One was that I hadn't implemented a speed limit yet and even when I did the ship felt uncontrolable. Two was when I realized I needed to keep the player on screen because it was way too easy to just speed away from the screen into the eternal vastness of the beyond. Solved this issue by clamping the player ship position to the edge of the screen and cancelling their momentum completely towards that specific axis. Still feel like the ship is way too fast for the game even after I reduced it's maximum speed, but that is one of the things I think I didn't quite got right.
With that, movement was done, and most of my game was dependant on the next part.
-=+ Second Day, And Towering Headaches +=-
To say that implementing the towers was a challenge might be the biggest understatment I could have done. It was obtuse, confusing, stupid and just shy away from a nightmare. But that came right after I had implemented shooting for my ship, so that shouldn't have been THIS hard.
Y'know that moment when you implement one mechanic first try, no sweat, perfect k.o. and then think to yourself "Adapting that is gonna be a piece'o'cake! just need to convert the mouse pointer for a proximity detection code, set a timer for shot delay and range of agression and voila! Done!" but when you implement the code itself... It looks like you done everything right but the tower can't hit a target in front of it to save itself (and the generator you're trying to protect). Not only that, but the shot itself ins't even aligning itself corretly to the targets it's suppose to be shooting towards?
Let's just say that my second day was a really dificult match of "find the diference" between my player shooting code and the towers shooting code on which the diferences wasn't on wrong syntax but incredbly obtuse passing of values that were suppose to be passed from a diferent object altogether.
To fight the frustration I was acumulating from this simingly invisible mistake I worked on effects, trying to force the enemies to spawn outside the room (mostly unsuccesyful) and working on the tower/enemy economy. I made it so the towers would cost a number of enemy kills and have the same amount of hp, at the obvious cost that they could be destroyed if attacked enough times by the enemies. I experimented with the towers having a faster firerate than the player, but ended up with the opposite for the sake of balance. Turns out that six towers shoting twice as fast as you is kind of overpowered.
I wasn't getting progress on trying to force the enemies to spawn outside the room, so I created a portal effect and coded it to spawn a portal if the coordenates of the enemy spawn indicated a space on the visible portion of the room. I was also so frustrated with the detection code that I deleted all the tower interacting objects from the project, only to imediately regret my decision and franticaly dig my backup files in order to try and recover that code, which I did, and solved the issue of the detection code with a second look at the it where I realized I was passing the instance ids instead of the position of the targets. And a couple minutes later I had also solved the tower shooting issues, both the direction and the drawing ones!
It looked like I could finnaly dedicate a time to sound design, pixelart and non-coding related polish, I thought. Foolish me... Foolish me...
-=+ Third Day, No UI, No FX, No Losing Condition, Not much of a game... +=-
In retrospect I had the very fundamentals done, but I still had everything on a very crude, rough state. Not much changed until posting and finalizing the game, but what I had already from the days before was already good enough. I had a rudimentary UI system with markings for currency and current wave of attack although I hadn't implemented a wave system until the last hours of the end. I still needed a Menu->Game->Game Over->Menu transition, which I only did at the very end. And I was STILL trying to implement a dinamic dificult system in the game, which I still don't know if it works as intended due to number crunching going out the window so I could focus on getting the code done.
But bottom line is, I went into panic mode once I realized I still neede to make the most important code for the game to work: The Generator Health and Death Code! YES, you heard me right! I did not implement the losing condition until the very last hours of the jam. Luckly, almost everything went smoothly on these last hours, bar the f#¢&%£ up text exibition that happened from me importing the menu codes from my personal libraries and the Title Screen and game name, which I made literally MINUTES before the deadline!
But it was over. The Countdown reached Zero, and I was already setting up my crudely put together game page with the download link and the entry page. No time for screenshots, no time to work on sounds, nor art, neither time to think about the mess. The deadline was here and the game needed to go, lacking what it might've lacked.
Thankfully, when I finished setting my game pages I wasn't feeling defeated. I was extatic, joyful, proud of the mess I've made, but a mess I have made. A mess I had FINISHED.
Prior to this LDJAM I have taked Ludum Dare on the 38º edition, the "Small World" theme. I am proud of that game because I tryed something unconventional for me, doing art before the gameplay, again, all by myself. I am proud of how nicely the tileset and ambient came together, but there was nothing else but to platform away on the level. No UI, No VFX or SFX, No Losing Condition... Well...
Not much of a game...
But this time was diferent. Again, I lack SFX, but I have some, if only minor, VFX. I don't have music, but I have a spacey background with a purple space and with starts. My developer art is a bunch of hitboxes, but they are distinct enough from one another to inform most of what is important to the player. And my game has at the very least a losing condition, compared to my previous entries in other gamejams (I have two, not counting this one), one of them is a puzzle platformer with infinite lives, and the other is a platformer "walking simulator". I have failed repeatedly in some aspects (No SFX, No UI, Lackluster Presentation just to name a feel) but I AM clearly improving and this jam showed me that.
I'm proud of myself. I finished a game I can clearly say I'm proud of. It has too much room for improvement and I may not come back to it, but this is the very first time I can clearly say "I am proud of the final result".
-=+ Things I Learned / Reflections on My Mistakes +=-
There is a number of things I think I could've done to make the game better, and a couple of things I regret doing. Here they are:
* -= Subtrative Input System OR How NOT to use logic you are NOT FAMILIAR with =- *
Remember that mini rant I did about this on the first day of the jam? Let me reiterate for you: "A "Subtrative Input System" is an input system that takes the inputs of your preferable devices and makes calculations based on the comands to determine which forces to apply to your character."
Sounded so nice on paper, gave me so much headache on pratice. So I'M NEVER USING THAT LOGIC EVER AGAIN UNLESS SOME FORM OF INPUT I MAY WORK WITH IN THE FUTURE FORCES ME TO!!!
This is so obnoxious that I could not implement an friction system precisely because I could not know how to correctly identify the forces applied to my main character. With a test based input I know exactly where each force is, therefore, I know exactly how to cancel them out because I control when each force is applied AND for how long.
Making that change was a mistake that gave me too much problem on the long run. Again "Sounded so nice on paper, gave me so much headache on pratice".
And only now , as of writing this postmortem, a solution for that ocurred to me:
- Take the motion variable and make a
sign(var) off of it;
- Invert it's value so it can be multiplied by the acceleration variable;
- And make a test for
inputvar == 0;
- When no input is been registered it will apply
var += accel*(sign(var)*-1); AND ACTUALLY APPLY THE FRICTION!!!
You don't know how much I'm hating myself for this blunder right now...
* -= Leave the FX for WHEN you have SOLVED all the other ISSUES =- *
Yes, you heard me right. I kept trying to do effects at a very early stage of development and that ate away the time I could've used on solving stuff like the ajustable dificulty system I tried to implement. Should I had left the explosions and portals behind to work on the systems I might have solved the issue of dificulty balancing that ended up in the final game.
One example of it was the speed increase the enemies had at the begining of the wave system. It worked like a charm, but I had made a f#¢& up with the ramping up logic so enemies started rushing the player as soon as the first wave ended. Kinda like the next wave after the first was wave 150 instead of wave 2! But when I fixed the problem enemies started going on the opposite direction as they spawned, like their speed had been reversed. I could not solve this issue due to time constraints and had to scrap the speed increase entirely, but that is one of the many small things that I could've addressed if I didn't spend so much time on FX, animations and anything non-critical to the interaction with the game.
* -= Set. Shit. Up. In. Advance! =- *
As I said on the beggining of this post, I didn't intend to enter this jam edition, but once I did I should've have set stuff like my gamepage and itch.io page and, why not, the menus of the game in advance. Those are some of the things that made so much stress on me by the final hours of the jam that I couldn't believe it was over when it was. I separated various other assets I do own for use, but I did not package the codes I had and that also made a lot of stuff harder for me because I didn't have time to deal with any of this if I just used my pre-built librarys to speed things up.
I actually had to last minute pack and export the menu codes I had from another game I've made to use it since it was already done, but that f#¢& up my UI completely and I wouldn't have to deal with it if I had not that in advance. Same goes for my sound libraries, although I didn't use any of them because by the time I remembered where they were I was already on the final stretch and couldn't decide which sound to use where and the same goes for coding. Remember how much time I lost because I had to hardcode the input first!? Needless to say I also had a library for that and I payed the price for not been organized beforehand.
-=+ Closing Thoughts +=-
I had no idea how much I had improved on making games until after I finished this jam. I learned a lot about myself, my passion and my future. I feel like I improved far more now than what I had felt in such a long time because I could finally put to the test everything I took so long during burnout time to learn and improve.
If anything I can take from this event it will be the fact that it takes pressure to perform, time to improve and organization to realize potencial.
I did perform this weekend.
I'm striving to improve these next months.
I will organize what I have accumulated over these years to realize how much I can make things better in the near future.
And I hope to finally be able to reach my potencial soon.
Because now I know I can!