2011-05-13 85 views
7

我正在用XNA開發C#遊戲,並且我一直在用C#學習程序,這要感謝Nick Gravelyn的教程,但是我遇到了一些困難。當我使用Nick的碰撞系統時,我沒有使用他的播放器代碼。我正在使用一個基於Fatso784的教程,我修改了它。所以,因此,我無法正確地修改我的碰撞系統版本。我已經達到了將玩家推出某些牌的程度,但我需要它變得更加堅實,因爲玩家偶爾也能穿過牆壁。我很確定我正在處理碰撞錯誤,但可能是碰撞有點糊塗。因此,這裏是從我的播放器類的相關代碼,此舉代碼:我怎樣才能讓我的碰撞更堅實?

public void Move() 
    { 
     pos.X = bounds.X; 
     pos.Y = bounds.Y; 

     offsetPos.X = bounds.Width; 
     offsetPos.Y = bounds.Height; 

     if (frameCount % delay == 0) 
     { 
      switch (direction) 
      { 
       case "stand": 
        if (sideCollide == "none") 
        { 
         Equalize(2); 
        } 
        else if (sideCollide == "left") 
        { 
         speed += 1f; 
        } 
        else if (sideCollide == "right") 
        { 
         speed -= 1f; 
        } 
        bounds.X += (int)speed; 
        if (frameCount/delay >= 8) 
         frameCount = 0; 
        srcBounds = new Rectangle(frameCount/delay * 64, 0, 64, 64); 
        break; 
       case "left": 
        if (sideCollide != "left") 
        { 
         if (speed > -maxspeed) 
         { 
          speed -= acceleration; 
         } 
         else if (speed < -maxspeed) 
         { 
          speed -= acceleration; 
          speed += drag; 
          Equalize(2); 
         } 
         speed += friction; 
        } 
        bounds.X += (int)speed; 
        if (frameCount/delay >= 4) 
         frameCount = 0; 
        srcBounds = new Rectangle(frameCount/delay * 64, 64, 64, 64); 
        break; 
       case "right": 
        if (sideCollide != "right") 
        { 
         if (speed < maxspeed) 
         { 
          speed += acceleration; 
         } 
         else if (speed > maxspeed) 
         { 
          speed += acceleration; 
          speed -= drag; 
          Equalize(2); 
         } 
         speed -= friction; 
        } 
        bounds.X += (int)speed; 
        if (frameCount/delay >= 4) 
         frameCount = 0; 
        srcBounds = new Rectangle(frameCount/delay * 64, 64, 64, 64); 
        break; 
       case "up": 
        if (speed > -4 && speed < 4) 
         srcBounds.Y = 128; 
        else 
         srcBounds.Y = 64; 
        if (srcBounds.Y == 0 || srcBounds.Y == 128) 
        { 
         if (jumpCount < 2) 
         { 
          if (frameCount/delay >= 9) 
           frameCount = 0; 
         } 
         else if (jumpCount > 2 && jumpCount <= 10) 
         { 
          if (frameCount/delay > 3) 
           frameCount = 2 * delay; 
         } 
         else if (jumpCount > 10 && jumpCount <= 18) 
         { 
          if (frameCount/delay > 5) 
           frameCount = 4 * delay; 
         } 
         else if (jumpCount > 18) 
         { 
          if (frameCount/delay >= 9) 
           frameCount = 0; 
         } 

         srcBounds = new Rectangle(frameCount/delay * 64, 128, 64, 64); 
        } 
        else if (srcBounds.Y == 64) 
        { 
         if (frameCount/delay >= 4) 
          frameCount = 0; 
         if (jumpCount <= 10) 
          srcBounds = new Rectangle((frameCount/delay)/2 * 64, 64, 64, 64); 
         else 
          srcBounds = new Rectangle(frameCount/delay * 64, 64, 64, 64); 
        } 
        if (jumpCount == 0) 
         startY = bounds.Y; 
        bounds = new Rectangle(bounds.X + (int)speed, 
         (jumpCount - 10) * (jumpCount - 10) - 100 + startY, 64, 64); 
        jumpCount++; 
        if (bounds.Y > startY) 
        { 
         bounds.Y = startY; 
         direction = "stand"; 
         jumpCount = 0; 
        } 
        break; 
      } 
     } 

     frameCount++; 
    } 

和碰撞代碼:

