我正在尝试为我的简单游戏(学校项目)编写一个用于碰撞检测的简单函数,直到我添加了无意义的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;
}
编辑: 我之所以使用静态布尔值,是因为我试图让Visual Studio在监视窗口中显示布尔变量的值,即使该变量(变量)不在作用域之内,它也不起作用,并且我忘记了删除静态变量。问题是我是否使用静态。
编辑2: 这是调用上面函数的函数(我知道digonalMovement需要一个小小的固定来使对角移动时两个方向的速度变慢(目前只有一个变慢),但这与问题在手):
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;
}
答案 0 :(得分:1)
在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
没有副作用,则编译器可能会省略对static
的调用。如果没有printf
和static
,该函数将没有副作用(除了由于读取超出数组末尾(无论如何都是未定义的行为)而导致的崩溃)之外。更改volatile
的值可能被编译器认为是无用的,因为此变量未在任何地方使用且未定义printf
。 collision
有副作用,因此调用它会使printf
不纯,因此无法忽略该调用。
总是很难尝试去理解未定义的行为。调试时,首先应禁用所有优化。如果不使用BufferedImage
并禁用优化,则该错误可能是可见的,而对于未经优化的代码,跟踪代码和查看局部变量应该会容易得多。
一旦在调试版本中出现可重现的崩溃错误,只需使用调试器向您显示错误发生的位置。崩溃错误应易于调查。