我的 Tank Trouble 中的碰撞检测问题,例如 C# 中的游戏
Collision detection problems in my Tank Trouble like game in C#
我正在用 c# 和 winforms 应用程序做 Tank Trouble(又名 AZ)之类的游戏。
我正在画一个图片框,墙壁存储在一个列表中,每面墙壁都有指定的厚度、起点和终点以及一个布尔值,它告诉墙壁是垂直的(真),还是水平的(布尔是错误的)
我的碰撞检测器遍历列表并检查它是否与其中之一发生碰撞,如果在一个方向(上、下、左、右)上检测到碰撞,则设置相应的布尔值
我的问题是,有时会有误报,也有误报,有些情况下,当它卡住而附近没有墙壁时,有时会穿过墙壁。
有人可以提出一些建议如何改进它吗?
有没有更好的方法来做到这一点?
这是我的代码
public void MoveTank()
{
// Calculate velocity from angle and base speed
Vx = (float)(moveSpeed * Math.Sin((angle * 0.0174532925)));
Vy = (float)(moveSpeed * Math.Cos((angle * 0.0174532925)));
CollisionDetector();
if (up == true)
{
Vy = 0;
}
if (down == true)
{
Vy = 0;
}
if (left == true)
{
Vx = 0;
}
if (right == true)
{
Vx = 0;
}
up = false;
down = false;
left = false;
right = false;
if (tUp) //if up key is pressed
{
tankCo.Y -= Vy;
tankCo.X += Vx;
}
if (tDown) //if down key is pressed
{
tankCo.Y += Vy;
tankCo.X -= Vx;
}
if (tLeft) //rotate left
{
angle -= angV;
if (angle < 0)
{
angle = 360 + angle;
}
angle = angle % 360;
img = RotateImage(OldImg, angle);
}
if (tRight) //rotate right
{
angle += angV;
angle = angle % 360;
if (angle < 0)
{
angle = 360 + angle;
}
img = RotateImage(OldImg, angle);
}
}
public void CollisionDetector()
{
foreach (Walls.Brick w in GameWindow.wall.allWalls)
{
if(w.vertical == true)
{
if (this.tankCo.X > w.wallStart.X && this.tankCo.X + this.Vx < w.wallStart.X)
{
this.left = true;
}
else if (this.tankCo.X < w.wallStart.X && this.tankCo.X + this.Vx > w.wallStart.X)
{
this.right = true;
}
}
else if(w.vertical == false)
{
if (this.tankCo.Y > w.wallStart.Y && this.tankCo.Y + this.Vy < w.wallStart.Y)
{
this.up = true;
}
else if (this.tankCo.Y < w.wallStart.Y && this.tankCo.Y + this.Vy > w.wallStart.Y)
{
this.down = true;
}
}
}
}
如果还不够,这里是我的整个存储库
经过一些工作,我想到了这里
感谢您的帮助
public void MoveTank()
{
if(tUp == tDown)
{
Vx = 0;
Vy = 0;
}
else if (tUp)
{
// Calculate velocity from angle and base speed
Vx = (float)(moveSpeed * Math.Sin((angle * 0.0174532925))); //that ugly number is PI/180
Vy = -(float)(moveSpeed * Math.Cos((angle * 0.0174532925)));
}
else if (tDown)
{
// Calculate velocity from angle and base speed
Vx = -(float)(moveSpeed * Math.Sin((angle * 0.0174532925)));
Vy = (float)(moveSpeed * Math.Cos((angle * 0.0174532925)));
}
//If it collides then one component of the velocity will be removed (Vx or Vy)
CollisionDetector();
tankCo.X += Vx;
tankCo.Y += Vy;
if (tLeft)
{
angle -= angV;
if (angle < 0)
{
angle = 360 + angle;
}
angle = angle % 360;
img = RotateImage(OldImg, angle);
}
if (tRight)
{
angle += angV;
angle = angle % 360;
if (angle < 0)
{
angle = 360 + angle;
}
img = RotateImage(OldImg, angle);
}
}
public void CollisionDetector()
{
foreach (Walls.Brick w in GameWindow.wall.allWalls)
{
if(w.vertical == false) // horizontal wall
{
//check if tank can collide with wall's side
if (tankCo.X >= w.wallStart.X && tankCo.X <= w.wallEnd.X)
{
//collision with tehe wall above
if (tankCo.Y > w.wallStart.Y && tankCo.Y + Vy < w.wallStart.Y)
{
Vy = 0;
}
//collision with the wall below
if (tankCo.Y + imgSize < w.wallStart.Y && tankCo.Y + imgSize + Vy > w.wallStart.Y)
{
Vy = 0;
}
}
//checks if tank can collide with the walls end
if (tankCo.Y < w.wallStart.Y && tankCo.Y + imgSize > w.wallStart.Y)
{
//collision with the right end
if (tankCo.X > w.wallEnd.X && tankCo.X + Vx < w.wallEnd.X)
{
Vx = 0;
}
//collision with the left end
if (tankCo.X + imgSize < w.wallStart.X && tankCo.X + imgSize + Vx > w.wallStart.X)
{
Vx = 0;
}
}
}
else if(w.vertical == true) //vertical
{
//check if tank can collide with wall's side
if (tankCo.Y >= w.wallStart.Y && tankCo.Y <= w.wallEnd.Y)
{
//collision with the wall from right
if (tankCo.X > w.wallStart.X && tankCo.X + Vx < w.wallStart.X)
{
Vx = 0;
}
//collision with the wall from left
if (tankCo.X + imgSize < w.wallStart.X && tankCo.X + imgSize + Vx > w.wallStart.X)
{
Vx = 0;
}
}
//checks if tank can collide with the walls end
if (tankCo.X < w.wallStart.X && tankCo.X + imgSize > w.wallStart.X)
{
//collision with the bottom end
if (tankCo.Y > w.wallEnd.Y && tankCo.Y + Vy < w.wallEnd.Y)
{
Vy = 0;
}
//collision with top end
if (tankCo.Y + imgSize < w.wallStart.Y && tankCo.Y + imgSize + Vy > w.wallStart.Y)
{
Vy = 0;
}
}
}
}
}
可能有点复杂,但对我有用
我正在用 c# 和 winforms 应用程序做 Tank Trouble(又名 AZ)之类的游戏。 我正在画一个图片框,墙壁存储在一个列表中,每面墙壁都有指定的厚度、起点和终点以及一个布尔值,它告诉墙壁是垂直的(真),还是水平的(布尔是错误的) 我的碰撞检测器遍历列表并检查它是否与其中之一发生碰撞,如果在一个方向(上、下、左、右)上检测到碰撞,则设置相应的布尔值 我的问题是,有时会有误报,也有误报,有些情况下,当它卡住而附近没有墙壁时,有时会穿过墙壁。 有人可以提出一些建议如何改进它吗? 有没有更好的方法来做到这一点? 这是我的代码
public void MoveTank()
{
// Calculate velocity from angle and base speed
Vx = (float)(moveSpeed * Math.Sin((angle * 0.0174532925)));
Vy = (float)(moveSpeed * Math.Cos((angle * 0.0174532925)));
CollisionDetector();
if (up == true)
{
Vy = 0;
}
if (down == true)
{
Vy = 0;
}
if (left == true)
{
Vx = 0;
}
if (right == true)
{
Vx = 0;
}
up = false;
down = false;
left = false;
right = false;
if (tUp) //if up key is pressed
{
tankCo.Y -= Vy;
tankCo.X += Vx;
}
if (tDown) //if down key is pressed
{
tankCo.Y += Vy;
tankCo.X -= Vx;
}
if (tLeft) //rotate left
{
angle -= angV;
if (angle < 0)
{
angle = 360 + angle;
}
angle = angle % 360;
img = RotateImage(OldImg, angle);
}
if (tRight) //rotate right
{
angle += angV;
angle = angle % 360;
if (angle < 0)
{
angle = 360 + angle;
}
img = RotateImage(OldImg, angle);
}
}
public void CollisionDetector()
{
foreach (Walls.Brick w in GameWindow.wall.allWalls)
{
if(w.vertical == true)
{
if (this.tankCo.X > w.wallStart.X && this.tankCo.X + this.Vx < w.wallStart.X)
{
this.left = true;
}
else if (this.tankCo.X < w.wallStart.X && this.tankCo.X + this.Vx > w.wallStart.X)
{
this.right = true;
}
}
else if(w.vertical == false)
{
if (this.tankCo.Y > w.wallStart.Y && this.tankCo.Y + this.Vy < w.wallStart.Y)
{
this.up = true;
}
else if (this.tankCo.Y < w.wallStart.Y && this.tankCo.Y + this.Vy > w.wallStart.Y)
{
this.down = true;
}
}
}
}
如果还不够,这里是我的整个存储库
经过一些工作,我想到了这里 感谢您的帮助
public void MoveTank()
{
if(tUp == tDown)
{
Vx = 0;
Vy = 0;
}
else if (tUp)
{
// Calculate velocity from angle and base speed
Vx = (float)(moveSpeed * Math.Sin((angle * 0.0174532925))); //that ugly number is PI/180
Vy = -(float)(moveSpeed * Math.Cos((angle * 0.0174532925)));
}
else if (tDown)
{
// Calculate velocity from angle and base speed
Vx = -(float)(moveSpeed * Math.Sin((angle * 0.0174532925)));
Vy = (float)(moveSpeed * Math.Cos((angle * 0.0174532925)));
}
//If it collides then one component of the velocity will be removed (Vx or Vy)
CollisionDetector();
tankCo.X += Vx;
tankCo.Y += Vy;
if (tLeft)
{
angle -= angV;
if (angle < 0)
{
angle = 360 + angle;
}
angle = angle % 360;
img = RotateImage(OldImg, angle);
}
if (tRight)
{
angle += angV;
angle = angle % 360;
if (angle < 0)
{
angle = 360 + angle;
}
img = RotateImage(OldImg, angle);
}
}
public void CollisionDetector()
{
foreach (Walls.Brick w in GameWindow.wall.allWalls)
{
if(w.vertical == false) // horizontal wall
{
//check if tank can collide with wall's side
if (tankCo.X >= w.wallStart.X && tankCo.X <= w.wallEnd.X)
{
//collision with tehe wall above
if (tankCo.Y > w.wallStart.Y && tankCo.Y + Vy < w.wallStart.Y)
{
Vy = 0;
}
//collision with the wall below
if (tankCo.Y + imgSize < w.wallStart.Y && tankCo.Y + imgSize + Vy > w.wallStart.Y)
{
Vy = 0;
}
}
//checks if tank can collide with the walls end
if (tankCo.Y < w.wallStart.Y && tankCo.Y + imgSize > w.wallStart.Y)
{
//collision with the right end
if (tankCo.X > w.wallEnd.X && tankCo.X + Vx < w.wallEnd.X)
{
Vx = 0;
}
//collision with the left end
if (tankCo.X + imgSize < w.wallStart.X && tankCo.X + imgSize + Vx > w.wallStart.X)
{
Vx = 0;
}
}
}
else if(w.vertical == true) //vertical
{
//check if tank can collide with wall's side
if (tankCo.Y >= w.wallStart.Y && tankCo.Y <= w.wallEnd.Y)
{
//collision with the wall from right
if (tankCo.X > w.wallStart.X && tankCo.X + Vx < w.wallStart.X)
{
Vx = 0;
}
//collision with the wall from left
if (tankCo.X + imgSize < w.wallStart.X && tankCo.X + imgSize + Vx > w.wallStart.X)
{
Vx = 0;
}
}
//checks if tank can collide with the walls end
if (tankCo.X < w.wallStart.X && tankCo.X + imgSize > w.wallStart.X)
{
//collision with the bottom end
if (tankCo.Y > w.wallEnd.Y && tankCo.Y + Vy < w.wallEnd.Y)
{
Vy = 0;
}
//collision with top end
if (tankCo.Y + imgSize < w.wallStart.Y && tankCo.Y + imgSize + Vy > w.wallStart.Y)
{
Vy = 0;
}
}
}
}
}
可能有点复杂,但对我有用