And another suggestion topic: - Drawing Surface

Started by Dualnames, Sun 31/01/2010 18:50:45

Previous topic - Next topic

Dualnames

I'm wondering because it's been bugging me with the "Plugin Help" topic a lot. Is it really possible to have a drawing surface that will be drawn instead on the background as it is now, in front of everything (characters and objects)? Perhaps allowing to set its baseline, might even work better. I'm just asking, because I want to do something, but the only way I get the effect I want is via a Drawing Surface, otherwise there are serious drawbacks, and no way seems to be able to overcome the drawbacks of the engine.

Equally, if it's more easy to implement the ability to draw a transparent sprite on an overlay, it would really make my day.

I'm not demanding anything. I'm just asking with force.. :D
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)

Shane 'ProgZmax' Stevens

#1
This has been suggested before, by me and probably by others as well.  I believe CJ's usual response was along the lines of the engine needing more than a casual modification in order to alter the draw order so drawing surfaces can have 'dynamic' z-orders.  This is also the main reason why I haven't completed my rain module since I don't feel the overhead of creating a gui or objects or whatever is worth it when a z-order value would allow me to randomize whether the rain appeared before or behind objects and characters.

Pumaman

A drawing surface is just a way that the script can access the various bitmaps that already exist in AGS. So potentially some sort of Overlay.GetDrawingSurface would allow you to get a drawing surface that is drawn on top of other things, it's something I'll look at for a future version.

SSH

It would be great if Overlays, Guis, objects, backgrounds, etc all had fully customizable Z values. Backgrounds would default to -1, Objects from 0 to max-Y, Overlays 10000-ish, GUIs 20000. Then scripters could change them as they see fit.
12

Dualnames

Quote from: Pumaman on Wed 03/02/2010 23:58:04
A drawing surface is just a way that the script can access the various bitmaps that already exist in AGS. So potentially some sort of Overlay.GetDrawingSurface would allow you to get a drawing surface that is drawn on top of other things, it's something I'll look at for a future version.

If you can use Overaly to you know...eh idea? Can I use a GUI as the engine is now, and you know like do this:

function repeatedly_execute() {

gGui1.BackgroundGraphic=surface.Graphic;
}

Or some workaround with a GUI, because unless the function you're saying that might get added on future versions still has the same drawbacks of Overlays (meaning the whole transparency thingy), then it's still no-go for me.
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)

monkey0506

Dual based on your responses in the other thread what this is really about isn't being able to get a DrawingSurface and put the results on top of everything else, it's about the way that DrawingSurface transparency works. There are two current limitations in AGS that are preventing you from being able to accomplish the effect you want:

- If you draw a sprite partially transparent onto a transparent surface the sprite becomes flattened, resulting in a pink-tinted sprite.
- You cannot use a DrawingSurface to merge alpha channels. You can draw an alpha channeled image and it will work fine, but you cannot use the DrawingSurface functions to combine multiple alpha channeled sprites into a single image without destroying the alpha channels (at most keeping the alpha channel of one single sprite).

Beyond these limitations it is perfectly possible to use either an Overlay or a GUI with the DrawingSurface functions to place the contents of the DrawingSurface on top of everything. That is not the problem.

Calin Leafshade

you could possibly use various buttons on a gui or alot of objects to have multiple alpha blended sprites drawn to the screen.. but this isnt really practical beyond about 10 sprites

Dualnames

Quote from: Calin Leafshade on Thu 04/02/2010 18:24:11
you could possibly use various buttons on a gui or alot of objects to have multiple alpha blended sprites drawn to the screen.. but this isnt really practical beyond about 10 sprites

There's rally not a workaround over this. It has to be done a certain way. I've tried everything, but none results to victory without losses.
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)

Calin Leafshade


monkey0506

#9
I'm pretty sure he wants something close to this.

The drawbacks I've seen with that method are that I experienced between an 8-10 FPS drop and because I'm using a screenshot there's sometimes some residue (for a loop) when the player is moving. (Specifically it's using the portion of the screenshot from the last loop (no way to force-refresh the screen) that the drop will be at this loop to flatten the sprite. So if the player, the mouse, or something else was at where the drop will be at, but the item isn't there now then the drop will be drawn as if that item were still there. If the drop is partially transparent this could mean that it could become tinted by something that's not behind it (again, for one single loop).)

Making the drops appear less often would allow me to use fewer drops (currently using about 200 drops) to cover the whole screen which showed an increase in FPS.

Seems like a reasonable compromise to me though.

Dualnames

Is it really possible to show me the way you're doing this? Scripting. I want to use it on a 800x600 game. There's always the workaround of "drawing rain", but I'd love to have a way to adjust it. If only I could get the surface into a gui without losing anything it would be great and it would really work as I wanted it to. I'm thinking of like using a gui to draw 100 percent non-transparent rain and use drawing surface to do the background rain. Perhaps that's the most reasonable way so far.
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)

