KyleTheCoder

Ludum Dare 48

LDJam 48 Lessons Learned for a Tactics Game

tldr version:

As a long-time jammer (Godot Wild Jam primarily), I was meta-thinking about LD48 and What Went Wrong :tm:, and my game, Tank Knight, and how I ran into some serious issues toward the end due to the fact I sort of hacked a bunch of the code together at the beginning. I've come to realize that even for relatively short-time-frame jams, you have to focus on making the code good before you can turn on the afterburners and produce the full game - because if the code stinks and you turn on the afterburners, it'll just explode in your face. While my code didn't quite rise to that level, it was definitely not great; there were a few bugs toward the end I just couldn't fix without rewriting the entire game system, and so I simply could not do it. The real issue is the code was so hacked together for the most part that I don't even want to continue it now, despite not receiving a lot of negative feedback. Speaking of which, y'all are awesome, and I love and appreciate every last one of you (even the more constructive criticism has somehow been kind to my game - not something you see in every jam). Next Ludum Dare, I will create something with a little bit smaller scope, and a little bit better art.

Extended analysis:

As a fantastic Godot developer (if I do say so myself - see GodotNuts GodotFirebase library, which I created and am the primary maintainer), I was most disgusted when reviewing my code toward the end with my approach to handling buttons. Little known fact: I'm a bit obsessed with custom resources and have a whole YouTube series on them. However, something - not entirely sure what - went horribly wrong when using them to identify my spells. The problem really was I had too many things going at once: a spell button, a spell ability, and a spell resource. After much lamenting and not being able to figure out one specific bug, which later turned out to be completely unrelated but I had no way of knowing at the time, I ended up pulling out the custom resources. They were, after all, empty; I just used the base Resource class as my resource to identify spells. Despite the fact that that was definitely not the cause of the bug I was seeing, I now believe it was the primary issue in preventing me from "turning on the afterburners" as mentioned above, because to create one new spell, it required three separate classes be defined, and each one was independent. At the least, it would have been way more effective to have the resource actually be a custom resource and hold onto a packed scene of the spell ability itself, as well as the spell button. This would have made it so I could have it all in one place, load up the folder with a FolderResource (my own invention - loads all resources in a folder into memory), and when you "get" the spell, just add an instance of the spell scene to the player, and an instance of the button to the bottom row. This would have been so much simpler, and also, incidentally, given me a place to hook into them without having to use groups. I love groups and am fine using them pretty regularly, but for this game there was just too much confusion in the code around them, because I had to try to find ways to hide/show buttons and had no way to actually reference them. The custom resource for holding them would have been perfect: the resource could also retain the button instance, and then I could have made a much more important decision about how to build out the game, which is...

