Need help with DynamicSprite / Overlay

Started by timid_dolphin, Mon 18/10/2021 22:50:18

Previous topic - Next topic

timid_dolphin

I've been working on a new rain module which will suit my aesthetic a bit better than some of the other ones out there.

After looking at a lot of pixel art, I find the most realistic ones don't animate the raindrops, but just randomly place them, but simulate refraction of the light and slightly desaturate and lighten from the background.

I think I'm on the right track, but there isn't a lot of detailed information about DynamicSprite and drawing surfaces (If I'm incorrect, please direct me to the relevant part of the tutorial!)

My code is posted below, I think that I need to create an overlay and draw a bunch of raindrops onto it, then reset it for the next rain. should be pretty lightweight if it works!

Thanks in advance to anybody who can help me with this!


Code: ags


function makeItRain(){
  
  //  set/reset overlay, using a sprite which is the same as the screensize, transparent colour
  //  overlay  = sprite 1234, etc...
  
  int howMuchRain = 10;             //to make 10 raindrops at a time 
  int rainDropLength = 20;          //each drop is 1 pixel wide, 20 pixels long
  
  for (int i = 0; i < howMuchRain; i++)
  {  
    int coordX = Random(359);
    int coordY = Random(170);       //find random places for the raindrops
    
  DynamicSprite* raindrop1 = DynamicSprite.CreateFromBackground(GetBackgroundFrame(), 
                                                                coordX, coordY, 1, rainDropLength);
                                                                //makes a raindrop from the background image
                                                                //would be better if it was from a screenshot,
                                                                //so includes objects, characters
  raindrop1.Tint(1, 1, 1, 20, 100); //slightly lighten and desaturate each drop

  DrawingSurface *surface = myOverlay;  //draw on the overlay
  
  surface.DrawImage(coordX, coordY-1, raindrop1.Graphic);       //place the raindrop 1 pixel higher than it's source
                                                                //creating a light refraction effect
  surface.Release();
  raindrop1.Delete();  
  }
}

[/code/

timid_dolphin

#1
Okay, after going through a lot of old forum posts and rereading the manual a thousand times, I think I'm starting to get my head around these things.

For now I'm testing this in a global late_repeatedly_execute_always()

It's beginning to look kind of ok. I really want the for loop to render x amount of raindrops, and it seems to only do one at a time each time this function is called.
But if I remove the for loop, the 'rain' stops when the player exits the first room.
Any ideas why it's behaving this way?

(DynamicSprite raindrop1 and Overlay surface are defined as in global variables.)

Code: ags

int howMuchRain = 10;             //to make 10 raindrops at a time 
int rainDropLength = 50;          //each drop is 1 pixel wide, 50 pixels long

function makeItRain()
{
  if(!IsGamePaused())
  {
    if(rainDrop1 != null)
    {
    //  rainSurface.Remove();
    }
 
     for (int i = 0; i < howMuchRain; i++)
    {  
      int coordX =  Game.Camera.X + 1 + Random(Game.Camera.Width - 2);
      int coordY =  Game.Camera.Y + 1 + Random(Game.Camera.Height - rainDropLength - 2);
      
      rainDrop1 = DynamicSprite.CreateFromBackground(GetBackgroundFrame(), coordX, coordY, 1, rainDropLength);
      rainDrop1.Tint(1, 1, 1, 30, 100); 
      rainSurface = Overlay.CreateGraphical(coordX - Game.Camera.X, coordY - 1 - Game.Camera.Y,  rainDrop1.Graphic, true);
      //raindrop1.Delete();
    }
  }
}


timid_dolphin

This feels weird replying to myself to help myself, perhaps reason to spend a little longer reading the manual before posting in this forum. I'll do it anyway, because this could be helpful to other beginners who want to get into the cool weird parts of the AGS engine!

so I create a DynamicSprite from a fully transparent screen sized sprite (slot 1234),

make a DrawingSurface from the DynamicSprite,

then the for-loop creates raindrops from the background image and draws them onto the DrawingSurface one pixel up from the source.

then I create a graphical Overlay from the background sprite which has been drawn on.

There's a timer there which slows them down a bit so they're not flickering every game loop but closer to a film frame rate.

It looks about as good as I would expect at this basic level. More could be done to make it more generalised and adaptable for different purposes.

It also needs another layer of 'splash' effects as rain drops hit the ground, which could be a variation on the same algorythm but with single pixels randomly appearing within a  few defined rectangles representing flat surfaces.

The effect could be more improved with customised animations of slower drips coming off the edges of surfaces etc.

I'm certain it will look cool when it's done!

Code: ags

//rainDrop1 and rainOverlay are defined as global variables

int howMuchRain = 10;             //to make 10 raindrops at a time 
int rainDropLength = 20;          //each drop is 1 pixel wide, 20 pixels long

DynamicSprite *rainBackground;
DrawingSurface *rainDrawingSurface;

function makeItRain()
{
  if(!IsGamePaused())
  {
    if(rainDrawingSurface != null)
    {
      rainDrawingSurface.Clear();
    } else {
      rainBackground = DynamicSprite.CreateFromExistingSprite(1234);
      rainDrawingSurface = rainBackground.GetDrawingSurface();
    }
      if(Game.DoOnceOnly("initRain")){
      SetTimerWithSeconds(13, 0.1);
    }
    if(IsTimerExpired(13))
    {
      for (int i = 0; i < howMuchRain; i++)
      {
        int coordX =  Game.Camera.X + 1 + Random(Game.Camera.Width - 2);
        int coordY =  Game.Camera.Y + 1 + Random(Game.Camera.Height - rainDropLength - 2);        
        rainDrop1 = DynamicSprite.CreateFromBackground(GetBackgroundFrame(), coordX, coordY, 1, rainDropLength);        
        rainDrop1.Tint(1, 1, 1, 30, 100);
        rainDrawingSurface.DrawImage(coordX, coordY-1, rainDrop1.Graphic);
      }
      rainOverlay = Overlay.CreateGraphical(0, 0, rainBackground.Graphic, true);
      
      SetTimerWithSeconds(13, 0.15);
    }   
  }
}

function late_repeatedly_execute_always()
{
  makeItRain();
}



Cassiebsg

Just wanted to say to keep posting.  (nod)
My experience with dynamic sprites is rather limited, so I can't help, but I always enjoy reading and learning. :)
There are those who believe that life here began out there...

timid_dolphin

Thanks!

I may not even use this as a rain machine, but it's been cool to learn about all this stuff, there's so much potential for other weird special effects, like you could use parts of this function to make the whole room drip with blood and melt away or something, or VHS glitch effects?

SMF spam blocked by CleanTalk