Legacy GM How Check Non-Existing Variables?

Posho

Member
Hello, I need some help with what might be an easy one:

I'm trying to use the sprite_exists function to check whether a sprite already exists within the game or not, but I get an execution error when such sprite doesn't actually exist.

The follow code is erroneous:
Code:
if sprite_exists(spr)
{
//do something
}
Any help?
 
Hello, I need some help with what might be an easy one:

I'm trying to use the sprite_exists function to check whether a sprite already exists within the game or not, but I get an execution error when such sprite doesn't actually exist.

The follow code is erroneous:
Code:
if sprite_exists(spr)
{
//do something
}
Any help?
What is the error?

Is spr a variable or the name of your resource?
 
S

SyntheticStorm9

Guest
do

if instance_exists(sprite you wanted to do)
{
do what you wanted to do here
}

instead,
the sprite_exists function is for arrays.
 

Posho

Member
The most important rule of anything related to programming: If there's an error message, post the whole error message.
What is the error?
Alrighty.
Code:
___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Create Event
for object obj_wall:

Variable obj_wall.spr(100002, -2147483648) not set before reading it.
 at gml_Script_sprite_tween_new (line 8) - if sprite_exists(spr)
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_sprite_tween_new (line 8)
called from - gml_Object_obj_wall_CreateEvent_1 (line 10) -         sprite_tween_new(spr_test_brick_2_swf, false)

Is spr a variable or the name of your resource?
"spr" is the name of the sprite that gets created within an object/instance.
For example: sprite_index = object.spr
 
S

SyntheticStorm9

Guest
I think you did obj_wall.spr
instead of just the actual sprite
 

TsukaYuriko

☄️
Forum Staff
Moderator
You seem to be confusing sprites with variables. They are not the same.

Sprite IDs can be assigned to variables as values. sprite_exists checks whether a given sprite ID (whether hard-coded or contained in a variable) is mapped to a sprite. It does not check whether the variable you are supplying exists (read: has been declared and assigned a value). Attempting to use a variable that does not exist will always result in an error message being thrown, and there is no way to check whether a variable exists.

Always declare all of your variables before you use them. In special cases like this, you may want to assign a default value that won't produce false positives to them upon declaration, e.g. by setting them to -1, since that is not a valid sprite ID under any circumstances.
 

Posho

Member
That's not how creating sprites works. Sprites can be created with functions like sprite_create_from_surface.
I know. That was just an example to show you how I assign sprites to variables in this case.


You seem to be confusing sprites with variables. They are not the same.

Sprite IDs can be assigned to variables as values. sprite_exists checks whether a given sprite ID (whether hard-coded or contained in a variable) is mapped to a sprite. It does not check whether the variable you are supplying exists (read: has been declared and assigned a value). Attempting to use a variable that does not exist will always result in an error message being thrown, and there is no way to check whether a variable exists.

Always declare all of your variables before you use them. In special cases like this, you may want to assign a default value that won't produce false positives to them upon declaration, e.g. by setting them to -1, since that is not a valid sprite ID under any circumstances.
Okay, I get you. So is there seriously no way to check if a variable exists then?

Long story short: there's a function within certain objects that makes them create a new sprite using the sprite_create_from_surface function and then adds more subimages with the sprite_add_from_surface function. The issue is that when I restart the game using game_restart, when the instances try to make their sprites once again, all of them lack the first subimage.

My theory is that they're trying to create a sprite that already exists on the game's database, so it doesn't actually create the sprite and the first subimage. However all the other subimages appear normally. That's why I'm trying to use stuff like sprite_exists, is_undefined, etc. so instances can NOT recreate sprites that already exist, but I'm failing at it.

Is there any way to do a "true" game restart?
 

TheouAegis

Member
Restarting the game using game_restart() does not clear everything. You should not even be using game_restart() - it's sloppy code and, as I said, doesn't even initialize everything in your game. You are right in guessing that the sprites still exist.

If you want to use a game_restart() call, you need a persistent object that has a Game End event that destroys all created resources (including paths, data structures, sprites, objects, etc.).
 

TsukaYuriko

☄️
Forum Staff
Moderator
the sprite_exists function is for arrays.
I'm not sure why you would think that this function has anything to do with arrays. I suggest re-reading its manual entry in order to allow you to understand what it is really used for.

Okay, I get you. So is there seriously no way to check if a variable exists then?
Correct. This would require run-time evaluation, which, in turn, would require GML to be an interpreted language, which is not the case (since Studio 1.x).
It is possible to mis-use ds_maps as collections of pseudo-variables that are possible to probe for existence without risking to blow up the program... at a corresponding performance cost... but I wouldn't recommend doing so, as there should never be a situation that requires checking whether a variable exists or not, anyway (if this is "required", there is most likely a better way to achieve the desired result).

Long story short: there's a function within certain objects that makes them create a new sprite using the sprite_create_from_surface function and then adds more subimages with the sprite_add_from_surface function. The issue is that when I restart the game using game_restart, when the instances try to make their sprites once again, all of them lack the first subimage.

