How to dynamic crop a sprite by angle?

Hi, I’m trying to develop a game where you get a full turn around a object to capture it.

How can I dynamic clip the sprite animation of the circle based in the player angle to follow the progress of the player around the creature? Is it possible?

It is a little hard to understand your writing. What I think you’re saying is you want to rotate the circle so that the white line is always pointing toward the player, correct?

If so, then assuming the circle is its own game object with sprite components, you can use go.set(url, “euler.z”, degrees) to rotate the game object to the specified degrees. You will have to do the trigonometry to find the angle between the center of the circle to the player.

Hint:

-- Returns angle between `origin` and `destination` in radians.
-- Use math.deg() to convert to degrees for euler transformations.
-- z components are ignored.
function angle(origin, destination)
	return math.atan2(destination.y - origin.y, destination.x - origin.x)
end
1 Like

Actually, I already implemented this part that you mentioned in the spell (yellow).

The goal of the player is to complete the circle around the target.
However I need to visually indicate how much of the circle he already made.
I have the current angle and all the information about position of the itens, but I don’t know how to crop the sprite animation like the blue circle in this reference image, based on the player position.
Is it possible?

1 Like

Is the circle one sprite component? What does that game object look like in the editor?

1 Like

Yes, the circle is a sprite component that executes an animation.

You can check the whole project on github:

One method that pops into my head is to make a fragment shader and apply it to the capture sprite.

At first, the capture should be fully transparent. For each pixel on the capture, the shader could decide if it should remain transparent or become opaque based on the the player’s starting angle (where he started capturing the monster) and current angle (where he is now). It would be a little bit of trigonometry to calculate which pixels fall within the captured area.

Another way of doing this would be to split the capture sprite into several sprite components, maybe 36 of them. They would all start out with tint.w = 0 (transparent). As the player circles around the monster, change their tints to 1 (opaque). This would work well without having to add shaders, however it wouldn’t be 100% smooth. A new component of the capture would only appear every 10 degrees of the circle, because 360 / 36 = 10.

1 Like

After some research I discovered this shader that apply the effect that I want:

Since I don´t know anything about GLSL, I tryed to learn a bit to understand what’s going on, and adapted the code to the following:

And it’s working great, accepting the values between 0 and 1.

However I can´t apply this on Defold fragment shader, I think that my mistake is to point the figure into the center of the sprite.

varying mediump vec2 var_texcoord0; 
uniform lowp vec4 resolution;
uniform lowp sampler2D texture_sampler; 
uniform lowp vec4 tint;

float circular_crop(vec2 position, float crop_size){
    float radius = length(position.xy);
    float angle = degrees(atan(-position.x, -position.y)) + 180.0; // angle clockwise from the top
    float fa = radians(angle - crop_size * 360.0) * radius + 1.0; // angle edge function
    fa = clamp(fa, 0.0, 1.0);

    return fa;
}

void main()
{
    float progress = 0.5;
    lowp vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w);
    
    vec2 pos = gl_FragCoord.xy - 0.5 * resolution.xy;
    
    float to_crop = circular_crop(pos, progress); 
    vec4 deadzone = vec4(0.0, 1.0, 0.0, 1);
    vec4 col = mix(tint_pm, deadzone, to_crop);

    
    gl_FragColor = texture2D(texture_sampler, var_texcoord0.xy) * col;
}

This code doesn´t apply any change in the sprite, I tried to multiply by green just for debug but I nothing changed in the sprite.

Any light about my mistake on this code?

1 Like

Are you able maybe to create a small repro? :slight_smile:

Otherwise, let’s check out if you have:

  • attached the material to the script? (share a screen shot of your collection with properties of chosen sprite)
  • what tag you have in Material? (share a screen of its material)
  • do you have matched constants with their respective names in Material definition?
1 Like

You can check the entire project here at:

Everything is correctly attatched because I can manipulate the .fp file and see the differences in the sprite section, as you can see:



Today I also tried to draw a basic circle in the middle of the sprite following this tutorial:

And I wasn’t successful. I think that the problem is in the position of the shape, I don’t know how to to point in the center, but I’m keep trying.