2014-04-15 2 views
0

전 C#으로 내 탁구 게임을 쓰고 있어요. 내 공이 문제없이 올바르게 재설정되지 않습니다. 나는 좋은 시간이나 코드를 디버깅하는 데 썼다. 그러나 나는 그것을 이해할 수 없다. 일하기로했다 기본적으로 무엇을'탁구'공이 재설정되지 않습니다.

는 볼이 윈도우의 경계를 떠나 감지되면 다음 Center() 방법은 전화를받을 것입니다 및 Center() 후 직접 백업 필드에 액세스하여 볼 Point을 재설정한다는 것입니다. 이제이 방법이 작동합니다. 코드를 단계별로 실행하여 작동하는지 확인했습니다.

이상한 일이 발생하면 Center()이 호출되면 공의 위치가 이전의 중심으로 되돌아갑니다. 이상한 일은 Point 속성의 set 접근자가 호출되기도 전에이 재설정이 수행된다는 것입니다. 그리고 여기에 코드

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

당신은 전화 후 즉시 _point = value을 설정이야 .. 내가 그래서 그것을 알아낼 수 없습니다 Center() 이외의 장소에 직접 백업 필드를 accesing 아니에요 100 % 확신 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 일 수 있습니다. 그 중 하나 또는이 모든 게임이 안 이상적

속성 세터 개체를 업데이트하고자하는 게임 컨트롤러에 의해 호출하여 Ball 클래스 내로 Update 방법을 넣어 정확하지만

+0

답변을 측면 초래, 여전히 속성 setter 오용으로 나쁜 코드 장려하기. – Sayse

+0

나는 setter가 결정 론적이어야 함을 동의한다. 아마도 나는 setter보다는 "update"루프에 넣을 것이지만, 나는 단지 질문에 답했다. – Charleh

+0

그래, 그거야! 또한 속성에 관해서는 알지 못했지만 유효성 검사와 물건에만 사용해야한다고 생각합니다. 나는 BallController 클래스를 구현하여 코드를 수정했다. –

관련 문제