public void CollideOutside(TileMap tilemap) 
    { 
     Point cell = Engine.PointCell(PlayerCenter); 

     Point? upLeft = null, Up = null, upRight = null, Right = null, downRight = null, Down = null, downLeft = null, Left = null; 

     if (cell.Y > 0) 
     { 
      Up = new Point(cell.X, cell.Y - 1); 
     } 
     if (cell.Y < tilemap.collisionMap.HeightinPixels) 
     { 
      Down = new Point(cell.X, cell.Y + 1); 
     } 
     if (cell.X > 0) 
     { 
      Left = new Point(cell.X - 1, cell.Y); 
     } 
     if (cell.X < tilemap.collisionMap.WidthinPixels) 
     { 
      Right = new Point(cell.X + 1, cell.Y); 
     } 

     if (cell.X > 0 && cell.Y > 0) 
     { 
      upLeft = new Point(cell.X - 1, cell.Y - 1); 
     } 
     if (cell.X < tilemap.collisionMap.WidthinPixels - 1 && cell.Y > 0) 
     { 
      upRight = new Point(cell.X + 1, cell.Y - 1); 
     } 
     if (cell.X > 0 && cell.Y < tilemap.collisionMap.HeightinPixels - 1) 
     { 
      downLeft = new Point(cell.X - 1, cell.Y + 1); 
     } 
     if (cell.X < tilemap.collisionMap.WidthinPixels - 1 && cell.Y < tilemap.collisionMap.Height - 1) 
     { 
      downRight = new Point(cell.X + 1, cell.Y + 1); 
     } 

     if (Up != null && tilemap.collisionMap.GetCellIndex(Up.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(Up.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 

      } 
     } 
     if (Down != null && tilemap.collisionMap.GetCellIndex(Down.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(Down.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 

      } 
     } 
     if (Right != null && tilemap.collisionMap.GetCellIndex(Right.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(Right.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 
       speed = -1f; 
       sideCollide = "right"; 
      } 
      else 
      { 
       sideCollide = "none"; 
      } 
     } 
     if (Left != null && tilemap.collisionMap.GetCellIndex(Left.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(Left.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 
       speed = 1f; 
       sideCollide = "left"; 
      } 
      else 
      { 
       sideCollide = "none"; 
      } 
     } 
     if (upLeft != null && tilemap.collisionMap.GetCellIndex(upLeft.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(upLeft.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 

      } 
     } 
     if (upRight != null && tilemap.collisionMap.GetCellIndex(upRight.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(upRight.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 

      } 
     } 
     if (downLeft != null && Left != null && tilemap.collisionMap.GetCellIndex(downLeft.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(downLeft.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 
       speed = 1f; 
       sideCollide = "left"; 
      } 
     } 
     if (downRight != null && Right != null && tilemap.collisionMap.GetCellIndex(downRight.Value) == 1) 
     { 
      Rectangle rect = Engine.CreateCell(downRight.Value); 
      Rectangle playerCell = Boundary; 

      if (rect.Intersects(playerCell)) 
      { 
       speed = -1f; 
       sideCollide = "right"; 
      } 
     } 

     if (Right == null && Left == null) 
     { 
      sideCollide = "none"; 
     } 
    } 

    public Rectangle Boundary 
    { 
     get 
     { 
      Rectangle rect = bounds; 
      rect.X = (int)pos.X; 
      rect.Y = (int)pos.Y; 
      return rect; 
     } 
    } 

那麼,怎樣才能提高我的碰撞?

回答

1

這個答案主要是迴應Tim的回答 - 因爲他給了很多錯誤的方法。 (你的問題是一個非常大的代碼轉儲,我不能真正發揮那麼多代碼的現貨錯誤)。

碰撞檢測技巧 - 「真正」物理引擎的做法 - 是始終將您的物體視爲固體。你總是 - 每一幀 - 檢查相互滲透的對象,然後分開他們,如果他們相互滲透。

如果您只測試跨移動對象的邊界你錯過碰撞。這包括任何嘗試通過捕捉表面來預測和避免碰撞的方法。如果你這樣做,你只是要求浮點精度的錯誤,讓你滑入對象。

編輯:當然,你的代碼似乎都是基於整數的(PointRectangle)。所以至少浮點精度不應該成爲問題。但也許你有一個<你應該有一個<=或這樣的效果?

(你也在很多地方使用字符串,你非常應該使用枚舉。)