Jibble

Author Topic: Can you store and/or recover a drawing made with DrawingSurface? [SOLVED]  (Read 814 times)

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...

« Last Edit: 25 Jul 2021, 10:53 by Héctor Bometón »

Cassiebsg

  • Cavefish
  • Fleeing the Cylon tyrrany...
    • Cassiebsg worked on one or more games that won an AGS Award!
    •  
    • Cassiebsg worked on one or more games that was nominated for an AGS Award!
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...

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.
« Last Edit: 26 Jul 2020, 22:19 by Crimson Wizard »

javixblack

  • don't go out!!!
I can't help you with nothing, but tiene pinturria el jueguito, guachí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!


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

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
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: Adventure Game Studio
  1. // GlobalScript.asc
  2.  
  3. // A sprite to store our graffiti painting
  4. DynamicSprite* sprGraffiti;
  5. export sprGraffiti;
Code: Adventure Game Studio
  1. // GlobalScript.ash
  2. 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: Adventure Game Studio
  1. // Room script
  2.  
  3. function room_Load()
  4. {
  5.   if(sprGraffiti != null)
  6.   {
  7.     // There is a sprite, so let's draw it onto the background
  8.     DrawingSurface* surf = Room.GetDrawingSurfaceForBackground();
  9.     surf.DrawImage(0,0,sprGraffiti.Graphic);
  10.     surf.Release();
  11.   }  
  12. }

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: Adventure Game Studio
  1. // Room script
  2.  
  3. function room_Leave()
  4. {
  5.     sprGrafitti = DynamicSprite.CreateFromBackground();
  6. }

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.)
« Last Edit: 18 Apr 2021, 08:59 by Snarky »

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
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.

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!