Thanks!
You should look into procedural animations for things like hair. I use the points of a Line2D to imitate hair physics (I use a curve in the thickness of the line2D to have a hairlike style). In case you’re wondering about the droplet effect on the ground with the rain, that’s manual. I created an AnimatedSprite2D and randomize the start frame and the animation speed each time the node enters the screen. There were 107 droplets placed by hand, so it’s better to have a deactivation node when they’re off-screen, otherwise you can get lag spikes each time the level loads (the rain in the background it’s a cpu particles with a rectangle texture).
If you want squishy animations, I recommend playing with the sprite’s scale values. For a more natural effect, you can try cubic animation instead of continuous animation.
As for the sprite explosion of the pal bullets or the bosses, that’s a shader. Unfortunately, some shaders cause some lag spikes on web builds (I had no time to optimize it).
For other VFX, I use CPUParticles since they’re less expensive on web.
Additional note: You may know this but there are tweens in godot “create_tween()” they are good, the difference is while in animationplayer you need to put the start and the end, in tweens you only need to put the end value, so the animation go to that value, and that's with code, so you can make animation that interact differently depending the scene, like the grappling hook, I use a tween (it’s not good practice in this case) that move the player to the last position of the grappling hook pal with a tween, but I needed the time to be directly affected by the distance of the player to the grappling hook, so the duration of the animation is [“the distance between player and the grappling hook”/600] seconds.