Legacy GM More texture pages? sprite_create_from_surface

Hello all,

With the use of sprite_create_from_surface, is an entirely new texture page created on the fly to store the newly created sprite? And if so, if sprite_create_from_surface is used multiple times, are multiple new texture pages created, or, are the newly created sprites added to the previously created texture page? The angle here is that I am concerned about having an outrageous number of texture swaps.

This entry from the manual does not discuss it:
The [below] code creates a surface and stores its index in the local variable "surf". It then targets that surface, clears it and draws several sprites on top of each other. Finally it creates a new sprite from the composite image drawn on the surface and assigns its index to "spr_Custom" before freeing up the memory used by the surface.
Code:
var surf;
surf = surface_create(32, 32);
surface_set_target(surf);
draw_clear_alpha(c_black, 0);
draw_sprite(spr_Body, 0, 0, 0);
draw_sprite(spr_Clothes, 0, 0, 0);
draw_sprite(spr_Hair, 0, 0, 0);
spr_custom = sprite_create_from_surface(surf, 0, 0, 32, 32, true, true, 16, 16);
surface_reset_target();
surface_free(surf);
 

Simon Gust

Member
Hello all,

With the use of sprite_create_from_surface, is an entirely new texture page created on the fly to store the newly created sprite? And if so, if sprite_create_from_surface is used multiple times, are multiple new texture pages created, or, are the newly created sprites added to the previously created texture page?

This entry from the manual does not discuss it:
The [below] code creates a surface and stores its index in the local variable "surf". It then targets that surface, clears it and draws several sprites on top of each other. Finally it creates a new sprite from the composite image drawn on the surface and assigns its index to "spr_Custom" before freeing up the memory used by the surface.
Code:
var surf;
surf = surface_create(32, 32);
surface_set_target(surf);
draw_clear_alpha(c_black, 0);
draw_sprite(spr_Body, 0, 0, 0);
draw_sprite(spr_Clothes, 0, 0, 0);
draw_sprite(spr_Hair, 0, 0, 0);
spr_custom = sprite_create_from_surface(surf, 0, 0, 32, 32, true, true, 16, 16);
surface_reset_target();
surface_free(surf);
I doesn't really create a texture page, just a texture. This texture is the exact size of the surface.
 
I doesn't really create a texture page, just a texture. This texture is the exact size of the surface.
OK, so a new texture page is not created. What if a sprite resource is on a texture page (as they are created normally), and then a call to sprite_delete(index) is made to that particular sprite? Is it erased from the texture page, or is that sprite index simply set to zero, with no way to access back to the original texture page? Subsequently, if a call is made to sprite_create_from_surface and the specified index is the same as the one that was just deleted, I assume, (as you just mentioned) that there are no changes made to any textures pages nor are any new ones created, and the sprite index is simply set to the new texture. Does this texture reside in computer memory, or graphics card memory?
This function will delete a sprite from the game, freeing any memory that was reserved for it. This is a permanent removal, and if the asset that you delete was included as part of the game's resources, not even restarting the game (unless you close the application first) will recover it. This is a very important function for those moments when you need to create and change sprites from external resources and should always be used to remove those assets that are no longer needed by a game, or to clear an indexed asset from a variable before re-assigning another asset to that variable.
 

RangerX

Member
If you create a sprite of background, a texture page is created with that sprite on background on it.
If you use "sprite_delete" or "background_delete", that texture page is erased forever.
If you create a surface, you created only that surface, its a texture in itself.
If you use surface delete, you delete that surface forever.



The only way you will leak memory is that way:
Let's say you create a sprite and you immediately catch it in a variable:

PauseBackground=sprite_create_from_surface();

And then, you never flush it with the delete function and then you pause the game again:

PauseBackground=sprite_create_from_surface();

The new sprite is now referenced into "PauseBackground" and the previous sprite is now unreferenced and therefore unaccessible forever. (memory leak).
 

CMAllen

Member
OK, so a new texture page is not created. What if a sprite resource is on a texture page (as they are created normally), and then a call to sprite_delete(index) is made to that particular sprite? Is it erased from the texture page, or is that sprite index simply set to zero, with no way to access back to the original texture page? Subsequently, if a call is made to sprite_create_from_surface and the specified index is the same as the one that was just deleted, I assume, (as you just mentioned) that there are no changes made to any textures pages nor are any new ones created, and the sprite index is simply set to the new texture.
This function will delete a sprite from the game, freeing any memory that was reserved for it. This is a permanent removal, and if the asset that you delete was included as part of the game's resources, not even restarting the game (unless you close the application first) will recover it. This is a very important function for those moments when you need to create and change sprites from external resources and should always be used to remove those assets that are no longer needed by a game, or to clear an indexed asset from a variable before re-assigning another asset to that variable.
This is wrong. Every sprite you create at run time DOES create a new texture page. If you were to create all your tiles via that routine and then draw them, you'd have many times more texture swaps than you would if you pre-loaded them into GM and let GM pack them onto texture pages itself.

