BRANDON FANNIN
  • Home
  • About
  • Résumé
  • Blog
  • Contact

Adventures in Game Development

Week 17/18 - Pausing

4/25/2025

 
Did not intend for these last bunch of updates to all be doubles, but that's how my free time ended up working out. Anyway, I managed to clear off the last two tasks off my list, so this will be my last update for this particular project. At least for a good while anyway, never know if I'll loop back around and finish the job later on. For now though, let's get into the details.

First up, I've got a pause menu now:
Picture
I had to tweak my viewport settings a bit and add some functionality to my camera manager to get the fade to work properly with UI layers, but besides that it's a pretty simple matter of setting the world timescale to pause, while setting the pause manager itself to only be active when the timescale is 0. Fun fact about Super Metroid's pause menu: the game is still running and accepting inputs while the fade to black is happening. As such, it is possible to cross the barrier to enter another room while in the middle of pausing. In this situation, the game cancels the pause sequence and instead transitions rooms, starting the fade at whatever value it was already at.  My system unfortunately can't support that sort of interaction without adding in quite a large chunk of functionality, so I elected to simply disable the door triggers while pausing.

I didn't end up getting the map screen fully functional, but I was satisfied that I had gained all the knowledge I needed for how to set up UI, so I elected to move on. 

Now, for the sound system... I can't exactly "show" the work I did here without recording actual videos, so I'll just do my best to explain what I did instead. The sound manager runs with two object pools, one for creating AudioStreamPlayer objects, which handle global sounds, and one for AudioStreamPlayer2D objects, which handle spatial sounds. When you want to create a sound, you pass the audio manager a reference to the file you want to play as well as whether or not it's a looping sound, where to play the sound from, and what object, if any, you want to attach it to. The manager gives you a reference to the sound emitter so that you can stop it manually if needed, and when the sound finishes playing, it uses the "Finished" signal to return itself to the proper pool. 

I also created an "AudioTrigger" script, which holds a dictionary of sound files that you can retrieve through name strings, and attached that to the object that I want to play sound effects (the player, in this case).  With the audio trigger present, I can do things like trigger footstep sounds from the player's animation whenever the sprite's foot hits the ground, or start and stop the spin jump sound effect whenever the player enters/exits the relevant state. 

Besides that, there's not much else to say.  I also set up music to play and made it so that it can transition between songs properly when changing rooms, as well as learned how to properly loop music rather than having it fade out/in whenever the song "ends".


And.... that's about it. at some point I will loop back around and clean up my code so that I can post this project as part of my work samples, but for now I have accomplished my goal of learning how to bend the Godot engine to my will. Current plans are to take a week or two to do some other studying for job search purposes, then I'll be back to start work on my first "real" Godot game. 

​See you next time. 

Week 15/16 - Cartography/Saving

4/11/2025

 
Didn't have time to write a blog post last week, so this week you get a double update. For the past two weeks I've been working on the map and saving systems. There's really not much to say about the save functionality, other than the fact that it employs Godot's resource system, which turns out to be very simple to use in that capacity. Basically I just made a resource class that contains all the data I want to keep track of, and then I copy that data from/into the actively running game to save or load. I had to rework a few systems to allow for mid-game loading, but that's about as far as the system goes. I can't really show it in action within the scope of my .gif maker either, so I suppose you'll just have to take my word that it works as intended.

Now as for the map... I decided that the best way for me to implement Metroid's specific style of map was to use tilemaps. Rather than just using a single tilemap and changing each cell based on whether the map tile has been revealed, explored, or still unseen, I went with several tilemaps stacked on top of each other. The "hidden" layer is on top, followed by "revealed", "explored", and "occupied". This makes the map itself a little bit of a pain to set up, since I have to draw several different versions of the same geography, but it does make things much simpler at runtime, allowing me to simply hide individual tiles on each layer as the player discovers more of the map. 

