I keep talking about explosions, but I don’t have any. So that sounds like a good excuse to add a rocket launcher. First, I need the weapon item and projectile definitions:
And with some new sprites, that works
And I need a new reticle setup and sprite:
Now, this is obviously just the same what my other guns and projectiles are doing — totally not what you expect rockets to do:
Let’s start easy – rocket trail smoke by specifying how a projectile should emit an effect:
And this is sort of going in a decent direction:
An obvious missing feature is how effects (do not) dissipate. I can imagine various ways they can do this, but fading out sounds like reasonable logic, so I can encode that:
And this works nicely (hard to see in GIF well):
A little side-issue here: the effects get drawn above the projectile (even when it is flying up — because it gets spawned right on top of it):
I never want this when they are next to each other. In fact, this brings a whole another question of how things are layered. I am depth-sorting sprites based on their world Z (forward away from camera) position. I do want effects that are actually behind a projectile to be behind projectile, but not when they are right on it, even if the camera thinks they are. So like this (orange – enemy; black – projectile; gray – smoke):
The closer projectile is “above” the mob, while the further one is “below”. Smoke is still below projectile even when above the mob. So I am moving the effects slightly forward (so they are above mobs and such), and then moving projectiles even more forward (so they are above mobs and effects). To do this, I can add an offset to my prefab’s sorting:
And this works out nicely and “hides” the effect behind the projectile until it moves away enough:
There is another peculiar issue though. When the effects are very close to the frame rate I am testing with, visual artifacts happen. For slightly slower that framerate speeds, this means some of the effects are skipped:
For faster speeds, effects can’t catch up as more than one is needed per frame and the logic only spawns one (multiple would just overlap). So I cannot effectively increase effect count. Normally, the frames would be faster than events, so they would appear fine even if there were some marginal errors:
Basically, the timer that runs these “overflows” correctly between frames — it runs on exact period timing using the actual time between frames. The actual update only spawns the effect when the frame happens when it moves all the objects. This has the consequence that effects that happen close to or faster than the frame update period tend to become “too discrete”:
Now, this timing happens all the time everywhere in the code and this is fine for 95% of logic (not fine for movement and I discussed this previously for collisions). But here we have visuals that appear obviously wrong. I’ve never had to deal with this exact sort of thing before, so now I have to come up with an algorithm to properly space out the effects. In short, interpolate them.
The way I do this is to see how much the frame was late compared to how much time was remaining until the next effect. In other words, how much the effect overshot its release target. Then offset the effect back by that amount proportional to the movement the projectile traveled that frame. In other words, move the effect back “in time”. In short, offset = frame movement * late time / frame time . And this works out really nicely (I was afraid it would be more complicated):
So back to the actual effect stuff now. I need to add some random movement to the effect, otherwise it looks too static. It’s literally just a move in a randomly selected direction at a given speed:
And that works out great:
With this, I don’t think I even need to add random spacing to my projectile effect emit period, but I’ll still add it because it’s literally a single variable:
With random movement enabled, it’s super-subtle as I expected and barely noticeable even in a screenshot:
Now I have to do something about (the lack of) the explosions. But before I start adding more variables to the projectile, I want to consider how to actually approach defining effects for something like an explosion. I already assume I will need mote than one effect — fire, blast, smoke, whatever. And they will be timed differently — fire first, smoke later. If I were to “hard-code” this into projectile — well, that’s bad. Besides, the projectile “dies” when it hits something, so there’s no one to control the effect timing anyway. Which means I need a new type of virtual object to handle a bunch of effects, which I can encode in an asset:
I can use it for my smoke trail and it’s a good candidate for testing. So let’s convert that. All the values can go into the bundle:
And the projectile only need to reference this bundle:
So now I can move all the logic from projectile to the bundle. It will need to support multiple effects running in parallel, but it’s a matter of having multiple subclasses. The only caveat is the whole “where to spawn” the effect logic and the above time corrections. I need to pass the effect source’s new position to the bundle every frame from the projectile. And the projectile needs to explicitly tell the bundle to remove itself when the projectile dies.
And this works great. So let’s encode an explosion similarly. I’m not sure what exact logic it will have, but there’s definitely some differences, such as how it is spawned. I want several spread-out instant effects for the explosion, so I need to add those fields:
And the projectile now references the bundle instead of a single effect for its impacts:
And this spawns the effects as expected:
The bundle also has to get rid of itself once any of its entries is done (the effects remain, it’s just that the bundle is done with its work); here — right after it spawns the mini-explosion effect.
I can now add properties to my explosion effect similar to the smoke one:
And this works okayish:
One thing I don’t like is that the effects don’t move “with the blast”, that is, in the direction they were spawned. I can override the new effect’s random move direction for this. I also don’t like that the effect can get bunched up too much. I can another parameter for minimum random spawn distance:
And I also want the effects to grow and fade, which means adding another animation type.
And this already looks closer to what I want (minus horrible sprites):
One thing that I want is timing — “instant” explosion should still not be instant. So I want entry timing that staggers them, just very quickly and with a maximum number of effects per step:
And this makes it look much better (relatively speaking):
One problem is that periodic effects can still overlap, because I cannot space them out randomly. So I need to pre-calculate random angles for the entire effect bundle’s entry — so all explosions end up spacing out randomly. And I can add some smoke for fun:
So yeah, compared to nothing happening, this looks great. But I imagine I will need to get real assets and then tweak this a bunch. But I can reuse this whole system whenever I need effects. May be adding just one effect is now more cumbersome, but adding many is much easier.
I can also add screen shake to explosions:
Where each projectile can specify its own shake mulitplier:
I can also specify the overall distance to explosion where screen shake is actuated. The closer to it, the less the shake:
So how about that projectile path itself. Rockets don’t fly like bullets: they have acceleration, some wobbling, all that stuff. So I think I will add some of that and define on a per-projectile, keeping it fairly simple (no flight pattern asset for now):
I played around with the math a bit and ended up using three properties for this:
And this works out okay.
(I am looking at the GIF and I see no difference… well, low-frame GIF is a horrible format for this. But the effect is there and it’s noticeable.)
Anyway, may be wobble options will help with that:
And here’s a wobbly path:
(It’s so subtle again even when in the game I was afraid I’m exaggerating it too much… damn GIFs!)
Well, there we go. I was hoping to do multiple weapons and some explosion stuff. But this seemingly small feature sure had a lot of caveats to it. But hopefully I can now implement more guns, more effects, more projectiles, more everything! (later.)