Destroyable image/sprite

Hello!
Probably noob stuff .. but ... :) .. I am trying to figure out a way to make a destroyable image/sprite. As an example, the shields/bunkers in Space Invaders which get destroyed at bullets impacts positions. Any suggestions? How do I plot transparent holes in an image/sprite, probably something can be done using Surface? I will probably also require pixel perfect collision.

Any suggestions for how I could do this?

Thanks,
Olla
 

ghandpivot

Member
That is hardly "noob stuff", yet it's not overly complex. I would go about this in one of two ways to give you a guidance of what to look into.

Method 1. Draw a sprite and slice it up so that each subimage of the sprite contains a square part of it (or any shape really). Then in the draw event you use an array and a for loop to draw each segment on top of eachother. Whenever the character takes damage, you either remove a segment at random or one that corresponds to the hit place.

Method 2. Use surfaces. Create one the size of your sprite and set it transparent (draw_clear_alpha(0,0)). Then draw your sprite onto it. Then draw whatever shape you want to destroy from your sprite on top of the surface, with blend mode set to bm_subtract. If you then want to keep your destroyed sprite you can store it in a variable with sprite_create_from_surface and refer to it for the next destruction and so on.
 
That is hardly "noob stuff", yet it's not overly complex. I would go about this in one of two ways to give you a guidance of what to look into.

Method 1. Draw a sprite and slice it up so that each subimage of the sprite contains a square part of it (or any shape really). Then in the draw event you use an array and a for loop to draw each segment on top of eachother. Whenever the character takes damage, you either remove a segment at random or one that corresponds to the hit place.

Method 2. Use surfaces. Create one the size of your sprite and set it transparent (draw_clear_alpha(0,0)). Then draw your sprite onto it. Then draw whatever shape you want to destroy from your sprite on top of the surface, with blend mode set to bm_subtract. If you then want to keep your destroyed sprite you can store it in a variable with sprite_create_from_surface and refer to it for the next destruction and so on.
Thanks for feedback, very helpful. I will try and explore method 2, even if it is the most difficult of the two, I think it is the result I am looking for. ;) I will post an update. Thanks once again!
 
Thanks for feedback, very helpful. I will try and explore method 2, even if it is the most difficult of the two, I think it is the result I am looking for. ;) I will post an update. Thanks once again!
Update: thanks for your tips Ghandpivot, I managed to knock together an initial test that works. I just need to make it more flexible now. :)

Here's what I did:

if (!surface_exists(mask)){
mask = surface_create(128,128);
}

surface_set_target(mask);
draw_sprite(spr_custom,0,0,0);

gpu_set_blendmode(bm_subtract);
draw_circle(irandom_range(0,128),irandom_range(0,128),10,false); // just drawing circles at random positions for now
gpu_set_blendmode(bm_normal);

spr_custom = sprite_create_from_surface(mask, 0, 0, 128, 128, false, true, 0, 0);

surface_reset_target();
surface_free(mask);

draw_sprite(spr_custom,0,800,800);
 

ghandpivot

Member
Cool, you did all that yourself! I think you might run into memory problems if you do not delete the left over sprites (sprite_delete) if this is run every step. Everytime spr_custom creates a new sprite from the surface, the old one is just left in the void which can be a problem in a full size project. I'm a bit uncertain about all that though, I've probably never made a project with surfaces myself.
 
Cool, you did all that yourself! I think you might run into memory problems if you do not delete the left over sprites (sprite_delete) if this is run every step. Everytime spr_custom creates a new sprite from the surface, the old one is just left in the void which can be a problem in a full size project. I'm a bit uncertain about all that though, I've probably never made a project with surfaces myself.
Yeah, I figured out because it slowed down after a short while, but I have fixed that now. Plus, I only update upon collision now.
There is a new problem I am facing at the moment and that is related to collision. For some unknown reason collision between bullets and the spr_custom seems off. I have set collision to pixel perfect, but it does work right and I am not sure why - but I am looking into this now.
 

ghandpivot

Member
Without seeing the project I think this might be because you are currently drawing the sprite. It is not the sprite_index of the object and will thus not be the mask for it.
If you make sure to set sprite_index = spr_custom and perhaps also sprite_collision_mask to it (probably don't need both?) then you might get better results. Don't forget to also rotate the actual sprite of the object if you're rotating the drawn sprite.
 
Without seeing the project I think this might be because you are currently drawing the sprite. It is not the sprite_index of the object and will thus not be the mask for it.
If you make sure to set sprite_index = spr_custom and perhaps also sprite_collision_mask to it (probably don't need both?) then you might get better results. Don't forget to also rotate the actual sprite of the object if you're rotating the drawn sprite.
Thanks for feedback. Yes, that was it. :) it all seems to be working as intended now even when it is rotating, etc. Thanks for you help, Ghandpivot :)
 
@ghandpivot : Hello! been away from my project for a while but now back onto it again. :) There's a rotation shield at the center of the screen which you, the player can destroy.. It works ... but sometimes I get a "trying to draw non-existing sprite" error.. and after hours of trying to figure out what's wrong I still haven't figured it out :/ ... So Reaching out to hear if you can can spot what I am doing wrong.. Here's the code (cut it down to the essential)..

Thanks, Olla
 

Attachments

ghandpivot

Member
Without seeing the rest of the code, do you ever delete or clear spr_custom?
Because in the code provided, you draw spr_custom before you define it (which works since it's defined in the create_event). This means that if you ever clear spr_custom somewhere else, the code will try to draw a non-existing sprite.
 
Without seeing the rest of the code, do you ever delete or clear spr_custom?
Because in the code provided, you draw spr_custom before you define it (which works since it's defined in the create_event). This means that if you ever clear spr_custom somewhere else, the code will try to draw a non-existing sprite.
Thanks for your reply. You were right!! I actually used "spr_custom" elsewhere for something else :/ and which I had completely forgotten about. I changed it and problem seems solved. A simply search on "spr_custom" and I would have figured, doh! Thanks once again.

/Olla
 
Cool, you did all that yourself! I think you might run into memory problems if you do not delete the left over sprites (sprite_delete) if this is run every step. Everytime spr_custom creates a new sprite from the surface, the old one is just left in the void which can be a problem in a full size project. I'm a bit uncertain about all that though, I've probably never made a project with surfaces myself.
You're 100% right

It's always good practice to delete/close it as soon as it's no longer needed when you manually put something into memory via code so you don't wind up with a leak that keeps getting worse and worse as more assets are manually loaded
 
Top