The map itself is currently hidden in game, and will remain that way until I can get the pause menu up and running, but I did also get the mini-map working. I considered just using a second camera pointing at the map proper and projecting it onto the HUD, but I found it difficult to maintain the proper visual with that approach. Instead, I made use of another small tilemap on the HUD.  This tilemap looks at the current state of the full-sized map and simply swaps out the tile sprites to reflect the map state in the player's immediate vicinity. 
Picture
A simple timer hooked up to a visibility toggle gets me the effect for the blinking tile on the player's current position. I ran into a little bit of trouble getting the map to play nice with the instant-load system I have hooked up for debug, but it turned out that I was accidentally using C# syntax for one of my for loops instead of GDScript. Turns out it's hard to drop 10 years worth of muscle memory, who would have guessed?

With these two features in a state that I'm satisfied enough with, we're just left with Sound and the Pause menu for implementation. Getting pretty close to the end here now, and my brain is already at work trying to churn up ideas for what comes next.

See you next time.

Week 13/14 - Room to Improve

3/21/2025

 
Alright, it's been a hot minute since the last time I was able to give an update. Life got a bit hectic so I had to take a bit of a hiatus from my project work in order to deal with everything, but now I should be more or less back on my normal work schedule. 

So this update is probably roughly equivalent to 2 weeks of actual dev work spread out across a little over a month, and what have we done during that time? Well, I introduced the concept of "Rooms" to the codebase, which store data for the tile sets and trigger volumes of a small chunk of environment as well as map coordinates (which will come in handy later). They also indirectly hold information on their neighboring rooms via the newly added transition triggers I made, which in turn allows us to move from room to room. 

And that's really what I spent the bulk of the time working on; room transitions. In Metroid, when the player walks through a door, they don't just simply appear in the next room, the game pauses, everything fades to black except for the door itself, the camera pans in the direction of the new room, and then everything fades back in before gameplay resumes. This process hides any load jitters while also being pretty visually appealing at the same time, but each step of that process involves a new system that I had to make.

Pausing the world is relatively simple thanks to Godot's timescale and Processing type options, just need to select the top-level node and tell it to pause, and set a few choice objects to be able to continue to run their update loops even when the timescale is paused. The fade involves attaching a giant black rectangle to the camera and adding scripts to allow it to transition from one color to another over time, and the actual camera movement only needed some slight adjustments to the camera manager system I set up as part of my last update. In order to get the whole sequence put together, I also had to figure out how callback functions work in Godot, which luckily ended up not being that much different from what I'm used to in Unity.  Technically I could have just used signals to get functions to fire when I need them, but having to connect and disconnect to signals repeatedly every time I ran through the process seemed like a lot more work than just passing in a callback function.
Picture
There's a little more magic happening behind the scenes when it comes to placing the rooms in the proper position in the world and making sure the player's movement and height are carried over between room transitions, but that's just some simple math at the end of the day. 

Now, as for what's next.... 14 weeks is actually a pretty short amount of time when it comes to game development, but the fact of the matter is that this project was supposed to be a relatively short one. Theoretically I could keep chipping away until I more or less recreate the whole game, but the point of this exercise was to familiarize myself with the Godot engine before I move on to working on something of my own. To that end, I have made a list of topics/features that I want to cover before I can declare this project over. Here's what we have left:

- Mini-map
- Pause Menu
- Save/Load
- Sound and Music

I've determined that basically everything else on the feature list I originally wrote up is either something I have already figured out how to do during my time with the engine, or something that the engine doesn't meaningfully effect the implementation of. As such, those won't be much help as a learning tool, and I'd be better off spending my time elsewhere. So all things considered, we're actually pretty close to the end here. I've been doing some thinking about the project I'll be starting up once I'm done with the Metroid stuff, and I'll talk some more about that when we get there.  For now, next thing on the docket is the map functionality.

​See you next time.

Week 12 - Tracking Progress

2/7/2025

 
Okay technically we missed a progress check-in last week, but I've been busy with job search matters so I had to put this project on the back-burner for a little bit. This past milestone has been all about our game's camera: getting it to follow the player, controlling where it can and can't go, and handling transition behaviors.

