Can you store and/or recover a drawing made with DrawingSurface? [SOLVED]

Started by Héctor Bometón, Sun 26/07/2020 16:37:13

Previous topic - Next topic

Héctor Bometón

I managed to get the "freehand paint" (https://www.adventuregamestudio.co.uk/forums/index.php?topic=58278.0) working pretty well, as you can see in the following video. Now, the question is, can it be permanently visible or stored somewhere somehow? When I leave the room and come back, it's all gone.

I fear the answer is simpler than I think but I've been working so many hours... my brain just wont work properly...


Cassiebsg

Just don't delete the drawing surface?  ???

Draw it on an object, or permanently on the BG? All depends on exactly what you want to achieve. If it's suppose to be erasable, then adding it to the BG is a bad solution, but if you want whatever graffiti to stay there til the end of the game, then use the BG as canvas. 
Otherwise, save it in an object or don't delete the drawing the surface (I think that if you don't delete it, it'll stay there, AGS will though throw an error file complaining about not deleting it, which you might not want in the final release).
There are those who believe that life here began out there...

Crimson Wizard

Cassiebsg, you probably confuse "drawing surface" and "dynamic sprite".

DrawingSurface can be deleted (by calling Release) freely as it's merely an interface to access some object. When you release Drawing Surface, the object stays changed. In fact, Releasing a surface is a must because with Direct3D and OpenGL renderers it signals to update the video texture.

Drawing on room background does not stay and gets lost when you leave the room. This is probably made intentionally, to not increase size of saved games.

The solution is to create a global DynamicSprite, draw on that sprite instead, and either assign that sprite to the room object, or paint that sprite to room background whenever player enters the room.
In your case things are little more complicated as, it seems, you can draw anywhere, so object will be inconvenient. Perhaps do this:
* create a global DynamicSprite.
* when entering a room, if that sprite already exists, then paste it on room background.
* when drawing, draw both on that sprite AND room background. Dynamic sprite will work as a reserved image for restoring room background later.

javixblack

I can't help you with nothing, but tiene pinturria el jueguito, guachín

Héctor Bometón


Well, you can't draw "anywhere", only onto certain regions or hotspots, but I get it.

Never used Dynamic Sprites before, but I think I understood your explanation. I'll give it a try! Thank you very much!


Héctor Bometón

Quote from: Crimson Wizard on Sun 26/07/2020 21:41:08
Cassiebsg, you probably confuse "drawing surface" and "dynamic sprite".

DrawingSurface can be deleted (by calling Release) freely as it's merely an interface to access some object. When you release Drawing Surface, the object stays changed. In fact, Releasing a surface is a must because with Direct3D and OpenGL renderers it signals to update the video texture.

Drawing on room background does not stay and gets lost when you leave the room. This is probably made intentionally, to not increase size of saved games.

The solution is to create a global DynamicSprite, draw on that sprite instead, and either assign that sprite to the room object, or paint that sprite to room background whenever player enters the room.
In your case things are little more complicated as, it seems, you can draw anywhere, so object will be inconvenient. Perhaps do this:
* create a global DynamicSprite.
* when entering a room, if that sprite already exists, then paste it on room background.
* when drawing, draw both on that sprite AND room background. Dynamic sprite will work as a reserved image for restoring room background later.

So... It's been a while, but I still haven't managed to make it work. I'm struggling understanding how to store and load/paste the previously drawn surface onto the Room when I enter. I understand the solution, but I'm currently not able to code it propoerly. could anyone be so kind to help me out with this? Thanks!

Snarky

I'm going to assume that there is only one room in the game where you want to be able to graffiti. If there are multiple rooms, we might want to use a slightly different solution.

1. You need a persistent DynamicSprite (one that doesn't stop existing when you leave the room). You do this by declaring a DynamicSprite* variable in the global script. Then we need to export it to make it available to other scripts, and import it so it's actually accessible to them:

Code: ags
// GlobalScript.asc

// A sprite to store our graffiti painting
DynamicSprite* sprGraffiti;
export sprGraffiti;

Code: ags
// GlobalScript.ash
import DynamicSprite* sprGraffiti;


Note that this variable is declared but not assigned: it is null until we actually create a DynamicSprite.

2. Now in the room itself, you're either drawing directly on the room background, or on an object overlaid on the room. From the other thread you linked, it looks like you're drawing directly on the background. (There are pros and cons to this, but let's go with it for now.)

So when we enter the room (the room event "Player enters room (before fadein)"; make sure you properly link the function to this event), we need to make sure we update the background to include any graffiti already painted.

Code: ags
// Room script

function room_Load()
{
  if(sprGraffiti != null)
  {
    // There is a sprite, so let's draw it onto the background
    DrawingSurface* surf = Room.GetDrawingSurfaceForBackground();
    surf.DrawImage(0,0,sprGraffiti.Graphic);
    surf.Release();
  }  
}


3. Now we just need to make sure that we update the DynamicSprite whenever the player leaves the room. (An alternative is to update the DynamicSprite every time we paint onto the background, but this should be easier.) We do this using the room event "Player leaves room"â€"again making sure we link the event to the function:

Code: ags
// Room script

function room_Leave()
{
    sprGrafitti = DynamicSprite.CreateFromBackground();
}


As you see, this is where we actually create the DynamicSprite.

(For robustness, we should test that this event is triggered not just when the player leaves the room, but also if you change to a different player character in a different room, e.g. for a cutscene.)

Snarky

Oh, one more thing: I'm not sure that if you draw onto the background, save before leaving the room, and restore that save, the graffiti will have been stored. If not, we do need to update the DynamicSprite as soon as you draw onto the background.

Héctor Bometón

Quote from: Snarky on Sun 18/04/2021 08:56:23
Oh, one more thing: I'm not sure that if you draw onto the background, save before leaving the room, and restore that save, the graffiti will have been stored. If not, we do need to update the DynamicSprite as soon as you draw onto the background.

Wow... I'm really sorry I never answered. I  really thought I did...

Your solution worked perfectly, as usual. Thank you VERY MUCH!

SMF spam blocked by CleanTalk