I should have build the game as a MainLevel (or whatever you want to call it) that loads sub-levels. The main level would be more like a global, always-running scene, and the sub-levels would simply be queue-freed and swapped out. I could then place the character (who would be part of the MainLevel) in its starting square and not have to worry about reloading the UI every single time almost any action is taken. Because of how I had to work around level load timing and rebuilding the UI, it really ended up causing me to use a lot of call_deferred, which in general sucks and makes your code more brittle (since you can't be sure what order things are going in when things are all happening "on the next frame" rather than "right now").

The main mechanic I had was pretty effective despite having way too many classes needing to be made per ability, but I think separating the abilities away from the actual player would have helped tremendously as well. It would have been a little bit harder in terms of targeting and such, but ultimately much easier to add new abilities. I had 3-4 more abilities planned that I just couldn't get to, including some pretty creative ones like rocket punch and diagonal sword throw. One issue I had was with PermaFire, which is a great idea in my mind (throws a flaming pile of fire onto the ground that sits there and damages every character that enters it). I had the ability as part of the character's tree, so when it was placed, it kept moving with the character. I suppose I could have just put a Node down first to remove the transform, but I didn't think of that at the time, so I had to find a real ugly way to to duplicate the node itself, then add it to the root tree and manipulate the collision shapes. It was painful af.

As a final note, just as a tip for you, if you ever want to make a turn-based game, it's best not to put the while loop (if that's what you're using) for the turns into your _ready() function. The best approach I found was creating a 1-shot timer to run a function which starts the turn-based part of the game, and put the while loop in that handler. While I don't know that there's a specific problem with _ready(), I found some odd things happening, I suspect because it wanted them to finish in a reasonable amount of time so it could continue with processing, but I'm not sure - just weird stuff would happen sometimes like not recognizing there were still turns left, and so on. That is all for now though.

Now, back to playing your games, you incredible monsters!

Ludum Dare 50

In like Anne Boleyn

Excited to produce yet another masterpiece with the Godot game engine. Have a real artist this time instead of my awfulness, though I'm considering doing both the compo and the extra.

If you have any Godot questions, or you're using Godot Firebase (my plugin) for any reason, feel free to ping me, happy to help!

Ever made an application for the jam?

Has anyone ever made an application rather than a game, but still fit the theme? Some of the themes in this jam are particularly good for it, like combine, garden, out of order, and so on. They wouldn't be "fun" in the traditional sense, I assume, but with engines like Godot, making an application really isn't vastly different from making a game.

Ludum Dare 53

The Silver Fleet method

Not really a post-mortem, nor even a retrospective, just some things I did on The Silver Fleet that made all the difference for a short jam.

Exaggeration is key. You only have so much time, so make things big. Don't think you need screen shake? Include it anyway - you're a self-respecting indie dev, after all! All of your features should have a bigger impact than you'd think. For Silver Fleet, one of the key ideas I had was having to juggle enemies by hitting them with your sword, pushing them back, and them coming back. For most enemies, I made that pushback pretty large, and one I had originally made so large he'd fly off the screen. I ended up having to trim that way down because he actually flew straight off the end of the boat if you hit him even once, but he's still in there! And to counter that, I had two "heavy" enemies that barely moved: they are the challenging ones with the red shirts on. (I only just realized the tie-in with Star Treks redshirts, holy moly!)

As for coding it, it was much easier than you might think. Godot supports "areas", which are just places that physics bodies can enter and trigger a notification. Godot 4 now also supports something called Callables - a variable representation of a function. I have a Callable defined that represents what happens if you hit the one button when you're in an area. The initial/default one is swing_sword - if you aren't in any special area at all, it defaults back to this.

The first area I made was the pit area. This is what you jump over with the rope, so I guess the rope is more the area, but you get my point: there's an area around the rope that if you hit the button, it has you swing over the pit (big hole in the boat from cannon fire, was conceptually what I was going for). That means you can't also swing your sword while swinging on the rope, but I deemed that an acceptable trade and decided I'd work around it with the design (only loosely did that come through - by the end, I had so little time that this decision ended up being really challenging). Other areas include: bowling cannonball area, level win area (doesn't switch anything, but is useful), and I think that's it.

Which leads me to my next point: use areas or your equivalent for your engine as much as possible. They are probably the most useful Godot node available and let you gain insight into what your game is doing at times. One funny trick I learned in a previous jam that I'm including here but wasn't in Silver Fleet: create areas that turn on or off other areas. This is how you can get super-complex puzzles and stuff, and you can automate turning on and off with animations, so you can open a door to the holodeck (for instance), or blow off half the ship where if you go into it, you start to lose health.

You can typically make those new areas (B/C for future purposes) into children of the initial area (A), which sounds confusing, but lets you do something nice: instead of making A have exported nodes or node paths to B and C, which isn't scaleable at all if you need to add D, E, and F, you just make B and C children of A and then any future children can be the same type added to the node. Then A just looks at its children and works on them logically appropriately. Sometimes this will mean making parts of your game just become hidden and turn off physics (or become free), but that's not so bad. It also means, if B and C are always going to be children, that when you add A to your main scene, you just make A have editable children and move B and C to wherever they need to go. The position isn't really relevant (or shouldn't be) to A's processing logic, so B and C can really be anywhere!

And this leads to my final point: game engines typically don't give you the ability to make games immediately. They give you the ability to make pieces of a game that you can then put together to form a game. You have to get used to this concept, and build a lot of pieces, during jams (and for your real games!), and then put them together in new and interesting ways. An example of this was having enemies in the rigging in my game, so when you swing on a rope, you can hit them. I made my rope area so that if you do hit the button while in the correct area, it would swap your action back to the default action automatically. This made it so you could kill enemies up in the rigging, which added something great to the design! I wish I had used that more. Oh well.

That's all for now. If you have any Godot questions or questions about Silver Fleet specifically, let me know! I'm always happy to help anyone.

Godot 4 project conversion guide

Hey all. I created this guide quite a while ago but it's still relevant! You can use it to convert your Godot 3.x projects to 4.x and it'll help a lot in the transition. For more advanced users, use this: https://gist.github.com/WolfgangSenff/168cb0cbd486c8c9cd507f232165b976

For an actual conversion guide for people just starting to transition to Godot 4, use this: https://gist.github.com/WolfgangSenff/0a9c1d800db42a9a9441b2d0288ed0fd

Feel free to add comments where needed! I'm happy to make updates. I should have posted this pre-LD53, but didn't think to until just now, sorry about that friends!