The good news here is that I learned that Godot has a lot of really nice built in camera functionality. It's got smooth follow, tracking bounds, and even built-in deadzone options.  The bad news is that it turns out I couldn't use most of these features for my purposes and had to write my own camera manager instead. So why is that? The short answer is that the default functionality of the godot camera was at odds with the camera design of Super Metroid. This was mainly evident in two areas: tracking and bounds.

For Camera Tracking, Godot has set up its cameras to use a very common design for side-scrollers known as a deadzone.  The idea is that if you are in the middle of the screen, you can move slightly to the left or right before the camera actually starts moving to follow you. This makes the camera feel more dynamic and more smooth than if it simply always tried to keep the player in the exact center. Super Metroid doesn't do that though, rather the camera moves slightly ahead of the player as they move in a particular direction, moving them to the "back" half of the screen to allow them to see farther forward. This makes sense for a game where your primary attacks are projectiles, as it gives you warning for things ahead of you so that you can better engage at range. For this purpose, I built the camera manager to have the camera track an invisible point that moves in whatever direction the player is going, up to a defined limit in each direction.
Picture
For the camera bounds, Godot has some built-in variables that you can set to tell the camera not to pan past a certain point. This works fantastically, the only problem is that if you ever try to change the bounds of the camera, say when going through a screen transition, the camera instantly snaps to be inside of the new bounds rather than transitioning to it smoothly. Technically Metroid's camera deals with this in two different ways depending on the specific trigger. Either the camera will simply do a slide transition to its new desire bounds, or the camera will have a ratchet effect applied to it, where moving closer to the bounds shifts the camera as normal, but trying to move away will have it remain in place. 
Picture
As you can see, I got it all working, it simply took a bit longer than expected. Anyway, hope you all enjoy the little primer on camera design. Next up I'll be moving on to real room transitions with all the added fun of scene/asset loading. 

See you next time.

Week 11 - Drops

1/24/2025

 
Couldn't think of a stupid joke for the title this week.  Anyway, I started off things by reviewing my list of goals for this project and I ended up cutting a number of things from the queue. My primary goal here isn't to recreate the entirety of Super Metroid, but to use existing designs in order to get used to using Godot. to that end, I removed things from my todo list that I have already figured out how to do in the engine, which will reduce the amount of time I need to spend on this training arc before I can start building something for real.

As for the actual implementation work for the week, I didn't run into any real surprises. First up, I finally added death effects for my enemies, though I did have to use the morphball bomb explosion effect as a placeholder, at least until I can find and slice up the real enemy death explosions.
Picture
The real explosions in the game do a better job of hiding the sprite pop, but functionality wise this one is done. Next was getting enemies to drop items when they die. Again, this was pretty simple in itself; I defined all the different types of drops, made them increment the player's stats when collided with, and set up data resources so that enemies can define their own drop rates for each type of item. Thing is, Metroid actually has a bit of a system when it comes to item drops: items don't drop if the player is full on that particular resource, and the drop rates of other items that the player is missing are boosted. I did not replicate the behavior exactly as it appears in the games, but I made a close approximation. When an enemy wants to drop an item, the Drop Manager looks at the player's current status. It only takes into account drop weights of resources that the player is currently not full on, skipping over those that are already topped off, and thus making sure that only things that the player needs will spawn.
Picture
While I don't truly have logic for missiles, super missiles, and power bombs up and running yet, I did still create the full suite of ammo drops as well.  

And.... that's about it for this week. Next up, I'm planning on shifting my attention to Godot systems that I'm less familiar with, specifically camera control and scene transitions. Once I get the ability to swap rooms working, hopefully I can start to figure out how save data works in this engine.

​See you next time.

Week 10 - Heads Up

