'傍'球没有重置

时间:2014-04-15 08:02:22

标签: c# multithreading debugging

我正在用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) 

1 个答案:

答案 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类中

物业设定者理想情况下不应该是副作用