GMS 2 How to draw a sprite when it's below a different sprite (visible through other objects/sprites)

W

woyosensei

Guest
Hi all!
I'm looking for a solution for a while now, but TBH I have no idea how to "bite it". I am working on top-down game and here and there have some trees spawned randomly around the map/room. What I want to achieve is when the player character is "under" the tree sprite (or any other sprite, like enemies) it will still be visible with some kind of partially drawn effect. I don't know how to call it properly in English (not my native language) but you can see it in almost every sprite-based game (but not limited to). Sometimes is just outline effect, sometimes is kind of transparent method. I was thinking about the method I can use and the couple ideas I have is shaders or surfaces. Also draw_sprite_part can be a way to achieve that, but I have no idea how to do it (yet). I just need to add that trees and player character are on different layers (trees are "higher")
What is the best method to achieve that kind of effect? Do you have any YT tutorials with some examples? Or maybe there is a script somewhere?
I will be very grateful for any help I can get.
Thank you in advance.
Best regards
 
N

northlight

Guest
Step 1 make a tree TOP - this top makes the bottom spawn out of itself
TREETOP - create event -
instance_create(x,y,treebottom)

Step 2 when the player touches the TOP part it will become slightly see through
TREETOP - draw event -
drawself()
if placemeeting(x,y,player) then image_alpha(0.5) else image_alpha(1)


MAKE OBJECTS LIST:
player
treetop(leafs)
treebottom(stump)

ALSO:
Depth needs to be where the player is below the TOP but above the BOTTOM part of the tree to get the effect you want.
 
W

woyosensei

Guest
You talking about isometric view (when the stomp is visible and the world is somewhere between top-down and side-view), not exactly top-down. But you gave me an idea. It's actually good one. Thank you.
 
C

Crazy Star

Guest
I made an example for you. Try putting this in your tress and other overlays:

Create evt
Code:
{
    
    twidth = texture_get_texel_width(sprite_get_texture(sprite_index, 0));
    theight = texture_get_texel_height(sprite_get_texture(sprite_index, 0));
    uniform_radius = shader_get_uniform(shader_lookthru, "radius");
    uniform_texel = shader_get_uniform(shader_lookthru, "texel");
    uniform_player = shader_get_uniform(shader_lookthru, "player");
    
}

Draw evt
Code:
{
    
    if(shader_is_compiled(shader_lookthru)) shader_set(shader_lookthru);
    else show_debug_message("Shader failed");
    
    shader_set_uniform_f(uniform_radius, 128);
    shader_set_uniform_f(uniform_texel, twidth, theight);
    shader_set_uniform_f(uniform_player, (mouse_x-x), (mouse_y-y));
    
    draw_self();
    shader_reset();
    
}

Vertex (default)
Code:
//
// Simple passthrough vertex shader
//
attribute vec3 in_Position;                  // (x,y,z)
//attribute vec3 in_Normal;                  // (x,y,z)     unused in this shader.
attribute vec4 in_Colour;                    // (r,g,b,a)
attribute vec2 in_TextureCoord;              // (u,v)

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
    gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
    
    v_vColour = in_Colour;
    v_vTexcoord = in_TextureCoord;
}

Fragment
Code:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform vec2 player;
uniform vec2 texel;
uniform float radius;

void main()
{
    
    float opacity = 1.0;
    vec2 pos = v_vTexcoord/texel-vec2(radius, radius);
    pos -= player;
    pos /= radius;
    float opa = dot(pos, pos);
    if(opa<1.0) opacity *= opa*opa*opa;
    
    gl_FragColor = v_vColour * vec4(1.0, 1.0, 1.0, opacity) * texture2D( gm_BaseTexture, v_vTexcoord );
}
 
W

woyosensei

Guest
Thank you for solutions! At the moment I'm trying to implement these examples and check which one I can use for my needs. No success so far :p The closest for what I need is @Crazy Star 's shader, but don't know how to adjust it for what I need. Can't adjust radius for player position (shader seems to be working if player's character is on the left side of the tree sprite). Will keep trying, tho. Maybe I can find perfect solution in @YellowAfterlife 's solution as well (looks a little bit odd. I don't know why; in theory it's exactly what I need, in the other hand the code is a little bit confusing)
 
Top