This is one facet of GM that people lament -- the lack of run-time texture page tools/controls. Which isn't to say that you can't do it, it's just that all the controls and methods you typically let GM handle will have to be created and managed by your own code. For sprites, that means mapping sprite_index and image_index to the correct UV coordinates and boundaries on your texture pages, sprite origins and offsets, which page a given sprite is on, etc. Quite a few users have requested, on multiple occasions, some method or ability to define our own texture pages, sprites, and the sub-images contained on those texture pages.
 

Jabbers

Member
Yes, it can get ugly adding custom sprites and backgrounds. I had to get help creating a custom texture page system, after I realised how each imported sprite takes up its own texture page. If you import an animated sprite this way, you get a new page per frame. Not good.
 

ph101

Member
Yes, it can get ugly adding custom sprites and backgrounds. I had to get help creating a custom texture page system, after I realised how each imported sprite takes up its own texture page. If you import an animated sprite this way, you get a new page per frame. Not good.
Could you give some pointers as to how to avoid this? My game has many animated NPCs - I was planning a system whereby using a bunch of elements, I can assemble sprites dynamically with different bits and peices. i was going to draw the six frames on a new surface, eg walk animation, then a random hat or whatever on top of the sprite, then create sprite from surface. This seemed a good way to get big combinations of possible sprites. Not if I need a texture page per frame though. I may have misunderstood.
 

CMAllen

Member
Could you give some pointers as to how to avoid this? My game has many animated NPCs - I was planning a system whereby using a bunch of elements, I can assemble sprites dynamically with different bits and peices. i was going to draw the six frames on a new surface, eg walk animation, then a random hat or whatever on top of the sprite, then create sprite from surface. This seemed a good way to get big combinations of possible sprites. Not if I need a texture page per frame though. I may have misunderstood.
That is exactly the kind of scenario that many developers want to work with but have to create their own texture page management system to accomplish, because GM's run-time texture management tools/controls are so sorely lacking. Even if the user had to handle image packing on run-time created texture pages, it would still be leaps and bounds better than what is currently possible (which is basically nothing without creating it yourself).

Spitballing the minimum necessary functions here, just because:
t_page_from_surface(surface, b_removeback, b_smooth, scale_power2); (returns id of new t_page)
t_page_from_image(file, b_removeback, b_smooth, scale_power2); (returns id of new t_page)
t_page_delete(t_page, b_autoclean); (deletes t_page and cleans out associated sprite defs or flags it for deletion once all sprites defs are removed)
sprite_def_create(origin_x, origin_y, width, height) (returns new sprite_index id empty)
sprite_define(t_page, sprite_index, image_index, x_coord, y_coord)

Really, these are the only new functions a user would need to handle texture pages manually. The rest of the functions necessary are already present within GM. It's just those basic functions that are lacking. And being native functions, they would be faster than interpreted user-created versions, in addition to not requiring the user write their own drawing routines to take advantage of user-created texture pages (which, being interpreted, would also be slower).
 

ph101

Member
That is exactly the kind of scenario that many developers want to work with but have to create their own texture page management system to accomplish, because GM's run-time texture management tools/controls are so sorely lacking. Even if the user had to handle image packing on run-time created texture pages, it would still be leaps and bounds better than what is currently possible (which is basically nothing without creating it yourself).

Spitballing the minimum necessary functions here, just because:
t_page_from_surface(surface, b_removeback, b_smooth, scale_power2); (returns id of new t_page)
t_page_from_image(file, b_removeback, b_smooth, scale_power2); (returns id of new t_page)
t_page_delete(t_page, b_autoclean); (deletes t_page and cleans out associated sprite defs or flags it for deletion once all sprites defs are removed)
sprite_def_create(origin_x, origin_y, width, height) (returns new sprite_index id empty)
sprite_define(t_page, sprite_index, image_index, x_coord, y_coord)

Really, these are the only new functions a user would need to handle texture pages manually. The rest of the functions necessary are already present within GM. It's just those basic functions that are lacking. And being native functions, they would be faster than interpreted user-created versions, in addition to not requiring the user write their own drawing routines to take advantage of user-created texture pages (which, being interpreted, would also be slower).
Darn. Thanks for the info. Going to have to come up with a new plan...
 
Top