MODULE: Underwater v1.1

Started by Kweepa, Wed 19/08/2009 06:13:55

Previous topic - Next topic

Kweepa

Underwater module
v1.0 for AGS 2.72+

Distorts a background in a wibbly wavy way.
Hard to show a screenshot, but you can see it in action in this demo:
http://www.kweepa.com/step/ags/tech/UnderwaterDemo.zip
Get the module here:
http://www.kweepa.com/step/ags/tech/Underwater11.zip
Video on youtube:
http://www.youtube.com/watch?v=EP1iFfDPXvY

Version history:
1.1 Added characters and objects (depending on baseline)
1.0 Initial version

Steve
Still waiting for Purity of the Surf II

Dualnames

Are you married? Wow, subspark will love this!!! Thanks a lot stevey!!
Worked on Strangeland, Primordia, Hob's Barrow, The Cat Lady, Mage's Initiation, Until I Have You, Downfall, Hunie Pop, and every game in the Wadjet Eye Games catalogue (porting)

SSH

Is it possible to run this effect on only a small area?
12

Snake

Grim: "You're making me want to quit smoking... stop it!;)"
miguel: "I second Grim, stop this nonsense! I love my cigarettes!"

TerranRich

I wish people would post videos of their modules in action. :P

Thanks, Steve! This will be very useful to a lot of developers here :)
Status: Trying to come up with some ideas...

Kweepa

Quote from: TerranRich on Wed 19/08/2009 15:42:56
I wish people would post videos of their modules in action. :P
Be my guest! It would take me longer to record, convert, and upload the video than to write the module! :=

Quote from: SSH on Wed 19/08/2009 11:04:19
Is it possible to run this effect on only a small area?
Yes, that would be possible. Are you thinking about a window in an underwater base or something like that? I'll have a think about the best way to handle the edges.

Quote from: Dualnames on Wed 19/08/2009 08:16:10
Are you married? Wow, subspark will love this!!! Thanks a lot stevey!!
Sorry, yes I am!
I considered posting this in sparky's thread...
Still waiting for Purity of the Surf II

Joseph DiPerla

Wow. Nice job. Anyway you can get that to work along with the character? It just doesn't seem right that the character doesn't have the same effect happen to him.
Joseph DiPerla--- http://www.adventurestockpile.com
Play my Star Wars MMORPG: http://sw-bfs.com
See my Fiverr page for translation and other services: https://www.fiverr.com/josephdiperla
Google Plus Adventure Community: https://plus.google.com/communities/116504865864458899575

Kweepa

Quote from: Joseph DiPerla on Wed 19/08/2009 17:16:54
Anyway you can get that to work along with the character?
I'd have to have a third buffer, render the bg, characters and objects to that, then do the underwater effect on top (and hide the visible objects). I think it's easy enough to get the current frame for characters...
Still waiting for Purity of the Surf II

monkey0506

Quote from: SteveMcCrea on Wed 19/08/2009 17:50:42I think it's easy enough to get the current frame for characters...

Sure, that's easy enough:

Code: ags
ViewFrame *frame = Game.GetViewFrame(player.View, player.Loop, player.Frame);
DynamicSprite *sprite = DynamicSprite.CreateFromExisitingSprite(frame.Graphic);
if (frame.Flipped) sprite.Flip(eFlipLeftToRight);


Though you do have to use a DynamicSprite if the frame is flipped (otherwise you can just use the raw sprite number). You could avoid creating the sprite unnecessarily by doing something like:

Code: ags
ViewFrame *frame = Game.GetViewFrame(player.View, player.Loop, player.Frame);
DynamicSprite *sprite;
int graphic = frame.Graphic;
if (frame.Flipped) {
  sprite = DynamicSprite.CreateFromExistingSprite(graphic);
  sprite.Flip(eFlipLeftToRight);
  graphic = sprite.Graphic;
}


I am assuming that you're using a DrawingSurface at some point which the character sprites would be drawn onto? Because at that point it's safe to delete the DynamicSprite (if any) of course.

