[SOLVED]Shadow effect not covering entire sprite

Started by Giacomo, Fri 02/08/2024 10:48:55

Previous topic - Next topic

Giacomo

Hello,
I'd like to ask a question about visual effects.

Imagine there is a object falling down from the sky.
On a certain moment the object lights up because it enter in a light ray action.
Then the object goes up and gets dark again.

Is it possible to create a shadow effect that covers the pixels within a sprite and on a certain range?
if I use region light then all the object changes tint and I'd like to give the shadow effect.

Eventually, I can do it manually on sprite editor, but I wonder if there is a faster way using
overlays or dynamic sprites.

Thank you.
https://ko-fi.com/giacomo97557 To support Falco's adventures

Crimson Wizard

#1
This may be done by having a darkness area painted on a object or overlay with black or dark grey color, and making such overlay translucent (using Transparency property), and placing it with higher baseline/zorder than the rest of things in the room.

Then anything passing under such overlay would get partially darkened.

Giacomo

#2
Thank you, Crimson. I indeed wanted to try with an overlay but I've never used it and I have to read well the manual to use it.

I'll give it a try, thank you!

Sorry Crimson, one more thing... I use objects as background, is it possible to affect just one object that is in front of these background objects and leave them unchanged?
https://ko-fi.com/giacomo97557 To support Falco's adventures

Khris

#3
A semi-transparent overlay will affect anything below it, whether it's an object or the room background.

Which means you basically need to paint a lighter version of the background so that darkening it via a shadow overlay will essentially darken it back to the lower lightness you want.

It's also possible to only darken the object but this requires using DynamicSprites and CopyTransparencyMask().
The idea is to create a dynamic sprite from the object sprite, draw the shadow on top using a Y offset based on the object's Y coordinate, then make the background transparent again by calling CopyTransparencyMask(OBJECT_SPRITE_SLOT).
Finally, you set the resulting DynamicSprite's .Graphic as the object's.
This has to be done inside repeatedly_execute, obviously, since the object is moving.

Code: ags
#define PIANO_SLOT 123

DynamicSprite* pianoSprite;

function room_Load() {
  pianoSprite = DynamicSprite.CreateFromExistingSprite(PIANO_SLOT);
  oPiano.Graphic = pianoSprite.Graphic;
}

function room_RepExec() {
  DrawingSurface* ds = pianoSprite.GetDrawingSurface();
  ds.Clear(COLOR_TRANSPARENT);
  ds.DrawImage(0, 0, PIANO_SLOT);
  bool mask_needed;
  if (oPiano.Y > 120 && oPiano < 170) {
    ds.DrawImage(0, 160 - oPiano.Y, SHADOW_SLOT);
    mask_needed = true;
  }
  ds.Release();
  if (mask_needed) oPiano.CopyTransparencyMask(PIANO_SLOT);
}

As the object moves down, the overlay is drawn further and further up, which causes it to remain static relative to the room.

Giacomo

Thank you, these info are very useful.
I'm still having a hard time with dynamic sprites, surfaces and overlays. I will test the script on a excercise project.


At the end I created the effect manually trough aseprite, because the animation script is full of lines and I can't handle it very well.
I will study more, to handle next complex animations better.

Cheers,
Giacomo
https://ko-fi.com/giacomo97557 To support Falco's adventures

SMF spam blocked by CleanTalk