No update for last week, between the Holiday and a few personal obligations, I didn't really accomplish much worth talking about. Mostly I just did some research into my next project goal; tile sets. Turns out Godot has plenty of tools to make setting up tile sets particularly simple, and a bunch more tools to give you just about all the control you could need. So, armed with a bunch of new knowledge I started off this week by... realizing that the tile set sprites I found for Super Metroid were incomplete. Honestly, I'm finding more and more that the Super Metroid sprites that I have access to are far from the comprehensive collection that I had first thought they were. The GBA Metroid games on the other hand, have proven to be quite thorough. In this particular case, the sprites that I was missing were these little guys: These represent tiles that can be destroyed by specific weapons from Samus' arsenal. For some reason, all of the sprite collections I could find for the Super Metroid tiles only had the tiles representing Speed Boost and Power Bomb blocks, and I did quite a bit of digging. Those ones up above are specifically the versions from Zero Mission, and since these are lower resolution than the tiles from the SNES, I've decided to just use the GBA tiles in general moving forward. I would do that same with Samus' own sprites to keep things consistent, but redoing all of the animations, let alone having to clean up and repair the sprite sheets would likely take more than a full work week by itself. If it bothers me enough as I continue through this project I'll consider revisiting the issue later, but for now we'll simply have to live with it. Now, getting the tile sets working within Godot was actually pretty fast and easy once I found the sheets I wanted to use. I messed around a bit with setting up the auto-tiling tool with a few different terrain types, applied physics shapes to the individual tiles I was using, and then went about replacing the white block platforms of my test scene. Here are the results: Definitely an improvement visually. As a bonus, I also figured out how to get slope movement working properly. Usually that's a massive pain, good on Godot for having built-in systems to handle it. In any case, because getting the tiles in went so smoothly, I moved onto the "stretch goal" that I set myself for the week; tile destruction. This is something that I've been thinking over for a decent while, and I think I came up with a pretty decent solution. Tile maps in Godot are considered to be a single object, so no matter what tile a projectile hits, it returns the tile map itself as the object it hit, and the tiles themselves don't have any logic attached to them. That means that I can't attach any sort of "Destroyable" script to tiles that I want to be able to blast away. Instead, I leveraged the ability to create multiple tile map layers, and I placed tiles on a second layer to signify both that they can be destroyed, and specifically what they can be destroyed by. When a projectile registers a collision with a tile map, I get the coordinates of the tile it hit and see if a corresponding tile exists on the "destructible" layer. If it does, I check to see if that tile can be destroyed by the projectile that hit it before removing the tile on both the "destructible" and "terrain" layers. I then spawn a pooled object that plays the tile destruction animation while also storing information about the tile in question, include what type of tile it was originally as well as whether or not it will need to reform after a few seconds (since that's a thing that happens sometimes in Metroid games). Reformed tiles only show the "destructible" layer version of the tile, since that's how it works in the source material. There's still some work to be done here, such as how certain weapons can reveal a destructible tile without actually destroying it, but that sort of stuff is probably going to have to wait until I actually get more weapons implemented. First though, I think I'm going to make my next goal getting a basic enemy working, that way we have something besides the ground to shoot at.
See you next time. We're just over a month into it now, and at this point I think I can say the whole blogging strategy is working pretty well. Forcing myself to sit down at the end of the week and measure my progress has definitely made me feel like I'm getting more done, even in the cases where I'm not working at a noticeably faster pace. But, that feeling of accomplishment helps boost morale, which in turn does actually make me more productive. I feel like at this point my output is quite a lot higher than it has been in a good while. Now for the actual progress report; In this past week I have built a pooling system, got basic projectiles working, and threw together a weapon manager for the player. All that is to say, you can now jump and shoot. As a quick aside, I looked intro trying to fix that little leg twitch Samus has at the top of her jump, but there's simply no easy way to do it. I'd either need to redo half of my animation tree, write some incredibly specific code to try to force a behavior that doesn't want to happen, or tear the whole thing up and write my own custom animation manager. Needless to say, since the whole point of this project is to learn, dealing with that isn't exactly high on my priorities. I've learned enough at this point that if I needed to set up animations like this on another project, I could build the systems in a way that better suites my needs, and I'm satisfied with that. Now, object pooling.... For those not familiar with games programming, here's a quick breakdown. Whenever you need to create or destroy a new instance of an object, that takes up a decent chunk of time/processing power. When it happens often enough, or if you're trying to create new instances of particularly complicated objects, that can easily lead to framerate drops and game stutters. Object pooling is a solution to this; instead of creating a new object whenever you need one, you create a bunch of objects ahead of time to setup a "pool"(usually during a loading screen). The object in the pool are just turned off and hidden until they are needed, at which point you switch them on and put them where they need to be. When you're done with an object, you turn it back off and return it to the pool. This is a pretty standard technique in the industry, used for things that we would otherwise need to create and destroy with some frequency. A few common examples would be bullets, item drops, and sometimes even enemies. Now, this is usually a pretty simple thing to set up, but Godot's quirks forced me to do a bit of experimentation this time. Godot doesn't support Multiple-Inheritance, a programming concept that's a bit harder to explain for those not already in the know, but the simplest explanation for my situation here is that I can't have projectiles be both physics entities and pooled objects at the same time. That forced me to revise my implementation of pooled objects a bit, but I'm actually pretty satisfied with the results. Basically, instead of telling something that it is a pooled object, I made pooled objects something you attach to other objects. Once attached, the pooled object has the ability to hijack whatever its connected to and turn them on or off as the Pool needs. This means that any object I make can theoretically be pooled, not just ones that I specifically design to be. For the projectiles themselves, I had to wrestle with Godot's Rigidbody system a bit more than anticipated, but I eventually got everything working as desired. The bigger lift here was actually making sure the projectiles spawned where they were supposed to. Samus' arm cannon doesn't have consistent positioning between different animations, even if it's aiming in the same direction. In order to deal with this, I had to go into every single animation and key in a position for the projectile's spawn point. Tedious work to say the least, but hey; it's done. One other thing of note; while I was setting up the projectile sprites, I discovered that the sprite sheet I'm using is actually missing quite a bit of content. It has all the sprites for missiles and bombs, but it only has the basic power beam and the fully upgraded ice beam... not any of the combinations in between. I was unable to find any more complete sprite sheets for the Super Metroid projectiles, so if I end up taking this far enough to want to do more than one beam power up, then I might need to substitute in different projectile spites. I was able to find a complete sheet for the GBA Metroid games, so in that scenario I might switch over to using those instead.
That's it for this week though. Not 100% sure what the goal for next week is, trying to decide between making an enemy to shoot at or getting tilemaps set up so that I'm not standing in a white and grey void any more. See you next time. |
Archives
April 2025
Categories
All
|