GarageGothic

Cool module. The functionality is very similar to the refraction part of my EffectObjects module, though that works on objects (as you can tell from the name) rather than backgrounds. Basically it turns any object into a lens which can scale/distort background, objects and characters behind it. I'm using 3.1.2, so DrawingSurface functions and CopyTransparencyMask are a great help. But I'm sure something similar could be done in 2.72.

The thing you have to remember if you want to RawDraw characters/objects onto the background before distorting it is to sort them by baseline first. Since characters and objects can move around and new characters can enter the room this has to be done every game loop, which is a bit of a pain but doesn't cause too much slowdown. Also, any walkbehinds within the distorted area would have to be faked by using objects.

Snake

Wow, if you can get this to work with the characters and objects too, that would be even better. I was actually going to ask about that in my first post but I had lost track of time and had to leave.
Grim: "You're making me want to quit smoking... stop it!;)"
miguel: "I second Grim, stop this nonsense! I love my cigarettes!"

Kweepa

Thanks monkey & GG for the pointers.
New version uploaded with a new helper module FakeScreen that composites objects and characters (sorted, scaled and transparent) onto a background frame before the Underwater module does its work. A walkbehind hides the actual objects and characters.

The demo has also been updated to reflect the changes.

Steve
Still waiting for Purity of the Surf II

monkey0506

Quote from: SteveMcCrea on Thu 20/08/2009 06:05:17A walkbehind hides the actual objects and characters.

So you have to cover the entire room in a walkbehind area, or does the module apply the effect to said area?

And you're welcome...looked over your code. Snazzy stuff you've got going on in there. :D

Kweepa

Quote from: monkey_05_06 on Thu 20/08/2009 06:16:51
Quote from: SteveMcCrea on Thu 20/08/2009 06:05:17A walkbehind hides the actual objects and characters.
So you have to cover the entire room in a walkbehind area...?
Yup! This is the easiest way to keep all the properties of the objects and characters intact. If you want to draw a window or porthole in front, you just set the walkbehind baseline above the window baseline. Then you can have a character walk in front of the window or swim behind it.
Still waiting for Purity of the Surf II

Kweepa

Still waiting for Purity of the Surf II

SSH

Hmm, what I actually really wanted was a reflective, wobbly surface of the water but only taking up a small part of the screen (e..g. in a fountain thats part of the background)
12

Kweepa

Then you want the Lake module!
http://www.adventuregamestudio.co.uk/yabb/index.php?topic=27356.0
You'd need to cover up a bit of it with an object.
Still waiting for Purity of the Surf II

subspark

Good work Steve! I knew someone would tackle my idea. Although I'm sure it was hardly a tackle.

Many cheers,
Sparky.

Ali

#18
The demo looks great, I could watch it for ten minutes...

However I ran into problems using it in an 800x600 32bit game. It came out like this:


