• Hey! Guest! The 36th GMC Jam will take place between February 27th, 12:00 UTC - March 2nd, 12:00 UTC. Why not join in! Click here to find out more!

Alpha parts of one sprite using another

Nakwatuk

Member
I've searched a number of methods using gpu_set_colorwriteenable() to create a mask of a sprite within another sprite. However, I'm seeking a method to using an inverse of this.

Say there's a player sprite and the player is carrying an item. The item is represented as another sprite that is drawn right after. However, I only want the part of the item's sprite that is not overlapping the player to show. I'm also using full sprite sheets for these and not individual sprite frames.

This would be handy in a number of applications such as left to right handedness of an item but using the same sprite, etc. Any insight would be most helpful.

Cheers,
Nak
 

Binsk

Member
Try drawing the player onto a small surface and then draw the item on top of the player with a modified blend mode. When done, draw the surface as normal.

For blend mode, going off the top of my head here, you could probably do something like:
Code:
surface_set_target(player_surf);
draw_sprite(player, ...);
gpu_set_blendmode_ext(bm_inv_dest_alpha, bm_one);
draw_sprite(item, ...);
gpu_set_blendmode(bm_normal);
surface_reset_target();
draw_surface(player_surf, ...)
My selected blend-mode might not quite be right (I'd have to mess with it to see), but perhaps something like that.

The goal here is to draw your player normally onto the surface and then, when drawing your item, you try multiplying your item's alpha by the inverse of the surface's alpha. Just make sure you clear the alpha to 0 on the surface before drawing anything. This way, since the player is drawn with an alpha of 1 on the surface then you'd get the inverse of 0 which negate's your item's alpha. If the player is NOT drawn at the position then there is an alpha of 0 which gives the inverse of 1 and then draws your item.
 

Nakwatuk

Member
Binsk, much appreciate your quick response on this one. I feel like the method you're mentioning is possibly getting me somewhere, but I may not be quite there.

Below is the code I have in place (ignoring the other instance variables like x_frame_, frame_size_, y_frame_ etc. because the two draw_sprite_part functions work on their own before attempting to implement this. I'm not positive my surface_create is correct. When I run, I get nothing drawn. This comes down to my ignorance on surface drawing.

Just to reiterate (and I think you're clear on this) but I'm trying to get the item draw to only draw where the player's pixels are not.

// Create event:
Code:
player_surf_ = surface_create(global.game_width, global.game_height);
// Draw event:
Code:
surface_set_target(player_surf_);

// Draw player
draw_sprite_part(spr_base_, 0, floor(x_frame_) * frame_size_, y_frame_ * frame_size_, frame_size_, frame_size_, _xx, _yy);

// Draw item
gpu_set_blendmode_ext(bm_inv_dest_alpha, bm_one);
draw_sprite_part(test_item, 0, floor(x_frame_) * frame_size_, y_frame_ * frame_size_, frame_size_, frame_size_, _xx, _yy);
gpu_set_blendmode(bm_normal);

surface_reset_target();
 
Top