我的程序中关于碰撞的一个小错误
A little bug about collision in my program
我花了一个小时试图解决我的问题。
我要把事情的经过画下来
char trap = 'Q';
char character = 'L';
....
.Q..
..L.
....
当L向上移动和Q向右移动时发生碰撞,程序结束。但是:
....
.QL.
....
....
当L向左移动,Q向右移动时,它们不会像上面的例子那样发生碰撞,而是发生了什么:
....
..Q.
....
....
这是我的代码。抱歉我的英语不好:(
测试移动是 'w' , 'a' , 's' 还是 'd' :
void cave::move(int& x, int& y, char m, char unit)
{
if ( m == 'W' || m == 'w' ) // if moves up
{
floor[x][y] = tile;
x -= 1;
for ( unsigned short int x = 0; x < 3; x++ )
{
if ( floor[x][y] == wall && floor[x][y] == trap[x] )
{
x += 1;
trapsMove();
}
}
floor[x][y] = unit;
}
else if ( m == 'A' || m == 'a' ) // if moves to left
{
floor[x][y] = tile;
y -= 1;
for ( unsigned short int x = 0; x < 3; x++ )
{
if ( floor[x][y] == wall && floor[x][y] == trap [x] )
{
y += 1;
trapsMove();
}
}
floor[x][y] = unit;
}
else if ( m == 'S' || m == 's' ) // if moves down
{
floor[x][y] = tile;
x += 1;
for ( unsigned short int x = 0; x < 3; x++ )
{
if ( floor[x][y] == wall && floor[x][y] == trap[x] )
{
x -= 1;
trapsMove();
}
}
floor[x][y] = unit;
}
else if ( m == 'D' || m == 'd' ) // if moves to right
{
floor[x][y] = tile;
y += 1;
for ( unsigned short int x = 0; x < 3; x++ )
{
if ( floor[x][y] == wall && floor[x][y] == trapx] )
{
y -= 1;
trapsMove();
}
}
floor[x][y] = unit;
}
else
control();
return;
}
ai运行函数
void cave::trapsMove()
{
int r[3]; // each index will hold the movement of traps
for ( unsigned short int x = 0; x < 3; x++ )
{
r[x] = rand() % 4 + 1;
if ( r[x] == 1 ) // moves up
move(traps_positionX[x],traps_positionY[x],'w',trap[x]);
else if ( r[x] == 2 ) // moves to left
move(traps_positionX[x],traps_positionY[x],'a',trap[x]);
else if ( r[x] == 3 ) // moves down
move(traps_positionX[x],traps_positionY[x],'s',trap[x]);
else if ( r[x] == 4 ) // moves to right
move(traps_positionX[x],traps_positionY[x],'d',trap[x]);
}
return;
}
检查是否碰撞
bool cave::collision()
{
for ( unsigned short int x = 0; x < 3; x++ )
{
if ( floor[character_positionX][character_positionY] == trap[x] )
return true;
}
return false;
}
好吧,从您的代码看来,Trap 和 Player 调换了位置。
但是,陷阱 (Q) 的位置切换会用地砖覆盖玩家 (L)。
基本上是这样的:
(1).QL.
(2) .L.. // L 和 Q 居住在同一个瓷砖
(3) ..问。 // Q 用 '.' 覆盖 L瓷砖
您的代码存在卷积问题,因为您试图在一个函数中做太多事情,或者在几个不同的地方做。这会导致您缺少例如上例中必要的碰撞检查。
更好的策略是尝试构建您的程序流程。例如你目前有:
(1) 提示方向
(2) 移动玩家板块
(2a) 如果玩家击中的方块是陷阱或墙(代码中的拼写错误,必须是 || 而不是 &&)移动陷阱
<-- (2a) 是另一个陷阱,陷阱可以连续做两步。
(3) 移动陷阱
(4) 检查碰撞
(5) 从 (1) 开始重复
我想你想要的是:
(1) 提示方向
(2) 移动玩家板块
(2a) 检查碰撞
(3) 移动陷阱
(3a) 检查碰撞
(6) 从 (1) 开始重复
至于重构尝试回收你的代码。例如,在您的 move() 函数中, char 'w' (...) 仅影响 'x' 或 'y' 变量。因此你也可以把它写成
move(...) {
if((m=='w')||(m=='W')) { y = y+1 }
else if((m=='a')||(m=='A')) { x = x-1 } // same for SD
if(floor[x][y] != wall) {
// set new position to object, if it can't move, just don't set it
}
}
这样您就不必复制和粘贴您的 for 循环,只需进行最少的改动。
我花了一个小时试图解决我的问题。
我要把事情的经过画下来
char trap = 'Q';
char character = 'L';
....
.Q..
..L.
....
当L向上移动和Q向右移动时发生碰撞,程序结束。但是:
....
.QL.
....
....
当L向左移动,Q向右移动时,它们不会像上面的例子那样发生碰撞,而是发生了什么:
....
..Q.
....
....
这是我的代码。抱歉我的英语不好:(
测试移动是 'w' , 'a' , 's' 还是 'd' :
void cave::move(int& x, int& y, char m, char unit)
{
if ( m == 'W' || m == 'w' ) // if moves up
{
floor[x][y] = tile;
x -= 1;
for ( unsigned short int x = 0; x < 3; x++ )
{
if ( floor[x][y] == wall && floor[x][y] == trap[x] )
{
x += 1;
trapsMove();
}
}
floor[x][y] = unit;
}
else if ( m == 'A' || m == 'a' ) // if moves to left
{
floor[x][y] = tile;
y -= 1;
for ( unsigned short int x = 0; x < 3; x++ )
{
if ( floor[x][y] == wall && floor[x][y] == trap [x] )
{
y += 1;
trapsMove();
}
}
floor[x][y] = unit;
}
else if ( m == 'S' || m == 's' ) // if moves down
{
floor[x][y] = tile;
x += 1;
for ( unsigned short int x = 0; x < 3; x++ )
{
if ( floor[x][y] == wall && floor[x][y] == trap[x] )
{
x -= 1;
trapsMove();
}
}
floor[x][y] = unit;
}
else if ( m == 'D' || m == 'd' ) // if moves to right
{
floor[x][y] = tile;
y += 1;
for ( unsigned short int x = 0; x < 3; x++ )
{
if ( floor[x][y] == wall && floor[x][y] == trapx] )
{
y -= 1;
trapsMove();
}
}
floor[x][y] = unit;
}
else
control();
return;
}
ai运行函数
void cave::trapsMove()
{
int r[3]; // each index will hold the movement of traps
for ( unsigned short int x = 0; x < 3; x++ )
{
r[x] = rand() % 4 + 1;
if ( r[x] == 1 ) // moves up
move(traps_positionX[x],traps_positionY[x],'w',trap[x]);
else if ( r[x] == 2 ) // moves to left
move(traps_positionX[x],traps_positionY[x],'a',trap[x]);
else if ( r[x] == 3 ) // moves down
move(traps_positionX[x],traps_positionY[x],'s',trap[x]);
else if ( r[x] == 4 ) // moves to right
move(traps_positionX[x],traps_positionY[x],'d',trap[x]);
}
return;
}
检查是否碰撞
bool cave::collision()
{
for ( unsigned short int x = 0; x < 3; x++ )
{
if ( floor[character_positionX][character_positionY] == trap[x] )
return true;
}
return false;
}
好吧,从您的代码看来,Trap 和 Player 调换了位置。 但是,陷阱 (Q) 的位置切换会用地砖覆盖玩家 (L)。
基本上是这样的:
(1).QL.
(2) .L.. // L 和 Q 居住在同一个瓷砖
(3) ..问。 // Q 用 '.' 覆盖 L瓷砖
您的代码存在卷积问题,因为您试图在一个函数中做太多事情,或者在几个不同的地方做。这会导致您缺少例如上例中必要的碰撞检查。
更好的策略是尝试构建您的程序流程。例如你目前有:
(1) 提示方向
(2) 移动玩家板块
(2a) 如果玩家击中的方块是陷阱或墙(代码中的拼写错误,必须是 || 而不是 &&)移动陷阱
<-- (2a) 是另一个陷阱,陷阱可以连续做两步。
(3) 移动陷阱
(4) 检查碰撞
(5) 从 (1) 开始重复
我想你想要的是:
(1) 提示方向
(2) 移动玩家板块
(2a) 检查碰撞
(3) 移动陷阱
(3a) 检查碰撞
(6) 从 (1) 开始重复
至于重构尝试回收你的代码。例如,在您的 move() 函数中, char 'w' (...) 仅影响 'x' 或 'y' 变量。因此你也可以把它写成
move(...) {
if((m=='w')||(m=='W')) { y = y+1 }
else if((m=='a')||(m=='A')) { x = x-1 } // same for SD
if(floor[x][y] != wall) {
// set new position to object, if it can't move, just don't set it
}
}
这样您就不必复制和粘贴您的 for 循环,只需进行最少的改动。