Public Group

# Problem with my sdl code

This topic is 4836 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

My program should move a ball around and if it collides with the stationary ball it stops. I got it to work except one problem, the time_passed variable seems to be 0 in the collision check function but not in the move_balls function. This meens that if I add a check to return false if theres time_passed <= 0 the move_balls function still moves it and the balls overlap, but if i dont have that check it trys to square root 0 in the collision check stuff and everything goes tits up. I suspect its a problem with mixing floats, #defines and Uint32s but I'm not sure.

/* Object Structure */
struct Sball
{
float x_pos, y_pos;
float x_pos_center, y_pos_center;
float x_vol, y_vol;
};
struct Sball ball;
struct Sball ball2;

Uint32 current_time, last_time, time_passed;

bool collision_check()
{
float movement_x, movement_y, movement_length, movement_length_squared;
float normalised_movement_x, normalised_movement_y;
float distance_x, distance_y, distance_length, distance_length_squared;
float dotproduct, dotproduct_squared;
float fred, bob, bob_squared, minimum_movement_length;

/* Quick check */
if (time_passed <= 0)
return false;

movement_x = ball.x_vol * time_passed * DELTA;
movement_y = ball.y_vol * time_passed * DELTA;
movement_length_squared = (movement_x * movement_x) + (movement_y * movement_y);
movement_length = sqrt(movement_length_squared);

normalised_movement_x = movement_x / movement_length;
normalised_movement_y = movement_y / movement_length;

distance_x = ball.x_pos - ball2.x_pos;
distance_y = ball.y_pos - ball2.y_pos;
distance_length_squared = (distance_x * distance_x) + (distance_y * distance_y);
distance_length = sqrt(distance_length_squared);

/* Quick Check */
if ((distance_length - radius_sum) > movement_length)
return false;

dotproduct = (normalised_movement_x * distance_x) + (normalised_movement_y * distance_y);
dotproduct_squared = dotproduct * dotproduct;

/* Quick Check */
if (dotproduct <= 0)
return false;

fred = sqrt(distance_length_squared - dotproduct_squared);

/* Quick check */
return false;

bob_squared = radius_sum_squared - (fred * fred);

if (bob_squared < 0)
return false;

bob = sqrt(bob_squared);

minimum_movement_length = dotproduct - bob;

if (minimum_movement_length > movement_length)
return false;

ball.x_pos += (normalised_movement_x * minimum_movement_length);
ball.y_pos += (normalised_movement_y * minimum_movement_length);
/*ball.x_vol = 0;
ball.y_vol = 0;*/

printf("ball.x_vol: %1.0f, ball.y_vol: %1.0f, time_passed: %d, movement_x: %1.0f, movement_y: %1.0f\n", ball.x_vol, ball.y_vol, time_passed, movement_x, movement_y);
return true;
}

void move_balls()
{
ball.x_pos += (ball.x_vol * time_passed * DELTA);
ball.y_pos += (ball.y_vol * time_passed * DELTA);
}



##### Share on other sites
The "time_passed" variable is modified somewhere in the program where it shouldn't. Check all the places where it is modified between the calls to your two functions, and make sure that what you want to happen actually happens.

##### Share on other sites
In the init code current_time is set to SDL_GetTicks() and this is how its updated in the game loop.

void game_loop(){    /* Update Time stuff */    last_time = current_time;    current_time = SDL_GetTicks();    time_passed = current_time - last_time;        printf("Time_passed: %d\n", time_passed);        get_input();        if (collision_check() == false)        move_balls();    draw_background();    draw_balls();        /* Refresh the screen */    SDL_Flip( screen );    }

##### Share on other sites
It really depends on how you're setting the time_passed variable.

Something with low precision like GetTickCount() will give you zero sometimes, BUT, in the long run it will give just about the correct amount of time that's gone by.

This means your balls will appear to move correctly, even if in some frames time_passed is zero, thus screwing up the collision checking.

The method you're using currently (with the quick check) should be fine, or you could use a higher precision counter like QueryPerformanceCounter that will be less likely to give you zero time passed.

Edit: I see from your reply you're using SDL_GetTicks(), and I'm not sure exactly how that works, but you could still see if there are any other options.

##### Share on other sites
Quote:
 Original post by bjleIt really depends on how you're setting the time_passed variable.Something with low precision like GetTickCount() will give you zero sometimes, BUT, in the long run it will give just about the correct amount of time that's gone by. This means your balls will appear to move correctly, even if in some frames time_passed is zero, thus screwing up the collision checking.The method you're using currently (with the quick check) should be fine, or you could use a higher precision counter like QueryPerformanceCounter that will be less likely to give you zero time passed.Edit: I see from your reply you're using SDL_GetTicks(), and I'm not sure exactly how that works, but you could still see if there are any other options.

Thats the problem though, with the quick check it then goes to move_balls which seems to move it even though time_passed must be 0 and hence shouldn't move it at all :o