(The background was a pencil line drawing from uncle-mum's Stediddy game)

Before I added a full screen walkbehind the pink colour was constant and behind the characters. Now it flashes on and off - at about the default rate for background animation now that I think about it. I tried downgrading to 16 setting which had no effect and I lowered the game resolution but the magenta colour remained.


EDIT: Ignore all this, Steve. It looks like AGS corrupted the bitmap somehow when I exported it. Opening the file in MSPaint and saving it again made the magenta go away. Nothing to do with your module. Keep up the good work!

GarageGothic

Quote from: Ali on Sat 22/08/2009 18:38:45Now it flashes on and off - at about the default rate for background animation now that I think about it.

Have you tried calling SetBackgroundFrame(0) in the player_enters_room event (unless the module already does this)?

Kweepa

Quote from: GarageGothic on Sat 22/08/2009 18:46:52
Have you tried calling SetBackgroundFrame(0) in the player_enters_room event (unless the module already does this)?

It does. :=
See the repeatedly_execute function below:
Code: ags

// Underwater module script

__Underwater Underwater;
export Underwater;

bool gEnabled = false;

float tt = 0.0;
float t = 0.0;

float a[5], b[5], c[5];

function __Underwater::Enable()
{
  float scalar = 2000.0;
  int i = 0;
  while (i < 5)
  {
    a[i] = IntToFloat(Random(2000)*(2*Random(1)-1))/scalar;
    b[i] = IntToFloat(Random(2000)*(2*Random(1)-1))/scalar;
    c[i] = IntToFloat(Random(2000)*(2*Random(1)-1))/2000.0;
    i++;
  }
  gEnabled = true;
}

function __Underwater::Disable()
{
  gEnabled = false;
}

float get_gradient_x(int xi, int yi)
{
  float x = IntToFloat(xi)/160.0 - 1.0;
  float y = IntToFloat(yi)/160.0 - 1.0;
  
  float dx = 0.0;
  int i = 0;
  while (i < 5)
  {
    dx += a[i]*t*Maths.Cos(a[i]*t*x + b[i]*t*y + c[i]);
    i++;
  }

  return dx;
}

float get_gradient_y(int xi, int yi)
{
  float x = IntToFloat(xi)/160.0 - 1.0;
  float y = IntToFloat(yi)/160.0 - 1.0;
  
  float dy = 0.0;
  int i = 0;
  while (i < 5)
  {
    dy += b[i]*t*Maths.Cos(a[i]*t*x + b[i]*t*y + c[i]);
    i++;
  }

  return dy;
}

function offset_a_block(DrawingSurface *surf, int x, int y, int w)
{
  int xoff = FloatToInt(1.0*get_gradient_x(x + w/2, y + w/2));
  int yoff = FloatToInt(1.0*get_gradient_y(x + w/2, y + w/2));
  DynamicSprite *ds = DynamicSprite.CreateFromBackground(1, x, y, w, w);
  #ifver 3.00
  surf.DrawImage(x - xoff, y - xoff, ds.Graphic);
  #endif
  #ifnver 3.00
  RawDrawImage(x - xoff, y - yoff, ds.Graphic);
  #endif
}

function repeatedly_execute()
{
  if (gEnabled)
  {
    tt = tt + 0.01;
    t = 2.0*Maths.Pi*Maths.Sin(tt);

    SetBackgroundFrame(0);
    // repeatedly grab a random chunk from bg 1 and paste it to bg 0, slightly offset
    #ifver 3.00
    DrawingSurface *surf = Room.GetDrawingSurfaceForBackground(0);
    #endif
    int i = 0;
    while (i < 128)
    {
      i++;
      int w = Room.Width/32;
      int x = Random(Room.Width - 1 - w);
      int y = Random(Room.Height - 1 - w);

      offset_a_block(surf, x, y, w);
    }

    // draw some more around the player
    ViewFrame *frame = Game.GetViewFrame(player.View, player.Loop, player.Frame);
    int graphic = frame.Graphic;
    int height = FloatToInt(IntToFloat(Game.SpriteHeight[graphic]*player.Scaling)/100.0);
    int width  = FloatToInt(IntToFloat( Game.SpriteWidth[graphic]*player.Scaling)/100.0);
    int left = player.x - width/2;
    int top = player.y - height - player.z;

    i = 0;
    while (i < 32)
    {
      i++;
      int w = Room.Width/64;
      int x = left - w/2 + Random(width - 1);
      int y = top - w/2 + Random(height - 1);
      if (x < 0) x = 0;
      else if (x >= Room.Width - w) x = Room.Width - 1 - w;
      if (y < 0) y = 0;
      else if (y >= Room.Height - w) y = Room.Height - 1 - w;
      
      offset_a_block(surf, x, y, w);
    }
    #ifver 3.00
    surf.Release();
    #endif
  }
}
Still waiting for Purity of the Surf II

TerranRich

My God, Steve, you have a ton of modules, all of them very useful and amazingly well-done! I gotta see which ones I can use. ;D
Status: Trying to come up with some ideas...

Kweepa

I've got a way to go to catch up with SSH or monkey_05_06!
Still waiting for Purity of the Surf II

monkey0506

To be fair though Steve your modules tend to be way cooler than mine. Most of mine are based on other people's scripts (like AGSMuse and QueuedSpeech) or a generic concept that's not really that difficult (like GUIAnimation for example where I just change the GUI.BackgroundGraphic property).

Yours implement 3D effects and things which I frankly don't understand what's happening at all! ::)

