Alpha parts of one sprite using another

Discussion in 'Programming' started by Nakwatuk, Feb 8, 2019.

Tags:
  1. Nakwatuk

    Nakwatuk Member

    Joined:
    Sep 29, 2018
    Posts:
    5
    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
     
  2. Binsk

    Binsk Member

    Joined:
    Jun 22, 2016
    Posts:
    583
    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.
     
  3. Nakwatuk

    Nakwatuk Member

    Joined:
    Sep 29, 2018
    Posts:
    5
    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();
    
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice