How to make low hp screen pulsation in 2D game?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Sk1ppeR

Basically if any of you have played Battlefield 3 or any modern first person shooter, when you get low HP all you hear is your heartbeat (that’s easy) and then there’s a pulsating screen effect that’s a bit opaque but it has blood splatter and turns on a reddish filter.

In extension to this question I would like to know how to make screen space pixel shaders? I’ve been following a lot of guides about it, managed to make a fog but you know, the fog itself is a node that has a pixel shader and I have to move it around with code, it’s not like I can attach it to the camera, can I?

Where can I find some literature about screen space effects? I’ve been coding fog elements and attaching them with pivot points to the player character. That’s great when the camera follows the player around, but as soon as you change the camera to some level based camera and the screen space effect is janky. Depending on the position you might not get fog at all for instance.

I’m not looking for complete solutions, I’m not going to waste your time with that, but I would like to know where I can read something and learn. I have set a quite ambitious project to myself (well ambitious based on my current abilities) and I’d like to get it done and learn something in the process.

What I’ve tried so far is using the “WorldEnvironment” node but turning on things and changing settings has no effect in 2D games. Other things I’ve tried is, like I said, Position2D nodes attached to the player character and with children’s the size of camera’s viewport. This brought me plethora of headaches when I started resizing the game, but that’s a question for another thread.

Thank you in advance.

Have you tried adding a CanvasLayer and using the shader on that? A CanvasLayer is usually what’s drawn above everything else. So using the “pulsating” shader on that may work.

Ertain | 2021-04-04 19:41

:bust_in_silhouette: Reply From: Tato64

For a simple solution i would use a node like Sprite / TextureRect / CanvasLayer with an image of an overlay with blurry red borders and maybe some blood drops and whatnot, you can animate this with a shader but i’d advise on directly animating it graphically (maybe use a series of animations and then using a shader on the viewport rect itself) and using AnimatedSprites, after that lay all that on top of everything (You can easily do this setting the Z-index to a high number and disabling “Relative”)

Then in whichever script the player’s HP is, in _process or _physics_process i would change that node’s alpha (modulate.a = X) according to the player’s HP.

You will tweak and figure out how you want it, but lets say it would be: invisible at full HP, fully visible at lowest HP, then it would be something like this:

First we will use rule of proportion to “translate” our HP to numbers between 0-255 (The alpha channel mix-max):

var hp_translated = currentHP * 255 / maxHP

and then

$Bloodyoverlay.modulate.a = 255 - hp_translated

Lets say maxHP is 100 and we’re at full health:

100 * 255 / 100 is of course 255

255 - 255 is of course 0

Meaning the overlay would be invisible (Alpha channel = 0)

Now if we were at 0 HP, lets save the easy math: hp_translated would be 0 and 255 - 0 = 255 so the overlay would be fully visible.

You could also tweak the math to make it start becoming visible at <50 HP or things like that.

Hope this helps!

This is very helpful, yes. Thank you for taking the time.

Sk1ppeR | 2021-04-05 07:44