LoadSaveSlotScreenshot and DynamicSprite.CreateFromSaveGame

Started by ZakMcKracken, Fri 15/07/2005 23:56:07

Previous topic - Next topic

ZakMcKracken

Hello,

I'm creating a new Save/Load GUI with screenshots.
Since I haven't created one before, I looked for a good tutorial, and found this one:
http://www.twin-design.com/agsezine/9/tutorial.cfm
(this is Scripting Tutorial By Andrew McCormack)

It says the tutorial will present how to make a load/save game dialog that uses the new "save games with screenshots" feature of AGS v2.6 onward.

Well... I'm using AGS 2.7, I did the tutorial step-by-step, but when I save the game, the compiler stops with message "undefined symbol LoadSaveSlotScreenshot'":
Code: ags

function sgs_getslots()
{
int i=1;
while(i<=6) 
	{
	if (GetSaveSlotDescription(i, sgs_struct[i].t)) 
		{
		sgs_struct[i].spr=LoadSaveSlotScreenshot(i, SGS_WIDTH, SGS_HEIGHT);
		} 
	else
		{
		StrCopy(sgs_struct[i].t, "");
		sgs_struct[i].spr=SGS_EMPTY_SPRITE;
		}
	SetLabelText(SAVELOAD, 6+i, sgs_struct[i].t); 
	SetLabelColor(SAVELOAD, 6+i, SGS_LABEL_COLOUR); 
	SetButtonPic(SAVELOAD, i, 1, sgs_struct[i].spr);
	i=i+1;
	}
Wait(1); 
SaveGameSlot(100, "temp"); 
sgs_struct[0].spr=LoadSaveSlotScreenshot(100, SGS_WIDTH, SGS_HEIGHT); 
DeleteSaveSlot(100); 
}


Well, the help file says that LoadSaveSlotScreenshot is obsolete, and suggests to use DynamicSprite.CreateFromSaveGame

I tried, but with no success. I changed the int to DynamicSprite*, but it doesn't compile.

Can someone clarify the concepts?
I think the tutorial is very very good, maybe it could be more useful fix the tutorial to make it compatible with AGS 2.7

Thank you.

monkey0506

Change the lines that read:

