MODULE: icicles, jars and other distorting glass objects

Started by Monsieur OUXX, Sun 03/08/2014 03:43:37

Previous topic - Next topic

Monsieur OUXX

This module was inspired by the AGS game "The Reaper" (credit goes to Grundislav and Ben304).

WHAT DOES IT DO
It's a special effect: when the player walks at some specific coordinates in the room, the module draws a copy of him (into an object of your choice), but the copy is distorted to look like it is seen through a cylindrical glass object.

THAT'S NOT CLEAR. CAN YOU SHOW ME?
Video : You can see the effect in action in any Let's Play video of "The Reaper", when the character walks behind the two glass jars in the foreground.
Demo game: dowload it below



HOW TO USE

WARNING: Absolute pre-requisite: You will see nothing if the character sprites don't have the same color depth as the object's sprite. For example, both need to be 16-bits, or both need to be 32-bits.

Note:the module assumes that your distorted character sprite will not be larger than 100x100px. If it's not the case, then change variables WIDTH and HEIGHT (capital letters) inside the script.

Note 2 :Not tested with scrolling rooms. If needed, then you should add the "Viewport.X" where relevant.

1) import the module into your AGS game
2.a) Create an object in your room where the distorted sprite will be drawn. Your object should have its own graphic (with actual pixels or fully transparent). The distorted sprite will be drawn on top of that sprite. I didn't test of the object has no graphic(sprite 0).
2.b) Create a region (e.g. Region 1) inside the room. When the player walks on it, the icicle computation will be turned on. When the player walks outside of it, the icicle computation will be turned off.
3) Keep in mind that the module uses the center of that object to calculate the player's position, relative to the icicle. For example, it uses the object's center to calculate when the player is "exactly behind" the object. That behaviour cannot be changed using the provided functions.
4) Call Icicle.NewIcicle(object, x_center, y_top, region);
   'object' is the object mentionned above
   'x_center' gives an horizontal offset (inside the object) to draw the distorted character (it doesn't have to be drawn in the middle of the object)
   'y_top' gives a vertical offset (inside the object)  to draw the distorted character (it doesn't have to be drawn in the middle of the object)
   'region' is the region on which the player should be walking for the distorted sprite to be rendered. (that allows you to disable the drawing and thus use less CPU)

5) (optional) Call Icicles.SetScale(ICICLE icicle,    float horiz,  float vertic)
    'icicle' is the ID of the icicle. It's the result of previous function 'NewIcicle'
    'horiz' and 'vertic' are the horizontal and vertical distortion ratio. You can stretch the distorted sprite horizontally and vertically to match the size of your actual icicle or jar or whatnot. For example horiz=2.0 means that the distorted sprite will be drawn at twice the width.

6) (optional) Call Icicles.SetProportions(ICICLE icicle,    int x3_width,  int x2_width,  int x1_width)
     The distorted sprite is typically rendered in 3 phases :
     - The central part is a vertical strip of the character sprite.
       It has a width equal to 'x3_width' and is stretched horizontal-
       -ly (200% -- twice the original width).
     - On each side of it, there is one vertical strip of width
       'x2_width', which just copies the original sprite without
       strecthing it.
     - On the far sides, there are 2 more vertical strips (of width
       'x1_width'). They are stretched horizontally at 50% (half the
       original width).

       |<-- x1_width (50%) --><-- x2_width (100%) --><----- x3_width (200%) -----><-- x2_width (100%) --><-- x1_width (50%)-->|

    By changing x1_width, x2_width and x3_width, you can change the proportions of which parts of the original sprite are strecthed 50%, 100% and 200%.

DOWNLOAD
>>> DEMO GAME 1.0 <<<


==============================


UPDATE: You know the way you always learn new things in AGS scripts?
Well, you'll notice that my module uses the following silly technique to get sprites Width and Height :
Code: ags

      //not the actual code in the module
      DynamicSprite* s sprite= DynamicSprite.CreateFromExistingSprite(something.Graphic);
      int width=s.Width;
      int height=s.Height;


Well, feel free to replace it with this, which will be much faster and memory-savy:
Code: ags

      width = Game.SpriteWidth[something.Graphic];
      height = Game.SpriteHeight[something.Graphic];

 

Mehrdad

Great. It's really useful .Thanks a lot for your works.
My official site: http://www.pershaland.com/

Ghost

At last! Nothing can stop my Frozen fanfiction game now! (laugh)

Seriously. This is awesome.

AnasAbdin

I haven't tested this one. Are the reflected sprites flipped as in reality?

ThreeOhFour

#4
Nice! I'm curious to see how you implemented this, it was an interesting thing to code when I did it for The Reaper and presented some strange challenges when I was trying to distort things (I had some weird issues when I moved the viewport, which is why in The Reaper it had a weird offset, if I remember right).

I haven't touched my own version of this code for a long time - I remember trying to take it further in complexity but having weird issues with color_transparent which prevented me from doing everything I wanted to with it. Cool to see someone else putting it into usable form!

Ghost

Quote from: AnasAbdin on Sun 03/08/2014 17:04:54
I haven't tested this one. Are the reflected sprites flipped as in reality?
Nope- not flipped, but the distortion effects are pretty good, so it's worth a shot, I'd say.

Monsieur OUXX

#6
Quote from: ThreeOhFour on Mon 04/08/2014 08:02:07
Nice! I'm curious to see how you implemented this

Poorly. I tried to keep it to the simplest because I had bad experiences before when I tried to do fancy things. Therefore, here, it's only done by copying the character sprite and duplicating a few vertical slices of it (by using "Crop"), then scaling them horizontally (by using the DrawImage standard parameters). But it does the trick, so I'm happy.

I didn't test it with scrolling backgrounds
, but even if I forgot some Viewport thingie somewhere, it would be easy to add into the script, because, as I said, the implementation is quite primitive and simple.

PS: for those who want to have the reflected sprites flipped as in reality, here is a tip : fiddle with variable relX (take its negative) -- it's the variable that gives the position of the character relative to the icicle. Then, go to the section of script that uses DynamicSprite.Flip() and add the relevant "if (something.Flipped)" where needed. It should take you 5 minutes.

 

SMF spam blocked by CleanTalk