我正在用C#编写我自己的Pong游戏,我的球有些问题没有正确重置。我花了一两个小时调试代码,但我无法弄明白。
基本上应该发生的是,当检测到球离开窗口边界时,Center()
方法将被调用,Center()
然后重置球Point
通过直接访问支持字段。现在这个工作,我已经验证它通过单步执行代码来完成它应该做的事情。
现在奇怪的是,在Center()
被召唤之后,球的位置会恢复到以前的中心位置。现在奇怪的是,这个重置发生在甚至调用set
属性的Point
访问器之前。而且我100%确定我没有直接在Center()
之外的任何其他地方访问支持字段,所以我无法弄清楚..这是代码
namespace Pong
{
internal enum CollisionType
{
Paddle, Boundary
}
class Ball
{
private readonly IGameView view;
private readonly IGameController controller;
private int velocity = 10;
private double angle;
private event CollisionHandler Collision;
private Point _point;
public Point Point
{
get { return _point; }
set
{ // If UpdatePosition() tries to move the ball beyond the boundaries in one tick move the ball to the boundaries
if(value.Y > view.Boundaries.Height || value.Y < 0)
{
_point = new Point(value.X, view.Boundaries.Height);
Collision(CollisionType.Boundary); // Also raise the collision event
}
//If the ball is going to pass the X boundaries of the map then a player should score and the ball should reset
if (value.X > view.Boundaries.Width || value.X < 0)
{
if (angle > 90) // If the angle of the ball of the ball is above 90 degrees then the left paddle was the shooter
{ // So he should score
var scoringPlayer = Array.Find(controller.Players, player => player.Paddle.Orientation.Equals(Orientation.Left));
controller.PlayerScore(scoringPlayer);
Center(scoringPlayer);
}
else // If not, then it's the right paddle
{
var scoringPlayer = Array.Find(controller.Players, player => player.Paddle.Orientation.Equals(Orientation.Right));
controller.PlayerScore(scoringPlayer);
Center(scoringPlayer);
}
}
// If the ball will collide with a player paddle then raise collision event
if (controller.Players.Any(player => player.Paddle.Position.Equals(value)))
{
Collision(CollisionType.Paddle);
_point = value;
}
_point = value;
}
}
public Ball(IGameView view, IGameController controller)
{
this.view = view;
this.controller = controller;
}
public void Center(Player server)
{
//Center the ball, acccess the backing field directly to avoid all the conditional logic in the property
_point = new Point(view.Boundaries.Width / 2, view.Boundaries.Height / 2);
//The ball will start moving from the center Point towards one of the different sides
/*TODO: Apparently the ball moves sideways down towards one of the player paddles, so we must implement more complex
logic to calculate the starting angle of the ball */
angle = (server.Paddle.Orientation.Equals(Orientation.Left)) ? 0 : 180;
}
public void UpdatePosition()
{
//Called to update ball position based on velocity and angle of ball
//For now let's just implement a very primitive movement algorithm
if (angle < 90)
{
Point = new Point(Point.X + velocity, Point.Y);
}
else
{
Point = new Point(Point.X - velocity, Point.Y);
}
}
}
//TODO: Add collision detection through BallCollision Event and implement BallCollisionHandler(CollisionType as Object args)
答案 0 :(得分:1)
您在致电_point = value
后立即设置Center
- 您需要确保在Center
public Point Point
{
get { return _point; }
set
{ // If UpdatePosition() tries to move the ball beyond the boundaries in one tick move the ball to the boundaries
if(value.Y > view.Boundaries.Height || value.Y < 0)
{
_point = new Point(value.X, view.Boundaries.Height);
Collision(CollisionType.Boundary); // Also raise the collision event
}
//If the ball is going to pass the X boundaries of the map then a player should score and the ball should reset
if (value.X > view.Boundaries.Width || value.X < 0)
{
if (angle > 90) // If the angle of the ball of the ball is above 90 degrees then the left paddle was the shooter
{ // So he should score
var scoringPlayer = Array.Find(controller.Players, player => player.Paddle.Orientation.Equals(Orientation.Left));
controller.PlayerScore(scoringPlayer);
Center(scoringPlayer);
}
else // If not, then it's the right paddle
{
var scoringPlayer = Array.Find(controller.Players, player => player.Paddle.Orientation.Equals(Orientation.Right));
controller.PlayerScore(scoringPlayer);
Center(scoringPlayer);
}
}
// If the ball will collide with a player paddle then raise collision event
if (controller.Players.Any(player => player.Paddle.Position.Equals(value)))
{
Collision(CollisionType.Paddle);
_point = value;
}
_point = value; // <--- This always gets set - even after you call Center above
}
}
编辑:
Sayse指出,虽然这是你遇到的问题,但将这个逻辑转移到“更新”中会很有用。代码的一部分 - 这个逻辑似乎应该是IGameController
实现的一部分或者IBallController
的一部分;或者将Update
方法放入游戏控制器想要更新所有游戏对象时调用的Ball
类中
物业设定者理想情况下不应该是副作用