我正在为大学作业创建一个项目,但遇到了一些障碍。这个问题很小,很可能会被忽视,但它仍然困扰着我,作为一个完成工作的程序性人,在解决之前我不能继续其他任何事情。
我的桨和球代码工作正常,以及基于球撞击桨的位置的简单角速度,但我的问题是球何时撞击砖块。该代码大部分都有效,并且看起来完美无瑕,但是当球执行以下两件事之一时,情况会发生变化:
- 击中砖块的一个角可能会错误地反转球速度的错误轴
- 同时击中两块砖(在它们的角落)会使球穿过它们并将它们移开;即使他们完全健康。
我使用的代码在这里(Ball.cs):
编辑(更新代码):
public bool Touching(Brick brick)
{
var position = Position + Velocity;
return position.Y + Size.Y >= brick.Position.Y &&
position.Y <= brick.Position.Y + brick.Size.Y &&
position.X + Size.X >= brick.Position.X &&
position.X <= brick.Position.X + brick.Size.X;
}
public bool Collide(Brick brick)
{
//Secondary precaution check
if (!Touching(brick)) return false;
//Find out where the ball will be
var position = Position + Velocity;
//Get the bounds of the ball based on where it will be
var bounds = new Rectangle((int)position.X, (int)position.Y, Texture.Width, Texture.Height);
//Stop the ball from moving here, so that changes to velocity will occur afterwards.
Position = Position - Velocity;
//If the ball hits the top or bottom of the brick
if (bounds.Intersects(brick.Top) || bounds.Intersects(brick.Bottom))
{
Velocity = new Vector2(Velocity.X, -Velocity.Y); //Reverse the Y axe of the Velocity
}
//If the ball hits the left or right of the brick
if (bounds.Intersects(brick.Left) || bounds.Intersects(brick.Right))
{
Velocity = new Vector2(-Velocity.X, Velocity.Y); //Reverse the X axe of the Velocity
}
return true;
}
这些方法是从 Level.cs 的 Update 方法中调用的:
public override void Update(GameTime gameTime)
{
player.Update(gameTime);
balls.ForEach(ball => ball.Update(gameTime));
foreach (var brick in bricks)
{
foreach (var ball in balls)
{
if (ball.Touching(brick))
{
if (!collidingBricks.Contains(brick)) collidingBricks.Add(brick);
}
}
brick.Update(gameTime);
}
if (collidingBricks.Count > 0)
{
foreach (var ball in balls)
{
Brick closestBrick = null;
foreach (var brick in collidingBricks)
{
if (closestBrick == null)
{
closestBrick = brick;
continue;
}
if (Vector2.Distance(ball.GetCenterpoint(brick), ball.GetCenterpoint()) < Vector2.Distance(ball.GetCenterpoint(closestBrick), ball.GetCenterpoint()))
{
closestBrick = brick;
}else
{
brick.Health--;
if (brick.Health > 0) brick.Texture = Assets.GetBrick(brick.TextureName, brick.Health);
}
}
if (ball.Collide(closestBrick))
{
closestBrick.Health--;
if (closestBrick.Health > 0) closestBrick.Texture = Assets.GetBrick(closestBrick.TextureName, closestBrick.Health);
}
}
collidingBricks = new List<Brick>();
}
bricks.RemoveAll(brick => brick.Health <= 0);
base.Update(gameTime);
}
球的碰撞方法决定了球的新速度值。如您所见,它完全取决于球的位置,而不是球的位置。此外,我对球正在碰撞的最近的砖块运行碰撞检查,但我降低了球接触的所有砖块的生命值(因此,速度只会根据最近的砖块更新,而不是所有碰撞的砖块)。
我理解为什么它会给我带来问题,这可能是因为球同时击中两侧(当它击中角落时)。
就像我说的,这是一个小问题,但仍然会影响游戏体验,尤其是当您期望球在逻辑上朝一个方向移动时,它只会朝相反的方向移动。