That's why I'm trying to use stuff like sprite_exists, is_undefined, etc. so instances can NOT recreate sprites that already exist, but I'm failing at it.
There are a couple of important distinctions to be made here. You may be aware of some of them already, but I'll list them all for the sake of completeness.
  • A variable may exist and hold a value that follows a valid format for a sprite ID, but still not resolve to a valid sprite.
  • A variable that does not hold a value or does not exist can not resolve to a valid sprite. It can't resolve at all; If attempted, an error will be thrown.
  • A sprite that does not exist is not undefined. It just doesn't exist.
  • A variable that does not exist is not undefined. It just doesn't exist.
  • undefined is the state of being declared but not defined, not the state of not existing.

An approach I'd consider suitable would be to take manual control over resource handling instead of relying on the black-box function that game_restart is, because as long as you are in control, if something goes wrong, you at least know where the problem lies (within your code) as opposed to having to figure out whether it even is your fault in the first place (and, therefore, whether you can do anything about it without rewriting everything).

For example, if you're dynamically adding sprites at "game start", you should dynamically remove them at "game end" - so that they can be added at "game start" again when you're restarting the game. Alternatively, implement your own method of keeping track of which sprites and subimages are loaded at which time, and use this info to determine when what needs to be loaded (or unloaded if it's currently not needed for optimization purposes). Instead of calling game_restart, return to your game's title screen or wherever a restart would take you, and using the info you were able to ensure to be suitable for the restarted game state because you are in control of it, you can go from there.
 

Carolusclen

Member
I recently had a similar issue with assigning sprite names to variables
when reading them, the draw_sprite function would not recognize the sprite
i resolved my issue by using asset_get_index

so for example if you had a sprite called My_Sprite assigned to a variable called spr
if you do something like draw_sprite(asset_get_index(My_Sprite),-1,x,y) should work

my issue was pulling sprite names from an array and assigning them to variables. was weird but that worked for me :)
 

Posho

Member
I'm not sure why you would think that this function has anything to do with arrays. I suggest re-reading its manual entry in order to allow you to understand what it is really used for.


Correct. This would require run-time evaluation, which, in turn, would require GML to be an interpreted language, which is not the case (since Studio 1.x).
It is possible to mis-use ds_maps as collections of pseudo-variables that are possible to probe for existence without risking to blow up the program... at a corresponding performance cost... but I wouldn't recommend doing so, as there should never be a situation that requires checking whether a variable exists or not, anyway (if this is "required", there is most likely a better way to achieve the desired result).


There are a couple of important distinctions to be made here. You may be aware of some of them already, but I'll list them all for the sake of completeness.
  • A variable may exist and hold a value that follows a valid format for a sprite ID, but still not resolve to a valid sprite.
  • A variable that does not hold a value or does not exist can not resolve to a valid sprite. It can't resolve at all; If attempted, an error will be thrown.
  • A sprite that does not exist is not undefined. It just doesn't exist.
  • A variable that does not exist is not undefined. It just doesn't exist.
  • undefined is the state of being declared but not defined, not the state of not existing.

An approach I'd consider suitable would be to take manual control over resource handling instead of relying on the black-box function that game_restart is, because as long as you are in control, if something goes wrong, you at least know where the problem lies (within your code) as opposed to having to figure out whether it even is your fault in the first place (and, therefore, whether you can do anything about it without rewriting everything).

For example, if you're dynamically adding sprites at "game start", you should dynamically remove them at "game end" - so that they can be added at "game start" again when you're restarting the game. Alternatively, implement your own method of keeping track of which sprites and subimages are loaded at which time, and use this info to determine when what needs to be loaded (or unloaded if it's currently not needed for optimization purposes). Instead of calling game_restart, return to your game's title screen or wherever a restart would take you, and using the info you were able to ensure to be suitable for the restarted game state because you are in control of it, you can go from there.
Wow, thanks for all the help, seriously. ;)

I just tried deactivating the sprites manually at game_end like you said using sprite_delete. No error messages pop-up but when restarting the game the same mistakes happen. Which makes me think maybe this has nothing to do with the issue. But -again- like you said I can just jump between rooms and do some sort of fake restart. Restarting the game is not a real issue at the moment at least.

However, now you made me think. The reason why this might be happening is because I'm trying to create sprites over sprites that already exist. The sprites in this game are needed to be created only once, not each time the game runs which can lead to really long load times and screw with memory once the project gets very asset-heavy. I completely forgot, but is is it possible to create sprites and save them directly into a directory on my PC instead of just having temporal sprites while the game is running? I could keep track of what sprites already exist (to avoid the non-existing variable/sprite issue we discussed earlier) through an INI file cache/array.


I recently had a similar issue with assigning sprite names to variables
when reading them, the draw_sprite function would not recognize the sprite
i resolved my issue by using asset_get_index

so for example if you had a sprite called My_Sprite assigned to a variable called spr
if you do something like draw_sprite(asset_get_index(My_Sprite),-1,x,y) should work

my issue was pulling sprite names from an array and assigning them to variables. was weird but that worked for me :)
Not too sure how this relates, but I didn't know this function existed. I can already see the possibilities with it.
 

TheouAegis

Member
Asset get index is for people who don't know the difference between a resource name and a resource ID. The only time you should even ever be using a resource name is in the debug mode.

Yes, you can save the Sprites to disk and use some file to keep track of which Sprites have been created into the program already.
 
Top