Layering Sprites / Views on top of each other

Started by deadsuperhero, Sat 21/12/2019 19:24:12

Previous topic - Next topic

deadsuperhero

Hey all!

I'm getting back into AGS, after many years of being away. One thing I'm curious about: I'm exploring making a game with a ScuMM-style dialog system, and want the characters to make different expressions as various lines of dialogue comes up.

One way of doing this would be to draw different sprites for different views, and switch to those views when certain lines come up in a scene. However, creating entirely different sprite sets and views just to get an expression change in creates some extra work.

So, my question is, is there a known way within AGS to composite one view on top of another view? For example, maybe EGO is in a conversation, and suddenly another character says something that annoys him. Would I be able to composite an annoyed face on top of the character's existing sprite?
The fediverse needs great indie game developers! Find me there!

deadsuperhero

A secondary use-case I can think of would be a more RPG-centric route: let's say that I have a character that I'd like to equip a given piece of clothing or armor. Instead of redrawing the whole character into a different sprite set, is it possible to just render the outfit view on top of the character sprite?
The fediverse needs great indie game developers! Find me there!

morganw

You can create a dynamic sprite, get access to its drawing surface, and then draw other sprites on top of it.
Here is a quick example (not tested), assuming that sprite ID 1 is a picture of someone's head and sprite ID 2 is a hat.

Code: ags
// get a reference to a dynamic sprite that contains a copy of the head
// (true is a flag to preserve the alpha channel of the image)
DynamicSprite* sprite = DynamicSprite.CreateFromExistingSprite(1, true);

// get a reference to the drawing surface for this new sprite
DrawingSurface* surface = sprite.GetDrawingSurface();

// draw the hat on top of the head
// (the first two parameters are x and y position where we will draw, if the images are same size then use 0 and 0)
surface.DrawImage(0, 0, 2);

// release surface after drawing
surface.Release();

// use the new graphic on an object
// (.Graphic is just the ID number)
object[0].Graphic = sprite.Graphic;

// delete the sprite when you are done with it
// (if it is for long term use then you might need to make the dynamic sprite pointer a global variable)
sprite.Delete();


Probably the best thing to do is to have a look at these two manual pages, which will show the sort of things that you can achieve:

https://adventuregamestudio.github.io/ags-manual/DynamicSprite.html
https://adventuregamestudio.github.io/ags-manual/DrawingSurface.html

Khris

If you put just the head in the main view, you can also use something like this:
Code: ags
  // in game_start
  cBody.FollowCharacter(player, FOLLOW_EXACTLY, 1);  // 1 means draw the character behind the player


Now you can use  player.ChangeView(SOME_VIEW);  to switch heads / facial expressions.

I'm not 100% sure whether the following character also turns to face the same direction. If it doesn't, you can instead manually position the body character at the same location in repeatedly_execute_always:
Code: ags
  if (cBody.Room != player.Room) cBody.ChangeRoom(player.Room, player.x, player.y);
  else { cBody.x = player.x; cBody.y = player.y; }
  cBody.Loop = player.Loop;
  cBody.Frame = player.Frame;



The other route is the DynamicSprite route, like morganw suggested. This requires you to grab the ViewFrames of the character's main view and change their  .Graphic  to the one of your global DynamicSprite.

Cassiebsg

You can also create the sprites with just the changes that will be displayed in-front of your player character, assign it to a "dummy" character that is set to follow exactly and it's non solid. Make sure the baseline for this characters is 1 pixel in front of your characters, change the dummy empty sprite to the  sprite/view/loop that you want to display at the proper time. Return to empty sprite when you want to return the player character to normal view.

PS: (And Khris was ofcourse faster than me and with code.  (laugh) )
There are those who believe that life here began out there...

SMF spam blocked by CleanTalk