monkey0506

#11
Is it really possible for you to understand that there is such a thing as DynamicSprite.GetDrawingSurface, DynamicSprite.Graphic, and GUI.BackgroundGraphic? :=

Sure, I could show you how I'm doing it. It is really possible. Scripting. :-*

Get ready coz here it comes:

Code: ags
int Drop_ID = 0;
int Drop_Count = 200;
bool Drop_Used[];
int Drop_X[];
int Drop_Y[];
int Drop_Transparency[];
DynamicSprite *backgroundSprite;

function game_start() {
  Drop_Used = new bool[Drop_Count];
  Drop_X = new int[Drop_Count];
  Drop_Y = new int[Drop_Count];
  Drop_Transparency = new int[Drop_Count];
  Debug(4, 1);
}

function repeatedly_execute() {
  if (backgroundSprite != null) {
    gRain.BackgroundGraphic = 0;
    backgroundSprite.Delete();
  }
  backgroundSprite = DynamicSprite.Create(System.ViewportWidth, System.ViewportHeight, false);
  DynamicSprite *screenshot = DynamicSprite.CreateFromScreenShot();
  DrawingSurface *surface = backgroundSprite.GetDrawingSurface();
  if (!Drop_Used[Drop_ID]) { // create new drop
    Drop_X[Drop_ID] = Random(System.ViewportWidth);
    Drop_Y[Drop_ID] = 0;
    Drop_Transparency[Drop_ID] = Random(55) + 45; // minimum 45% transparency
    Drop_Used[Drop_ID] = true;
  }
  Drop_ID++;
  if (Drop_ID == Drop_Count) Drop_ID = 0;
  int i = 0;
  while (i < Drop_Count) {
    if (Drop_Used[i]) { // make drop fall
      Drop_Y[i] += 1;
      Drop_Used[i] = (Drop_Y[i] < System.ViewportHeight);
    }
    if (Drop_Used[i]) { // draw drop
      DynamicSprite *sprite = DynamicSprite.CreateFromExistingSprite(screenshot.Graphic, false);
      sprite.Crop(Drop_X[i], Drop_Y[i], Game.SpriteWidth[1], Game.SpriteHeight[1]);
      surface.DrawImage(Drop_X[i], Drop_Y[i], sprite.Graphic, 0);
      sprite.Delete();
      surface.DrawImage(Drop_X[i], Drop_Y[i], 1, Drop_Transparency[i]);
    }
    else { // reset variables
      Drop_X[i] = 0;
      Drop_Y[i] = 0;
      Drop_Transparency[i] = 0;
    }
    i++;
  }
  surface.Release();
  gRain.BackgroundGraphic = backgroundSprite.Graphic;
}


gRain is a 320x200 transparent GUI. You can change the resolution and GUI size and the code will still work the same way. It's not code I would generally release publicly as I'd usually clean it up a lot and make it look prettier. But you're a smart kid. :P

It would probably actually be better to allow the GUI to define the size of the area. And to be really cool you could probably even make it use GUIControls to define areas where the effect should be hidden, like under a porch at the bottom of the screen or something...

You could also even create depth by drawing onto the background at the same time...

...hmm...I'm just thinking of all sorts of ways to customize this and make it look better and better.

Shane 'ProgZmax' Stevens

I agree fully with SSH's suggestion to have in-game modifiable z-orders for everything for consistency and convenience.

fovmester

Pumaman:
QuoteA drawing surface is just a way that the script can access the various bitmaps that already exist in AGS. So potentially some sort of Overlay.GetDrawingSurface would allow you to get a drawing surface that is drawn on top of other things, it's something I'll look at for a future version.

I was just now working on a particle system module, when I realized that I would need some kind of Drawing Surface to draw the particles on. I could of course use 50+ objects in each room, but that will never happen.

An Overlay.GetDrawingSurface() would thus really be useful for this application. Please, if you could consider putting it into one of the next updates, I would jump high with joy!

monkey0506

I really don't see the need for an Overlay.GetDrawingSurface when we can do:

Code: ags
Overlay *overlay;
DynamicSprite *sprite;

// draw something on overlay
DrawingSurface *surface = sprite.GetDrawingSurface();
// draw some stuff
surface.Release();
if ((overlay != null) && (overlay.Valid)) overlay.Remove();
overlay = Overlay.CreateGraphical(x, y, sprite.Graphic, true);


Presumably there's a bit more overhead and/or memory consumption in having to store a DynamicSprite alongside the Overlay to be able to draw on top of the existing overlay contents, but it's not like it's impossible to accomplish. Nor is there any graphical difference between the two methods...

SMF spam blocked by CleanTalk