Drawing layers of tiles on surface

Started by Iolo, Tue 20/02/2018 02:50:27

Previous topic - Next topic

Iolo

Hello everyone, I'm quite new to AGS scripting and would like to get some insight on how to accomplish this.

The map's data and tileset are loaded in memory and I'd like to draw the map on a picture/surface before displaying it, this would allow me to scroll the scene.

My question is how can I achieve this? By drawing regions of a tileset Graphic on a DrawingSurface? All tiles have transparency and some of them have alpha. I guess i'm looking for a Blitting function that supports drawing to a picture, transprency and alpha, but AGS has its own set of rendering functions and I'm a little confused.

Any help is appreciated!


Snarky

#1
Quote from: Iolo on Tue 20/02/2018 02:50:27
how can I achieve this? By drawing regions of a tileset Graphic on a DrawingSurface?

Yes, for example. Another way would be to just load each tile into a separate Object.

QuoteAll tiles have transparency and some of them have alpha. I guess i'm looking for a Blitting function that supports drawing to a picture, transprency and alpha

DrawingSurface.DrawImage()
You will need to crop the tileset to just the tile you want to draw first, using DynamicSprite.CreateFromExistingSprite() and DynamicSprite.Crop(), or if you're drawing to separate Objects, you can load your tileset into the drawing surface and just do DynamicSprite.CreateFromDrawingSurface(tileSetSurface, tilex, tiley, wilewidth, tileheight) for each tile.

QuoteAGS has its own set of rendering functions and I'm a little confused.

In AGS, to show a graphic on screen you need to assign it to an instance of one of the built-in game types: Room background, Object, Character (i.e. animation frame), Overlay, GUI background, GUI Control, or Cursor (I think that's all of them). In most cases (except for Room background, which you can draw to directly), you do this by assigning a certain sprite as the object's graphic. If you need to manipulate the sprite first, you have to use a dynamic sprite, which can be created at runtime.

For room backgrounds and dynamic sprites, you can get a drawing surface, which gives you access to most of the AGS drawing functions. You get the drawing surface, draw on it, release it, and the room background/dynamic sprite is updated. (This update is destructive: if you need to revert back to the original background/sprite, e.g. to erase something you drew, you should keep a backup.)

Iolo

#2
Thank you Snarky, I went with the one sprite per tile approach and I have to say it works perfectly just like you said! I also understand what you meant by 'destructive update'. Once you Draw on the Background it stays forever that way, but I need to Clear it everytime I draw the map anyway so I won't have to restore the background image.

The second part of my test includes other elements like objects and they stack perfectly with transparency and alpha which is great!
Here is the code I'm using, it seems to work fine.

Code: ags

  DynamicSprite *MapViewport = DynamicSprite.Create(Num_Tiles_X * Tiles_Width, Num_Tiles_Y * Tiles_Height,  true);

  DrawingSurface *MapSurface = MapViewport.GetDrawingSurface();
  MapSurface.Clear(COLOR_TRANSPARENT);
  for(int i=0; i<Num_Tiles_Y; i++)
  {
    for(int j=0; j<Num_Tiles_X; j++)
    {
      MapSurface.DrawImage(j * Tiles_Width, i * Tiles_Height, Tiles_Slot + Tiles_Floor[(i * Num_Tiles_X) + j].Index, 0);
    }
  }
  MapSurface.Release();

  DrawingSurface *Background = Room.GetDrawingSurfaceForBackground();
  Background.Clear(COLOR_TRANSPARENT);   //GUIs cover the extra space outside viewport 
  Background.DrawImage(0, 0, MapViewport.Graphic);
  Background.Release();
  MapViewport.Delete();

*edit: I added the delete command for the dynamic sprite (the manual mentions it).

Very helpful and clear answer, thanks again!

Snarky


SMF spam blocked by CleanTalk