I am doing a Tank Trouble (aka. AZ) like game in c#, winforms application. I am drawing to a picturebox, the walls are stored in a list, each wall has a specified thickness, a starting and ending point and a boolean which tells if the wall is vertical (true), or if it is horizontal (the bool is false) My collision detector goes trough the list and checks if it collides with one of them, then sets the respective booleans if collision was detected in a direction (up, down, left, right) My problem is, that sometimes there are false positives, and false negatives too, there are cases, when it stucks while no walls are near, sometimes goes through the walls. Could somebody give some suggestions how to improve it? Is there a more optimal way to do it? Here is my code
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;
}
}
}
}
if it isn't enough here is my entire repository
https://github.com/SorbanElod/CSharp/tree/main/SPANzer
CodePudding user response:
After some work here is what i came up with Thank you for your help
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;
}
}
}
}
}
It may be a bit complicated but it works for me