Igor Hardy

#24
For some reason everything stops moving during cutscenes. Any ideas?

EDIT: AH! I added "always" to "repeatedly_execute" and it did the trick.

Kweepa

Ah yes, that'll do it.
It's probably worth putting out a new version with that change.
Still waiting for Purity of the Surf II

abstauber

Wow, this is really a great module. Is there by any chance a source of all those algorithms, you're using?

Kweepa

The source code is right up there ^^^. :=
The "magic" is in get_gradient_x/y, which just sum up some sine waves with different magnitude and phase, and are used to offset a block of pixels.
I don't have a specific reference. I just pulled the approach out of my arse. However, a quick web search for "2d fractal noise sum of sine waves" turned up this which seems similar:
http://developer.download.nvidia.com/SDK/9.5/Samples/samples.html#glsl_vertex_water
Still waiting for Purity of the Surf II

abstauber

Hehe... that makes the module even more impressive :D

I once had a book about megademo-coding for Turbo Pascal, but unfortunately I've lost it :(
It was full of algorithms and 3d gimmicks... *sigh*

PuNKKoMmANDO77

thank Steve , this module is simply amazing

Kweepa

Quote from: PuNKKoMmANDO77 on Thu 10/12/2009 11:35:57
thank Steve , this module is simply amazing

Glad you like it.
Let me know if you need any help integrating it into a game (that goes for everyone!). And also let me know if you release a game using it...
Still waiting for Purity of the Surf II

Lufia

Hi. I want to implement something like that in a completely different game engine and I thought this module could help me out. ... But I've trouble understanding how it works. ^^'

Starting here :
Code: ags
a[i] = IntToFloat(Random(2000)*(2*Random(1)-1))/scalar;

Get a random number between 0 and 2000, multiply by... either 0 or 1 ? then divide by 2000. I think I'm reading something wrong.

Then in get_gradient
Code: ags
float x = IntToFloat(xi)/160.0 - 1.0;

What's that 160 doing here ? Why -1 ?
I'll just trust you on the way to calculate dx and dy.

offset_a_block
Code: ags
int xoff = FloatToInt(1.0*get_gradient_x(x + w/2, y + w/2));

We're using the center of the chunk of background to displace as the argument for get_gradient, right ?

repeatedly_execute
Are you displacing 128 random chunks of background ?
I understand that first loop (I think), the rest of the function lost me.

I hope I'm not too annoying. >.>

Kweepa

Quote from: Lufia on Tue 26/01/2010 15:30:04
Code: ags
a[i] = IntToFloat(Random(2000)*(2*Random(1)-1))/scalar;

Get a random number between 0 and 2000, multiply by... either 0 or 1 ? then divide by 2000. I think I'm reading something wrong.
Yup; multiply by either -1 or 1; yup.
It's just a random float between -1 and 1. More complicated than it needs to be, sorry!

Quote
Code: ags
float x = IntToFloat(xi)/160.0 - 1.0;

What's that 160 doing here ? Why -1 ?
The 160 is the screen width divided by two. The -1 then makes x between -1 and 1.

Quote
Code: ags
int xoff = FloatToInt(1.0*get_gradient_x(x + w/2, y + w/2));

We're using the center of the chunk of background to displace as the argument for get_gradient, right ?
Yup, that's right.

Quote
repeatedly_execute
Are you displacing 128 random chunks of background ?
I understand that first loop (I think), the rest of the function lost me.
Yes, that's right.
The rest of the function displaces some more blocks near the player.

Good luck!
Still waiting for Purity of the Surf II