1/17/2025

 
Another week down with a good amount of progress made. Following up from last week, my primary goal was to finish the player's damage interaction, which meant I had to set up a few extra systems.  First up, we need a way to actually keep track of the player's health, so that means setting up some UI. I created a UI Manager script, defined a basic "UI Screen" to hold shared functionality, and then went about making the HUD from there.  Luckily, unlike many of my past experiences with the art assets I'd been able to find myself, the sprites for the UI chunks I had needed minimal amounts of work in order to get in to "game-ready" state. So, after looking up some basic guides on how to use the UI nodes in Godot, I threw together my replica of the Super Metroid HUD.
Picture
Not bad, eh? I'm not planning on implementing grapple beam, reserve tanks, or X-ray visor for this little project of mine, so I left those bits out of my setup. Next step was actually getting those values hooked up to real player stats, which... lead me to rearrange some of my architecture first. Previously, I just had the player, level, and enemies thrown under an empty node for organizational purposes, but I ended up finally making myself a real "Game Manager" script to exercise more control over how the program runs.  Instead of just using Godot's built in "_ready" function to set up values at game start, I introduced Initialization functions to key scripts and had the Game Manager trigger those in correct load order.  In simpler terms, I needed to be able to make sure certain values were set within the player instance before I could hook up my new "Player Status" script and properly connect the HUD to that.

Speaking of Player Status, that script is effectively just a data holder used to keep track of stats. At the moment it holds the player's max and current health, as well as max and current ammo counts for missiles, super missiles, and power bombs, but it will eventually hold data on what power-ups have been collected and what items are equipped. Basically, this thing will be what I eventually turn into save data once I start working on that system.  For now though, it has been properly hooked into the HUD, which updates the relevant fields as necessary. 
Picture
Energy tanks are shown/hidden based on what the player's max health is, and the icons for your various types of ammo are set to hidden if you can't hold any of that ammo yet. And of course, this all updates in real time as the player's stats change.
Picture
As you might be able to see from the clip above, I also got my i-frame flash working as intended. That one was thankfully as simple as I thought it would be.

For next week, current goals are to get enemy drops working so that there's actually a way to make those numbers go up instead of just down, and also finally maybe make proper hit and death effects for my poor enemies. 

See you next time.

Week 9 - Ouch

1/10/2025

 
Back to work after the new year.  There's not a whole lot of visual progress this week in comparison to earlier updates, but I still got a decent amount of work done. Under the hood I made it so that weapons actually apply damage to enemies instead of just instantly killing them, made them die properly when their health hit zero, and added in functions that allow entities to modify incoming damage values.  I also setup damage property flags to represent different types of incoming damage and made it so that enemies can be set to be immune to specific damage types. That will come into play relatively soon when I start adding in bombs, missiles, and different beam types.

With that set up, I also added a little bit of polish to the damage sequence so that we now get that classic sprite flash when something gets hit by an attack:
Picture
The system I made for this should be pretty versatile, able to take in lists of colors, frame counts, and duration to create looping effects. In theory, it should work perfectly for when I get i-frame visuals up and running. Speaking of player damage, I also made it so that enemies can damage players and even apply knockback to them.
Picture
I had to at least stub in invincibility frame logic to prevent them from applying damage continuously, but I will be adding visuals to let the player know when they're active in the near future. 

That's about it for progress this time, because I actually spent a good portion of the week getting sidetracked by research.  While trying to figure out the best way to handle collision detection for enemies, I stumbled across a post talking about physics optimization and kinda fell down a rabbit hole for a bit.  Evidentially Godot has systems called "servers" that handle all of the engine's rendering, physics, and computations under the hood.  While the Node system is very user friendly, it's not the most efficient in terms of processing, and so it can start to hold you back when you have a large number of nodes active at the same time. You can apparently get around this issue by polling the servers themselves instead of just using Nodes. 

This video does a pretty great job of showing the differences in the two approaches:
It's not quite as simple as they make it sound, especially if you want bullets with non-linear/non-standard movement, but the potential performance gains are pretty obvious. Now, this isn't exactly important for my work on this project because the number of live physics objects in any given scene will always be low, but it's pretty vital information for some of my future plans. 

We'll talk more about that when I start getting closer to checking everything off my todo list for Metroid though. For now, my next goals are to finish sprucing up my enemy damage effects (VFX for hit and death), adding visuals to the player's i-frames, and then starting set up the HUD so that we can actually see how much health the player has.

See you next time.

Weeks 7/8 - Adversary

