Ramy670
Ramy670

Reputation: 81

Conditional return value bug fixed with a useless printf call

I was trying to write a simple function for collision detection for my simple game (school project) and couldn't get a proper return value out of it until I added a meaningless printf line (initially it was intended to assist in debugging ) and it all worked somehow. I wonder what could that bug be? and how I can fix it with a more "proper" way. Thanks.

Here is my function (Variable "rect" (rectangle)is a standard SDL struct that has 4 integer members representing it's height, width and it's corner's x and y):

bool collision(SDL_Rect *rect1, SDL_Rect *rect2) {
    //chekcs to see if rect2 is totally outside of boundaries of rect1
    static bool collided;
    if (rect1->y > rect2->y + rect2->h) {
        printf("");
        collided = false;
        return collided;
    }
    if (rect1->y + rect1->h < rect2->y) {
        printf("");
        collided = false;
        return collided;
    }
    if (rect1->x > rect2->x + rect2->w) {
        printf("");
        collided = false;
        return collided;
    }   
    if (rect1->x + rect1->w < rect2->x) {
        printf("");
        collided = false;
        return collided;
    }
    //returns 1 if none of above is true

    collided = 1;
    return collided;
}

Edit: I used static bool because I was trying to get Visual studio to display the boolean variable's value in watch window even when it (the variable) was outside of scope, it didn't work and I forgot to remove static. The problem is there whether I use static or not however.

Edit 2: Here is the function that is calling the function above (I know digonalMovement needs a small fix to make the speed slower on both directions when moving diagonally (currently only 1 of them becomes slower), but this shouldn't have anything to do with the problem in hand):

void player_movement_calc(int player_nr, SDL_Rect char_rects[], Char character[]) {
    // determine velocity
    character[player_nr].x_vel = character[player_nr].y_vel = 0;
    bool collided = collision(&char_rects[0], &char_rects[2]);

    bool digonalMovement = 0;
    if (character[player_nr].up && !character[player_nr].down) {    
        if (digonalMovement)
            character[player_nr].y_vel = -SPEED * 0.86; //multiplying by sin(45)
        else {
            character[player_nr].y_vel = -SPEED;
        }
        digonalMovement = 1;
        if (collided)
            character[player_nr].y_vel -= 2 * character[player_nr].y_vel;
    }
    if (character[player_nr].down && !character[player_nr].up) {
        if (digonalMovement)
            character[player_nr].y_vel = SPEED * 0.86;
        else {
            character[player_nr].y_vel = SPEED;
        }
        digonalMovement = 1;
        if (collided)
            character[player_nr].y_vel -= 2 * character[player_nr].y_vel;
    }
    if (character[player_nr].left && !character[player_nr].right) {
        if (digonalMovement)
            character[player_nr].x_vel = -SPEED * 0.86;
        else {
            character[player_nr].x_vel = -SPEED;
        }
        digonalMovement = 1;
        if (collided)
            character[player_nr].y_vel -= 2 * character[player_nr].y_vel;
    }
    if (character[player_nr].right && !character[player_nr].left) {
        if (digonalMovement)
            character[player_nr].x_vel = SPEED * 0.86;
        else {
            character[player_nr].x_vel = SPEED;
        }
        digonalMovement = 1;
        if (collided)
            character[player_nr].y_vel -= 2 * character[player_nr].y_vel;
    }
    //clears diagonalMovement to make it false for next fram
    digonalMovement = 0;

    // update positions
    character[player_nr].x_pos += character[player_nr].x_vel / 60;
    character[player_nr].y_pos += character[player_nr].y_vel / 60;

    // collision detection with bounds
    if (character[player_nr].x_pos <= 0)
        character[player_nr].x_pos = 0;
    if (character[player_nr].y_pos <= 0)
        character[player_nr].y_pos = 0;
    if (character[player_nr].x_pos >= WINDOW_WIDTH - char_rects[player_nr].w)
        character[player_nr].x_pos = WINDOW_WIDTH - char_rects[player_nr].w;
    if (character[player_nr].y_pos >= WINDOW_HEIGHT - char_rects[player_nr].h)
        character[player_nr].y_pos = WINDOW_HEIGHT - char_rects[player_nr].h;

    // set the positions in the struct 
    char_rects[player_nr].y = (int)character[player_nr].y_pos;
    char_rects[player_nr].x = (int)character[player_nr].x_pos;
}

Upvotes: 1

Views: 148

Answers (1)

chqrlie
chqrlie

Reputation: 144770

In the player_movement_calc() function, you have collision(&char_rects[0], &char_rects[2]). It seems you should be comparing the rectangles of the players with

    bool collided = collision(&char_rects[0], &char_rects[1]);

You may be reading beyond the end of the char_rects array, causing undefined behavior. Any side effects caused by printf, such as allocating memory for its own purpose or the the stdout buffer might change the behavior of the program, for example by making the memory accessed beyond the end of the array readable, hence removing the crash and hiding the bug.

Another potential explanation is the call to collision might be omitted by the compiler if its result is unused and if the function collision has no side effects. Without the static and the printf, the function has no side effect (apart from the crash caused by reading beyond the end of the array which is undefined behavior anyway). Changing the static value may be considered useless by the compiler since this variable is not used anywhere and not defined volatile. printf has side effects, so calling it makes collision unpure, hence the call cannot be elided.

It is always difficult to try and make sense of undefined behavior. When debugging, you should first disable all optimizations. The bug is probably visible without the printf with optimizations disabled and tracing the code and watching local variables should be much easier with unoptimised code.

Once you have a reproducible crash bug in a debug build, just use the debugger to show you where it happens. Crash bugs should be easy to investigate.

Upvotes: 1

Related Questions