2013-12-16 74 views
1

這是一個跟進問題到question that I posted last night。我必須在Windows Form中爲學校編寫一款遊戲,並且我正在創建一個迷宮遊戲,玩家必須在他們被殺之前在迷宮中導航。作爲迷宮遊戲,必須使用一些碰撞檢測來確保玩家不會簡單地穿過牆壁(這將是一個非常無聊的遊戲)。我已經實現了一個基於昨晚我問過的問題來防止這個問題的功能,但是我得到了一些奇怪的結果。二維窗體中奇怪的粘性碰撞檢測窗體遊戲

當玩家觸摸牆壁時,遊戲停止,玩家最終陷入困境。玩家不能移動,除非他們按下組合鍵移動穿過牆壁(我的遊戲使用WASD,所以如果我觸摸牆壁,我可以按下W + A並穿過牆壁到達我的玩家脫落的另一側) 。

這是我的碰撞代碼:

   // This goes in the main class 
       foreach (Rectangle wall in mazeWalls) 
       { 
        if (playerRectangle.IntersectsWith(wall)) 
        { 
         player.Stop(); 
        } 
       } 

這是玩家的移動代碼:

public void Move(Direction dir) 
    { 
     // First, check & save the current position. 
     this.lastX = this.x; 
     this.lastY = this.y; 

     if (dir == Direction.NORTH) 
     { 
      if (!CheckCollision()) 
      { 
       this.y -= moveSpeed; 
      } 
      else 
      { 
       this.y += 1; 
      } 

     } 
     else if (dir == Direction.SOUTH) 
     { 
      if (!CheckCollision()) 
      { 
       this.y += moveSpeed; 
      } 
      else 
      { 
       this.y -= 1; 
      } 


     } 
     else if (dir == Direction.EAST) 
     { 
      if (!CheckCollision()) 
      { 
       this.x += moveSpeed; 
      } 
      else 
      { 
       this.x -= 1; 
      } 

     } 
     else if (dir == Direction.WEST) 
     { 
      if (!CheckCollision()) 
      { 
       this.x -= moveSpeed; 
      } 
      else 
      { 
       this.x += 1; 
      } 


     } 
    } 

CheckCollision()方法:

private bool CheckCollision() 
    {    
     // First, check to see if the player is hitting any of the boundaries of the game. 
     if (this.x <= 0) 
     { 
      isColliding = true; 
     } 
     else if (this.x >= 748) 
     { 
      isColliding = true; 
     } 
     else if (this.y <= 0) 
     { 
      isColliding = true; 
     } 
     else if (this.y >= 405) 
     { 
      isColliding = true; 
     } 
     else if (isColliding) 
     { 
      isColliding = false; 
     } 
     // Second, check for wall collision. 
     return isColliding; 
    } 

Stop()方法:

public void Stop() 
    { 
     this.x = lastX; 
     this.y = lastY;    
    } 

Here是我上傳的gif,以便您可以看到玩家在迷宮牆上的行爲。注意他是如何滑過牆壁並反覆卡住的。

我的問題是我該如何讓這個玩家停止粘連,並且實際上能夠滑動和移動牆壁?我嘗試了多種碰撞模式,並且使用了昨晚的(非常有用的)答案,但他不會停止粘在牆上!讓我知道你是否需要任何其他細節/信息。

編輯:輸入代碼,由Dan-O請求:http://pastebin.com/bFpPrq7g

+0

確保您的代碼邏輯牢固。代碼可能有可能在同一時間檢查兩個按鍵事件,然後違反邏輯。嘗試確保只有按鍵事件檢查僅在獨佔模式下工作,例如使用線程等待/阻塞進行最後一個事件(排隊方法)。 – Kelmen

+0

@Kelmen你想我發佈我的鍵盤輸入代碼嗎?因爲遊戲是在WinForm中構建的,所以輸入是由鍵盤事件處理的,說實話我並不知道很多。如果你願意,我可以發佈。 – MrSir

+0

對不起,我對代碼審查不感興趣。我正在給你一個方向如何改進/調試你的代碼。 如果你不知道如何處理這個問題,就像使用Debug.WriteLine(「x is」+ x.ToString())。並試圖在dev模式下重現此問題,當它發生時,查看VS輸出窗口,檢查消息,查看是否將x值更改爲某個意外值,並追溯代碼,添加更多內容以查明原因。 – Kelmen

回答

1

遊戲設計是一個複雜的課題。對於實現2D迷宮遊戲,有一些非常有據可查的策略。大多數人都可以在這裏做的是根據你所做的事情提出一般性建議,因爲知道商業遊戲不是試圖在這裏做什麼。無論如何,我會投入我的兩分錢。我只在OpenGL中做過這樣的事情,而不是使用Windows Forms。

我看到的第一件事就是你的精靈不會集中在它的車道中。計算這最終會讓事情變得更容易,因爲玩家總是隻有4個可能的方向。當對角線也是可能的時候,北部,南部,東部和西部並不意味着太多。

設計你的遊戲板,使你的牆壁和你的車道是相同的寬度。使用均勻間隔的行和列。由於您使用的是固定的紙板大小,因此這應該像將寬度和高度除以所需的行數和列數一樣簡單。

完成此操作後,您將根據您的x和y座標始終知道您所在的車道。例如,如果您的列寬度爲80像素,而您處於x = 160,那麼您就知道自己在列2中(在基於0的陣列中爲1)。這是你能夠將敵人置於棋盤上並且能夠以編程方式跟蹤他們將要前進的唯一方法。此外,您可以根據車道適當調整您的球員和敵人。

比方說,你的行和列是80Wx60H像素(他們可以是你最喜歡的任何東西)。現在讓我們假設你的玩家從0,160開始向東移動。而且,根據你的地圖,當他到達第3列(零基模型中的第2列)時,他可以移動南北。意思是,當他達到160,160時。請記住,如果x = 0開始第1列,那麼80開始第2列,依此類推。

忘記碰撞一會兒,你可以使用這樣的邏輯。

RectangleF playerRectangle = new RectangleF(); 
int COLUMN_WIDTH = 80; 
int ROW_HEIGHT = 60; 

if (playerRectangle.IntersectsWith(wall)){ 
    int column = playerRectangle.X/COLUMN_WIDTH; 

    //---------------------------------------------- 
    // This will return false if the player 
    // is not positioned right at the column. The 
    // result of % will contain decimal digits. 
    // playerRectangle.X has to be a float though. 
    //---------------------------------------------- 
    if(column % 1 == 0){ 
     //-------------------------------------------- 
     // do this based on your keyboard logic. this 
     // is pseudo-code 
     //-------------------------------------------- 
     if(keys == keys.UP){ 
      // Move up 
     } 
     else if(keys == keys.DOWN){ 
      // Move down 
     } 
    } 
} 

你想要做的另一件事是存儲一個方向屬性與你的牆壁。這樣當你碰撞一個,你就會知道你的選擇是什麼運動。如果您碰撞的牆是WallOrientation.NorthSouth,您只能在擊中它時移動北部或南部。或者,你可以反過來從你打的方向。如果沒有按鍵,你就坐下。有些事情會這樣做。

public enum WallOrientation{ 
    NorthSouth, 
    EastWest 
} 

沒有對此代碼進行測試。我剛剛寫下它,所以可能會出現錯誤。我只是想給你一些想法。我希望這個建議能幫助你一些。

+0

此時,我的截止日期只有幾天,所以我想我會採納您的建議並實施基於網格的系統。謝謝。 – MrSir