12/20/2024

 
Ended up missing my update last week because I lost a significant amount of dev time to a nasty stomach bug, and holiday obligations ended up interrupting me on more than one occasion, so these two weeks effectively combine into a single week's worth of work. 

So what did we get done? I fixed a few bugs that cropped up with my tile destruction system, as well as implemented basic architecture for enemies and created our first enemy. I wanted to stick with something simple enough for my initial foray into enemy implementation, so I decided to go with one of the first enemies you encounter in Metroid; the Geemer.
Picture
Or at least that was the plan, but because of my struggles with Super Metroid Sprites, I ended up using the Metroid Fusion equivalent of the same enemy design. It's called an "Owtch", which really is a top-tier name.
Picture
Now, it's not that I couldn't find sprites for the Geemer this time around, just that they were cut up in a way that was a bit nonsensical and putting them together would have been a small nightmare. Besides, the Owtch does exist in Super Metroid so it still counts.

As far as enemies go, these guys just move along flat surfaces, following the geometry of the terrain as they encounter walls or ledges. Very simple to the player, relatively painless in terms of coding. For something like this you just need move forward and have one raycast downward and one facing forward to check for walls or cliffs.  If it finds one, play an animation to smooth the transition and update which directions the enemy thinks is "forward" and "down" so that the new surface becomes its "ground". 

Godot seems to have some interesting quirks with raycasts, such as them not being able to properly detect surfaces on the first frame the enemies exist, or needing to create a "query" object in order to actually use them, but besides that they behaved mostly as expected. 
Picture
Picture
Most of my issues involved two main factors: getting the sprites to properly reorient themselves to the surface they are attached to, and getting the enemy to properly re-attached to a surface after it encounters a cliff (the movement shown in the gif on the right). The former issue is born from the fact that I only actually have sprites for when the Owtch is upright or attached to a left wall. For ceilings and right walls, I need to carefully time a sprite flip when the transition animation finishes. You can probably see a little bit of popping in the gifs above when the enemy finishes rounding the top-right corner. I have since fixed that particular issue but didn't have time to grab new screenshots before making my post.

The second issue involves the fact that when the enemy encounters a cliff, there is a frame or two when it's in the middle of it's transition animation where it's not technically touching the ground at all, and early on in my tinkering it thought it was just constantly encountering cliffs when this happened, leading the enemy to spin in place in the air. The solution to this one was to shift the source of my ground-detection raycasts based on what part of the transition it is in. when it knows its firmly attached it searches from the back edge of it's hitbox, but while its in the process of transitioning around a corner it looks from the front edge instead.

Luckily, it seems the way I set up the movement logic on these guys plays nice with the destroyable terrain. I'm going to need to add in some safety checks to make sure the destructible blocks can't reform on top of an enemy, but I was honestly going to have to deal with that for the player anyway.
Picture
With all that working, I added actual health tracking to enemies, made it so that projectiles can actually hit them, and made it so that they can die properly.
Picture
Still need to add death VFX of course, as well as making it so that enemies can hurt the player as well.  Those will probably be in my next list of goals.  That being said, this should be my last update for the year. The holidays are basically upon us and I'm not going to be able to spend much time at a desk. 

Happy Holidays to anyone reading, and see you next time.

Week 6 - Lay of the Land

12/6/2024

 
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:
Picture
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:
Picture
Definitely an improvement visually. As a bonus, I also figured out how to get slope movement working properly.
Picture
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.
Picture
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.
Picture
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.

Week 5 - Jump and Shoot

11/22/2024

 
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​.
Picture
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.
Picture
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.
<<Previous

    Archives

    April 2025
    March 2025
    February 2025
    January 2025
    December 2024
    November 2024
    October 2024

    Categories

    All
    AI
    Animation
    Attack Logic
    Camera
    Clean Up
    Enemies
    Game Development
    Godot
    Level Design
    Music
    Optimization
    Player Mechanics
    Projectiles
    Project Start
    Research
    Sound
    State Machines
    Super Metroid
    Tile Maps
    UI
    VFX

    RSS Feed

Proudly powered by Weebly
  • Home
  • About
  • Résumé
  • Blog
  • Contact