0

Alright so im using Raylib.h and got stuck in this code for a while now. I want to have a smooth animating movement of the velocity vector of the ball from one point to another. Basically The principle is to drag at any point on the screen and the ball will go opposite direction to that like a bow? But it goes at instant from one point to another which i dont want

typedef struct Ball {
        Vector2 position;
        Vector2 speed;
        float radius;
        bool active;
    }  Ball;

int main (void)
{
    const int width = 1080;
    const int height = 720;
    static Ball ball = {0};
    Vector2 pos1;
    Vector2 pos2;
    Vector2 posChange;

    SetTargetFPS(60);

    InitWindow(width,height,"Midny is sad frfr");
    Texture2D background = LoadTexture("green_checker.png");

    ball.position = (Vector2){(width)/4, height-80};
    ball.speed = (Vector2){0 , 0};
    ball.radius = 8;
    ball.active = false;

    while(!(WindowShouldClose()))
    {
        if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT)){
             pos1 = GetMousePosition();

        }

        if(IsMouseButtonDown(MOUSE_BUTTON_LEFT)){
             pos2 = GetMousePosition();
             posChange = Vector2Subtract(pos2,pos1);

        }

        if(IsMouseButtonReleased(MOUSE_BUTTON_LEFT)){
            Vector2 DirectionVelocityVector = Vector2Negate(posChange);
            //float distance = Vector2Distance(posChange,pos1);
            ball.active = true;
           
            //Vector2 target = Vector2MoveTowards(ball.position,DirectionVelocityVector,distance/10000);
            ball.speed = (Vector2) { DirectionVelocityVector.x, DirectionVelocityVector.y};
            Vector2 movementThisFrame = Vector2Scale(ball.speed,GetFrameTime()*200);
            ball.position = Vector2Add(ball.position,movementThisFrame);
            if(ball.active){
                ball.position.x = ball.position.x + ball.speed.x;
                ball.position.y = ball.position.y + ball.speed.y;
            }
        }
        BeginDrawing();
        ClearBackground(RAYWHITE);
        DrawTexture(background,0,0,WHITE);

        



        DrawCircleV(ball.position,ball.radius,WHITE);
        EndDrawing();
    }


}

I was expecting a smooth animated movement but it doesnt expect to happen ig.. It moves at instant from one point to another? Is there any possible way to fix this thank you

Oka
  • 23,367
  • 6
  • 42
  • 53
  • `GetFrameTime()*200`, what's this `200` stands for? What if you make it 1 or maybe 0.1? – Todd Wong Dec 10 '22 at 15:14
  • And `IsMouseButtonPressed` and `IsMouseButtonDown` seems unintuitive, what's there behivour? I thought you should save position to pos1 when mouse down, and save position to pos2 when release. But when the hack "pressed" triggers? – Todd Wong Dec 10 '22 at 15:17
  • @ToddWong alright so for the second one Ismousebuttonpressed and IsmouseButtonDown are different. First one gets the position when the mouse was clicked/tapped at any arbitrary point on the screen while ismousebuttondown changes the value of the position while the mouse button is pressed – Midnight Demise Dec 10 '22 at 16:03
  • also no effect comes when i add **0.1** to it instead of 200 :C – Midnight Demise Dec 10 '22 at 16:06
  • Yeah, took another look. Why `ball.active = true`? And in your `if(ball.active){...}` you just add ball.speed (which is effectively the same as -posChange) to ball.position at once. You want animation, you have to add it portion by portion, not all at once. (I suppose IsMouseButtonReleased only triggered everytime you release the button) – Todd Wong Dec 10 '22 at 18:40

1 Answers1

0

Two issues:

  1. You are only ever updating the position of the ball during a frame in which the mouse button has just been released. There will only be one instance of this occurring each time the mouse is clicked, dragged, and released.

  2. You are setting the speed of the ball equal to the inverse distance the mouse traveled. The speed (velocity here) of an object should be the amount it will change in a given time frame (a step).

These two problems combined cause the ball to make a single, large change in position.

There are more than a few ways to address this, and each approach depends on how you want an object to move, and how the input influences its movement.


Here is one example of of translating the change in mouse position into a change in velocity for the object.

The object is always being updated every frame, and as such multiple instances of input may overlap.

#include <raylib.h>
#include <raymath.h>

int main(void)
{
    const int width = 1080;
    const int height = 720;

    InitWindow(width, height, "Don't be sad!");
    SetTargetFPS(60);

    struct {
        Vector2 position;
        Vector2 velocity;
        float radius;
    } ball = { .position = { width / 2.f, height / 2.f }, .radius = 8.f };

    Vector2 click_origin;

    while (!WindowShouldClose()) {
        if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
            click_origin = GetMousePosition();

        if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) {
            Vector2 difference = Vector2Negate(Vector2Subtract(GetMousePosition(), click_origin));
            ball.velocity = Vector2Add(ball.velocity, Vector2Scale(difference, .05f));
        }

        /* Update position, and apply friction */
        ball.position = Vector2Add(ball.position, ball.velocity);
        ball.velocity = Vector2Scale(ball.velocity, .95f);

        BeginDrawing();
        {
            ClearBackground(RAYWHITE);
            DrawCircleV(ball.position, ball.radius, RED);
        }
        EndDrawing();
    }
}

Here is an example of installing an uninterruptible animation in the object, with a duration of 120 frames. Multiple instances of mouse input cannot affect the object simultaneously.

#include <raylib.h>
#include <raymath.h>

int main(void)
{
    const int width = 1080;
    const int height = 720;

    InitWindow(width, height, "Don't be sad!");
    SetTargetFPS(60);

    struct {
        Vector2 position;
        float radius;
        struct {
            unsigned frames;
            Vector2 step;
        } animation;
    } ball = { .position = { width / 2.f, height / 2.f }, .radius = 8.f };

    Vector2 click_origin;

    while (!WindowShouldClose()) {
        if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
            click_origin = GetMousePosition();

        if (ball.animation.frames) {
            ball.position = Vector2Add(ball.position, ball.animation.step);
            ball.animation.frames--;
        } else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) {
            Vector2 difference = Vector2Negate(Vector2Subtract(GetMousePosition(), click_origin));

            ball.animation.frames = 120;
            ball.animation.step = Vector2Scale(difference, 1/120.f);
        }

        BeginDrawing();
        {
            ClearBackground(RAYWHITE);
            DrawCircleV(ball.position, ball.radius, RED);
        }
        EndDrawing();
    }
}
Oka
  • 23,367
  • 6
  • 42
  • 53