Code: ags
sgs_struct[#].spr=LoadSaveSlotScreenshot(#, SGS_WIDTH, SGS_HEIGHT);


To:

Code: ags
DynamicSprite* spr = DynamicSprite.CreateFromSaveGame(#, SGS_WIDTH, SGS_HEIGHT);
sgs_struct[#].spr = spr.ID;


Leave sgs_struct[ # ].spr defined as an int.  And be sure to replace # with the appropriate numbers and not just copy and paste o_0.

Edit:  Apparently a '[' followed by a '#' and a ']' creates the bullet sprite
  • .  I didn't know that...

    Edit:  Allong with forcing the bulleted text to the next line.

ZakMcKracken

Hello monkey,

thank you for your support.
Unfortunately, the compiler says "ID is not a member of spr". I tryed to write it in lowercase, too.

Anyway, I attempted a workaround.
I loaded AGS 2.62 in a separate directory, and created the Save/Load GUI according to the tutorial.
Everything works fine  :=
So, I saved everything, then I loaded AGS 2.7, and loaded my game with the new GUI.

The room conversion has been applied, as usual, and when I look into the Global Script to see if something has changed, I surprisingly notice that everything was untouched!  :o
There are "LoadSaveSlotScreenshot" function calls, and... they works! The compiler compiles the game, and when I test it, it works. The screenshots appear.

I can't figure out why, yesterday, the compiler told me "undefined symbol LoadSaveSlotScreenshot'"...

Well, to be honest, there is a little thing that doesn't work: the very first time I save a game, it crashes indicating that I attempted to delete a sprite that was not allocated.
But the game saves correctly in its slot.
Then, every time I run the game, and save, everything is right.

Maybe it could be useful to change all obsolete functions into the new logic; if I succeed in, I'll post the changes.

Regards

Pumaman

2.7 can be backwards compatible with 2.62 and support all the old-style commands, if "Enforce object-based scripting" is not checked in the General Settings tab.

By default in a new game backwards compatibility is disabled, but if you upgrade a game from 2.62 it is enabled. You can toggle the checkbox to change it yourself.

ZakMcKracken

Hello Pumaman,

you are right, mistery solved. It was the "Enforce object-based scripting" option!

Thank you.

monkey0506

But it gets confusing using both... Sorry I didn't look up the right property name.  I just assumed it would be ID for some reason...  The proper name would be spr.Graphic...but I guess you're just going to use the old-style code amongst new-style...

ZakMcKracken

Hello Monkey,

no, no, I am trying to translate into the new object-oriented style. So, every clue is welcome  :)

I use the old style just to better understand the concepts and logic, but my final goal is to make a game enterely object-based.

Regards

monkey0506

Okay, then you may want to use the code I posted, and just change "ID" to "Graphic".  In case you didn't already figure it out.  Sorry that I just made up the property name.  I was kind of tired and a lot of the new object types have ID properties (Hotspot, Object, Character, etc.).  I should have paid better attention when I was looking up the proper parameter list.

~Cheers

ZakMcKracken

Hello everybody,

Now I have understand, but there is just one more thing that puzzles me.

In AGS 2.62, the following lines...
Code: ags

SaveGameSlot(100, "temp"); // Save current game in temp slot
sgs_struct[0].spr=LoadSaveSlotScreenshot(100, SGS_WIDTH, SGS_HEIGHT); // load up screenshot
DeleteSaveSlot(100); // Delete temporary slot

...work fine: in sgs_struct[0].spr there is a value.
In fact, the subsequent instruction:
Code: ags

SetButtonPic(SAVELOAD, button, 1, sgs_struct[0].spr); // change selected button to have current game screenshot

works fine as well: in my button, I see the picture.

Same code, compiled with AGS 2.7: when I click on the button, it shows me anything, and the game crashes. It seems it can't load the sprite from the temporary saved game slot.
The option "Save screenshot in save game" is checked.

Well, I changed the above lines as follow:
Code: ags

SaveGameSlot(100, "temp"); // Save current game in temp slot
DynamicSprite* spr = DynamicSprite.CreateFromSaveGame(100, SGS_WIDTH, SGS_HEIGHT);
sgs_struct[0].spr=spr.Graphic;
spr.Delete();
DeleteSaveSlot(100); // Delete temporary slot

...and when the code is executed in the game, it crashes with the error: "null pointer referenced", and the line number indicates the assignment: "sgs_struct[0].spr=spr.Graphic;".

I checked again the option "Save screenshot in save game"... and it's turned on.

I could suppose there is a bug in SaveGameSlot function, but I don't think so: if I run the game with the original lines of code (that is using LoadSaveSlotScreenshot), the game crashes the first time I try to save, but if I run the game again, and try to save, I see a picture in a slot. So, I assume that a sprite as been saved with the slot.

I don't know... it seems like the slot 100 is unpleasant to AGS :-)
Can someone try to see if SaveGameSlot(100, "temp") saves the screenshot correctly?

Thank you

Gilbert

I think that's because you deleted the sprite from memory:
spr.Delete();

sgs_struct[0].spr originally points to a sprite number (i suppose) which no longer exists after the deletion of spr.

ZakMcKracken

Hello,

wow, Gilbot, what a speedy!! :D  I just came in to add further information to my case.

When I compile the original code with AGS 2.7, the game crashes when attempting to execute the following line:
Code: ags

if (sgs_struct[i].spr != SGS_EMPTY_SPRITE) DeleteSprite(sgs_struct[i].spr); //SGS_EMPTY_SPRITE is defined as 139, which is a sprite in the library with a picture saying "Empty slot"

with the message "Attempted to free a static sprite that was not loaded by the script".
Same code, in AGS 2.62, works fine.



In conclusion, the differences betweeen 2.62 and 2.7 (executing the same code):

Code: ags

SaveGameSlot(100, "temp"); // Save current game in temp slot
sgs_struct[0].spr=LoadSaveSlotScreenshot(100, SGS_WIDTH, SGS_HEIGHT); // load up screenshot
DeleteSaveSlot(100); // Delete temporary slot
...
SetButtonPic(SAVELOAD, button, 1, sgs_struct[0].spr); // change selected button to have current game screenshot
...
int i=0;
while(i<=6) 
  {
  if (sgs_struct[i].spr != SGS_EMPTY_SPRITE) DeleteSprite(sgs_struct[i].spr);
  i=i+1;
  }


...with AGS 2.62 everything is allright:
  • Loads a sprite number into sgs_struct[0].spr
  • Sets the image when I first click on the button
  • Deletes the sprite from sgs_struct[0].spr

    ...with AGS 2.7 something is wrong:
  • sgs_struct[0].spr is 0
  • There is no image in the button
  • When attempting to delete sgs_struct[0].spr (which value is 0), it crashes with the error "Attempted to free a static sprite that was not loaded by the script".

    Hope this could be useful.

    Thank you everybody!
    Regards

Gilbert

Let me see if I can help.

1. In V2.7+, to make a screenshot sprite, you don't need to do the workaround of making a temp save game anymore, check out the sprite function CreateFromScreenShot() from the manual.

2. Since in V2.7+ you're more recommended to use the pointerish function Sprite.Delete() rather than the old functions DeleteSprite() and LoadSaveSlotScreenshot(), etc., which work on sprite number.
From the manual, it seems that you have to work past one problem:
Quote
IMPORTANT: If the DynamicSprite instance is released from memory (ie. there is no longer a DynamicSprite* variable pointing to it), then the sprite will also be removed from memory. Make sure that you keep a global variable pointer to the sprite until you are finished with it, and at that point call Delete.
That is, if you create a dynamic sprite you must define a DynamicSprite* pointer to hold it, whereas:
- If you define a DynamicSprite* pointer inside of a function, make sure that the sprite is only usedÃ,  inside the scoop of that function (otherwise the game may not work if you still want it outside of this function), since the variable will be destroyed (alongside with the sprite) when the function ends, so if you want to use it somewhere else, declare this variable outside of the function, on top of the script.
- Since old functions like LoadSaveSlotScreenshot() don't return a DynamicSprite* pointer, they're probably obsolete and won't work now, since you need to keep a copy of that pointer for the sprite to stay.

Either way, what I think is that, unless you really need to, you don't normally need to delete the sprites yourself, since they'll be taken of by the engine automagically most of the time.

ZakMcKracken

Thank you very much, Gilbot.

I defined a DynamicSprite* variable outside my functions, and used CreateFromScreenShot and CreateFromSaveGame to set and load screenshots.

Then I set that variable to null, so the allocated memory can be freed.

Now it works.

Well, I just test it and as soon as possible I'll make a tutorial, to create a Save/Load GUI with screenshots using AGS 2.7

Regards

SSH

Ooops, sorry, I could have told you most of that staright away but I've been away... since I wrote the tutorial.

Actually, if you look at the source code for the game Pixel Hunt, there is a 2.7 compatible version of the same code.

12

monkey0506

I forgot to say that when working with a pointer, such as:

Code: ags
DynamicSprite* spr = DynamicSprite.CreateFromSaveGame(...);


That you should test to make sure that the object pointed to exists:

Code: ags
if (spr != null) { /* do stuff */ }

ZakMcKracken

Hello SSH,

thank you very much for your help. I downloaded source code of your game, you are great!
First of all, because you produced 2 distinct modules, and second... it works perfectly!

Thank you everybody.

Regards.

simulacra

I have intensely studied the pixel hunt code as well as this thread and tried unsuccessfully to modify the old sgs to work in 2.7. I think that the problem is that I do not know what I am doing.

Code: ags
function sgs_getslots()
{
int i=1; // Loop counter starts at 1
while(i<=6) { // Count from 1 to 6
if (GetSaveSlotDescription(i, sgs_struct[i].t)) { // Slot exists
[b]sgs_struct[i].spr=DynamicSprite.CreateFromSaveGame(i, SGS_WIDTH, SGS_HEIGHT);[/b]

} else { // There is no saved game for this slot
StrCopy(sgs_struct[i].t, ""); // Blank description
sgs_struct[i].spr=SGS_EMPTY_SPRITE; // Empty sprite
}
SetLabelText(SAVELOAD, 6+i, sgs_struct[i].t); // Set GUI label to description
SetLabelColor(SAVELOAD, 6+i, SGS_LABEL_COLOUR); // Set GUI label colour
SetButtonPic(SAVELOAD, i, 1, sgs_struct[i].spr); // Set button to have screenshot pic
i=i+1; // next slot
}
// Get current game ss, too
Wait(1); // make sure screen is updated
//SaveGameSlot(100, "temp"); // Save current game in temp slot
//Wait(20);
//sgs_struct[0].spr=DynamicSprite.CreateFromScreenShot(SGS_WIDTH, SGS_HEIGHT); // load up screenshot
//DeleteSaveSlot(100); // Delete temporary slot
sgs_sprite = DynamicSprite.CreateFromScreenShot(SGS_WIDTH, SGS_HEIGHT);
}


The first highlighted line gives me an error about trying to assign a sprite to an int. I guess I must have mixed apples and pears, but what do I do instead?

I commented out the old-school code and tried to replace it with what I think is a pointer to a dynamic sprite.

I am really have angst regarding this as I am supposed to hand the project over to the printer at friday and spent several days messing this up even further.  :'(

SSH

The latest beta of my modules to do these are available here, along with some other crap: http://www.lumpcity.co.uk/~ssh/sgs_gue_prob.rar

but make sure you use latest beta AGS  as the GUE import is broken pre 2.71 beta 5. If you must try with an earlier version, make sure you back up your game files first, as the broken GUE import can totally screw up a game.

As for your code, sim, DynamicSprite functions return a DynamicSprite * which I used the array dspr for in my  Pixel Hunt code that you have. so replace sgs_struct.spr with dspr on the first line (that bold doesnt work, btw)

I'm just adjusting the modules to use new strings and I should be done.
12

simulacra

I see.

The line:

Code: ags
    AskYesNo("Overwrite savegame?");


Causes a type mismatch error "cannot convert const string to string".  :-\

SSH

Yeah, change all the string parameters of functions to const string.... see the beta thread for CJ's explanation
12

SMF spam blocked by CleanTalk