我试着为我的简单游戏(学校项目)编写一个简单的碰撞检测函数,直到我添加了一个无意义的printf行(最初是为了帮助调试)之后,才得到一个正确的返回值。我想知道那虫子是什么以及如何用更“恰当”的方法来解决问题。谢谢。
下面是我的函数(变量“rect”(矩形)是一个标准的SDL结构,它有4个整数成员,表示它的高度、宽度和拐角的x和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;
}

编辑:
我使用静态bool是因为我试图让Visual studio在监视窗口中显示布尔变量的值,即使它(变量)不在作用域内,它也不起作用,我忘记删除static。但问题是我是否使用static。
编辑2:
下面是调用上述函数的函数(我知道在对角线方向移动时,需要一个小的修正,以使速度在两个方向上都变慢(目前只有一个方向变慢),但这与手头的问题没有任何关系):
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;
}

最佳答案

player_movement_calc()函数中,您有collision(&char_rects[0], &char_rects[2])。看来你应该把运动员的长方形和

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

您可能正在读取超过char_rects数组末尾的内容,从而导致未定义的行为。由printf引起的任何副作用,例如为自己的目的分配内存或stdout缓冲区,都可能改变程序的行为,例如使超出数组末尾访问的内存可读,从而消除崩溃并隐藏错误。
另一个可能的解释是,如果编译器没有使用它的结果,并且函数collision没有副作用,那么编译器可能会省略对collision的调用。在没有staticprintf的情况下,函数没有副作用(除了读取数组末尾以外的未定义行为导致的崩溃)。更改static值可能被编译器认为是无用的,因为此变量不在任何地方使用,也未定义volatileprintf有副作用,因此调用它会使collision不完整,因此无法忽略该调用。
总是很难尝试去理解不明确的行为。调试时,应首先禁用所有优化。如果没有禁用优化的printf,这个bug可能是可见的,如果没有优化的代码,跟踪代码和监视局部变量应该会容易得多。
一旦在调试生成中出现可复制的崩溃错误,只需使用调试器向您显示错误发生的位置。崩溃错误应该很容易调查。

关于c - 通过无用的printf调用修复了条件返回值错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55619222/

10-12 18:04
查看更多