It feels like my game will focus on shooting weapons, so here we go. Another core gameplay feature that I need to make feel good is shooting weapons. (It seems like every other part of the game is “core gameplay” that I need to get done well. Hopefully, that just means I have been working on the important stuff and not feature creeping.)
The player fires their weapon at wherever they click the mouse. Obvious first thing to do is to actually point the weapon the player is holding to where the mouse is. I guess I can just rotate the sprite to whatever direction the mouse is?
Okay, may be not “just”. I need to flip the sprite whenever the angle is visually “opposite”:
The weapon is pivoting around the sprite’s pivot. However, I want the weapon to be “carried” with an offset. That way the player is holding the weapon slightly away from themselves. In other words, the weapon is to be held by the grip/stock at its pivot:
I also need to avoid the weapon flipping too often when aiming directly up/down. This can result in it spazzing out flipping back and forth due to small mouse, player, or camera movements. Instead, I have a small error allowance:
Since my game is fake-2.5D, I can simulate some of the supposed verticalness by having the weapon move further on horizontal axis than on vertical axis (exaggerated greatly here so it’s obvious what I mean):
I am not 100% sure this is something I actually need or that anyone would notice, or that not having it lessens the game feel. But I think it will be more obvious when wrong once my player has a real sprite with hands.
The carrying offset properties are stored in the weapon definition and are just two values. Both really depend on the sprite size.
Next thing I can add is a muzzle flash. At its simplest, it’s just a sprite that is toggled at the weapon’s barrel for a brief time every time the weapon fires. And that simple logic works nicely and adds greatly to the feedback:
I control this with more weapon properties and these are just duration and offset for the muzzle flash, specific to each weapon’s sprite.
Now onto some of that badly needed weapon kick feedback:
Oh yes! The actual implementation is a bit tricky here. I tried a few approaches, and it basically came down to some maths with parameters that look good. Again, my weapon properties define values for the kick, unique for each weapon:
The weapon keeps an internal force value. This force pushes or pulls the weapon away from its resting position. When the weapon fires, the force gets set to “kick strength” and pulls the weapon back (F1 in diagram). Then it attempts to return to its resting position with the “reset speed” (results in F2). This acts like a spring. The caveat is that this acts exactly like a spring and springs oscillate. So the “reset amplitude” is a multiplier that dampens the amount of “springiness” and makes the force weaker (A). Sort of like a spring trying to drag a weight with friction. In other words, it takes roughly the same time to reset, but it does so without oscillation.
I could have made this simpler, for example, with an animation curve. The “problem” is that weapons can fire faster that their kick duration. For example, a machine gun may never fully reset its kick until it stops firing. Or firing multiple rounds can amplify the kick beyond what a single round can kick. And this method handles these cases nicely.
All of this also applies to enemies, but they only aim (poorly) at the player when they see them:
I also added an effect entity that follows the same framework as everything else (props, mobs, etc.). It’s technically not necessarily an “effect” like a particle or something, but just a general temporary object in the scene that doesn’t otherwise interact with stuff. For now, I added an effect to projectile (definitions), so that they can spawn an effect when they hit something:
The effects run an internal timer and despawn at the end of it.
Speaking of hitting stuff, I need visual feedback when enemies (or player) get hit. I guess I could just flash the enemy white for a brief period. This is very old school, but it works fine, looks decent, and I don’t need to bother with proper animations for now. To do this, I needed a custom sprite shader that allows tinting the sprite, so I got one off the web. Anyway, it works fine:
I don’t know if this is what I’m actually going to go with. May be I will make it subtle when I implement real sprites.
I also added proper shotgun bullet spread so that the player doesn’t end up shooting all the pellets in the same direction but so they spread nicely:
Finally, I am also adding reload to weapons. I’m not actually adding finite ammo (yet, not sure what I will do). But here’s a machine gun running out of ammo in immediate magazine and reloading:
The actual output is in debug because I am not adding UI at this point, but I will have to show ammo on screen at some point. There also no visual feedback for reloading, so I will need something for that later. But I think I will do the more with this later.
Also, I made the camera follow the player smoothly to avoid jarring stops:
It’s a bit hard to see in a GIF of a small portion of the screen. But the player rectangle would be exactly in middle if the camera was not smoothing its path. The effect is subtle full-screen, but it just feels better.