ZapZap

 First of all, I suck at scripting when it gets the tiniest bit complicated. So I was trying to use your module for a game (MAGS Underwater) and when using the fakescreen I don't really understand what are the parameters I need to put... one int for objects another one for characters and the baseline? I don't really get it (the numbers I 'intuitively' try result in error)
"Loose ends have a way of strangling you"

eri0o

Hey, does someone has a backup of this code somewhere? I am really interested in the code :). Also the FakeScreen module, I couldn't find it's topic. :~(

arj0n


eri0o

Thanks arj0n ! Just downloaded both modules! :]

m0ds

thanks arjon + eri0o! i was also going to ask for underwater a couple days ago :)

Danvzare

I never knew I needed this module until now. :shocked:

Mehrdad

#39

Maybe I'm wrong to use this module. But I get an error in AGS 3.4.1. I only add underwater.Enabled(); in one of my rooms. Is it enough or I need other codes too?

Edit: Problem solved. I forgot duplicate frame. It works perfectly on 3.4.1 too.
My official site: http://www.pershaland.com/

The creature

Does anyone still have this module still? The link appears to be dead and it would be really handy for something I've been working on :(

Privateer Puddin'


The creature

I know this is an old module and probably not supported now but I have an issue. I'm using the Draw Behind so the it also puts the water effect on characters and objects. But having done that, I've found you can no longer click on items and objects (obviously).

Is there a way to set mouse clicks to pass through/ignore a walkbhind layer? I'm not sure there is but I thought I'd fire out the question.

Kweepa

I don't think you can do that easily.
I think the best option would be to modify the script to make FakeScreen write to a DynamicSprite and have the Underwater module modify that sprite and stick it on a non-clickable full screen GUI.
Still waiting for Purity of the Surf II

eri0o

You can also draw on a graphic overlay

bx83

#45
I'm using a game with 1366x768 (widescreen) backgrounds, and it's 32it colour.
When I use this module, the player and other on-screen objects show no change, and the background begins to sway wildly getting more and more distorted.
What am I doing wrong?

SOLVED: I was using the wrong resolution. Mine are 1366 wide, so lines 34/35/50/51 in module are all using 683.0 (half of 1366), not 160.0 (half of 320, the very small size).

eg:
Underwater.asc:

Code: ags
float get_gradient_y(int xi, int yi)
{
  float x = IntToFloat(xi)/683.0 - 1.0;
  float y = IntToFloat(yi)/683.0 - 1.0;
  
  float dy = 0.0;
  int i = 0;
  while (i < 5)
  {
    dy += b[i]*t*Maths.Cos(a[i]*t*x + b[i]*t*y + c[i]);
    i++;
  }

  return dy;
}

bx83

It's me again.
I'm using AGS 3.5.0.31 (p9)
Have Underwater working; Fakescreen not working.
I have an animated object which will not distort as the background is doing with Underwater.
No matter the combinations of src/dest backgrounds, or my baseline (=0 seems to work best), it will won't work - object remains undistorted.
I have background 0 (main), background 1 (copy of bg0, working space), and a spare bakcground 2 (used for something else, plain white image on it).
I also have a walkbehind on background 0, if this is significant.
Also: Underwater is above Fakscreen in the script list (though I doubt this matters).

Can anyone help? What am I doing wrong with Fakescreen that I'm not with Underwater?

The creature

#47
I would have loved to use this module in my game as it's mostly set under water, From my tests with it it looked great...but as you have described, I ran into the same issues that the module doesn't support. There were a few ideas on how to fix this but they were beyond my coding abilities at the moment.

But if this gets resolved I'll be all over this module. I certainly keep an eye on this thread in the case that someone tweaks the module code to work with interactive/animated room objects.

Monsieur OUXX

eErio what are you waiting for? Use your coding magic to rewrite this module from the ground up in AGS 3.5  ;)
 

eri0o

I don't remember if I did it or not, can you try the version here: https://ericoporto.github.io/agsModuleList/ ?

Rik_Vargard

Wow this is so impressive!!  8-0

glurex

Is there a way to activate the effect only in one specific moment (cut scene) and then disable it?

SMF spam blocked by CleanTalk