##### Share on other sites
That's weird, if you're sure that it is skipping collision and moving the balls at the same frame. (Well, I guess you'd know, if they go through each other!)

What are you using to compile this? You can usually step through your code line-by-line, and watch variables. That would be the next thing I'd try in your situation.

##### Share on other sites
Think I see the problem, If i dont set the x and y vol to 0 then it will carry on into the ball. If I do set it to 0, the next check will square root 0 and mess up. Let me just make sure this is the problem, one moment!

edit: Yeah that fixed the disapearing ball.

bool collision_check(){    float movement_x, movement_y, movement_length, movement_length_squared;    float normalised_movement_x, normalised_movement_y;    float distance_x, distance_y, distance_length, distance_length_squared;    float radius1, radius2, radius_sum, radius_sum_squared;    float dotproduct, dotproduct_squared;    float fred, bob, bob_squared, minimum_movement_length;        movement_x = ball.x_vol * time_passed * DELTA;    movement_y = ball.y_vol * time_passed * DELTA;        /* Quick check (no movement so no collision)*/    if ((time_passed <= 0.0) || ((movement_x == 0) && (movement_y == 0)))        return false;            movement_length_squared = (movement_x * movement_x) + (movement_y * movement_y);    movement_length = sqrt(movement_length_squared);        normalised_movement_x = movement_x / movement_length;    normalised_movement_y = movement_y / movement_length;            radius1 = ball.radius;    radius2 = ball2.radius;        radius_sum = radius1 + radius2;    radius_sum_squared = radius_sum * radius_sum;            distance_x = ball.x_pos - ball2.x_pos;    distance_y = ball.y_pos - ball2.y_pos;    distance_length_squared = (distance_x * distance_x) + (distance_y * distance_y);    distance_length = sqrt(distance_length_squared);        /* Quick Check */    if ((distance_length - radius_sum) > movement_length)        return false;        dotproduct = (normalised_movement_x * distance_x) + (normalised_movement_y * distance_y);    dotproduct_squared = dotproduct * dotproduct;        /* Quick Check */    if (dotproduct <= 0)        return false;        fred = sqrt(distance_length_squared - dotproduct_squared);        /* Quick check */    if (fred >= radius_sum)        return false;            bob_squared = radius_sum_squared - (fred * fred);        if (bob_squared < 0)        return false;        bob = sqrt(bob_squared);        minimum_movement_length = dotproduct - bob;        if (minimum_movement_length > movement_length)        return false;        ball.x_pos += (normalised_movement_x * minimum_movement_length);    ball.y_pos += (normalised_movement_y * minimum_movement_length);    ball.x_vol = 0;    ball.y_vol = 0;        printf("ball.x_vol: %1.0f, ball.y_vol: %1.0f, time_passed: %d, movement_x: %f, movement_y: %f\n", ball.x_vol, ball.y_vol, time_passed, movement_x, movement_y);    return true;}

Problem is now that when the circle should hit the other one, it carries on untill its hit the oposite edge, and then gets flipped back to the outside of the circle. Then it kind of gets stuck on the other ball, if I move my mouse in the other direction it thinks its coming from the other way and flips it back over to the other side. :(

[Edited by - kzar on August 18, 2005 7:34:45 AM]

##### Share on other sites
After alot of hacking about I have found that my program works perfectly if I just invert the dotproduct. Ovbiously this is a hack though so I was wondering if anyone could point out how I should have calculated the dotproduct in the first place? Thanks

bool collision_check(){    float movement_x, movement_y, movement_length, movement_length_squared;    float normalised_movement_x, normalised_movement_y;    float distance_x, distance_y, distance_length, distance_length_squared;    float radius1, radius2, radius_sum, radius_sum_squared;    float dotproduct, dotproduct_squared;    float fred, bob, bob_squared, minimum_movement_length;        movement_x = ball.x_vol * time_passed * DELTA;    movement_y = ball.y_vol * time_passed * DELTA;        /* Quick check (no movement so no collision)*/    if ((time_passed <= 0.0) || ((movement_x == 0) && (movement_y == 0)))        return false;            movement_length_squared = (movement_x * movement_x) + (movement_y * movement_y);    movement_length = sqrt(movement_length_squared);        normalised_movement_x = movement_x / movement_length;    normalised_movement_y = movement_y / movement_length;            radius1 = ball.radius;    radius2 = ball2.radius;        radius_sum = radius1 + radius2;    radius_sum_squared = radius_sum * radius_sum;        distance_x = ball.x_pos - ball2.x_pos;    distance_y = ball.y_pos - ball2.y_pos;    distance_length_squared = (distance_x * distance_x) + (distance_y * distance_y);    distance_length = sqrt(distance_length_squared);        /* Quick Check */    if ((distance_length - radius_sum) > movement_length)        return false;        dotproduct = (normalised_movement_x * distance_x + normalised_movement_y * distance_y);    dotproduct *= -1;    dotproduct_squared = dotproduct * dotproduct;        /* Quick Check */    if (dotproduct <= 0)        return false;        fred = sqrt(distance_length_squared - dotproduct_squared);        /* Quick check */    if (fred >= radius_sum)        return false;           bob_squared = radius_sum_squared - (fred * fred);        if (bob_squared < 0)        return false;        bob = sqrt(bob_squared);        minimum_movement_length = dotproduct - bob;        if (minimum_movement_length > movement_length)        return false;    ball.x_pos += (normalised_movement_x * minimum_movement_length);    ball.y_pos += (normalised_movement_y * minimum_movement_length);    ball.x_vol = 0;    ball.y_vol = 0;    return true;}

##### Share on other sites
Say ball1 is heading toward ball2 from the left.

When you find distance, you take ball1.x - ball2.x, which will be negative. However, ball1 is moving in the positive x direction. So your dot product will be negative when ball1 is moving towards ball2, which is the opposite of what you want.

Probably the best way to fix it is just make distance ball2-ball1, rather than the other way around.

##### Share on other sites
Quote:
 Original post by bjleSay ball1 is heading toward ball2 from the left.When you find distance, you take ball1.x - ball2.x, which will be negative. However, ball1 is moving in the positive x direction. So your dot product will be negative when ball1 is moving towards ball2, which is the opposite of what you want.Probably the best way to fix it is just make distance ball2-ball1, rather than the other way around.

That fixed it, thanks.

1. 1
2. 2
Rutin
19
3. 3
4. 4
5. 5

• 9
• 9
• 9
• 14
• 12
• ### Forum Statistics

• Total Topics
633302
• Total Posts
3011272
• ### Who's Online (See full list)

There are no registered users currently online

×