2011-08-10 20 views
5

我正在用Java編寫一個基於2D平鋪的遊戲,比如Bomberman(我的第一款遊戲)。如何在使用數組的2D瓦片遊戲中協調圖形和邏輯位置?

我使用二維數組來表示我跟蹤牆壁,可行走空間等的地圖。現在,我可以讓玩家平穩地交換精靈,取決於他按下的方向鍵(但不與其交互背景/地圖,它可以隨機走動並離開屏幕)。

我的問題是當我想要跟蹤玩家的數組中的位置。邏輯上,角色始終只屬於一個圖塊,但圖形上它可以位於兩個圖塊之間。我該如何解決這個問題?

我已經嘗試過這樣的:

currentTileArrayX = X/tileWidth;

currentTileArrayY = y/tileHeight;

其中,x和y是精靈的左上座標。 但是一切變得非常錯誤,因爲玩家的小精靈與小方塊大小不一樣。

我有另外一個選擇可以解決以前的問題:當玩家按下方向鍵時,將角色移動到下一個方塊,如動畫。這不會讓玩家在兩塊牌中間停下來......但是如果他用另一次按鍵打斷它呢?如何在動畫執行時停止用戶的操作?我認爲這是最簡單的解決方案,但我不知道如何實施它。

我已經嘗試在其他問題中找到解決方案,但我沒有運氣。我希望你能幫助我。

非常感謝。

回答

2

Aaaaaaaaaaaaaaah!遇到「離散空間問題」:)你的邏輯圖是離散的,但你的UI運動處於連續空間。我不是用戶實際上可以同時在兩個瓷磚中 - 視覺上是,但從來沒有'內部'。現在,你所得到的球員的位置,並且可以「隨時隨地」瓦片內或2瓦這麼說「邊界上」 ......

有兩種解決這個問題,IMO:

  1. 使用簡單舍入:如果玩家的位置是<瓦片邊界只是讓他在前面的瓦片。如果下一個更大。現在邊界問題 - 您可以使用啓發式算法,因爲您不應該相信浮點比較的準確性(即與0比較並不是一件好事)。所以你可以嘗試像這樣的if(currentPosition - boundary <= 0.000000001)然後認爲它是下一個瓦其他留在同一個。
  2. 那麼@Jay打敗了我。所以第二個是實際上已經定義了一個 的移動速度,並且移動了多個步驟的字符,每個 '點擊'/'按下' - 但是你說你有問題在「之間」按下了鍵 。
 
    update() 
     { 
      calculate(); //update all datastructures/calculations 
      draw(); //update the visual representation based on calculations 
     } 

update()是a.k.a,gameLoop:如果你的代碼是這樣設計 那麼它不應該是一個問題,我猜。我認爲這應該可以解決你的問題...

+0

Nupul我改變了我的代碼使用解決方案第一。感謝它,它解決了許多錯誤,我現在可以說它幾乎可行。但我還有一個問題:http://imageshack.us/f/687/bomberbug.png/ 我希望我在圖像中正確解釋它。 – Rama

+0

在圖像中,currentPosition仍然是紅色的圖塊。由於紅瓦的右邊是免費的,我可以走到右邊,但是我不能。 – Rama

+0

@Rama:你不明白你的意思......如果你可以向右走,那麼「爲什麼不呢?」其次,如果「圖形地」表明你不需要,那麼數據結構上也不應該被允許。您的內部模型必須準確地表達您的觀點。如果我不能在模型中正確使用,那麼我不應該被允許在視圖中這樣做,而不是反過來,因爲視圖是v.v.v.v的十進制。如果我沒有正確理解這個問題,你能否澄清一下這個問題? – PhD

1

我會盡量保持邏輯的一部分(平鋪球員屬於)和可視化部件(磚之間的動畫)作爲單獨的越好。我的做法是有一個合理的位置(玩家設置的區域)和移動速度(這基本上意味着玩家在移動到瓦片後不允許移動到下一個區塊的時間量)。然後,從一個瓦片到另一個瓦片的動畫將意味着你的精靈總是朝着你的瓦片的屏幕座標移動 - 這個時間很容易由移動速度決定(一個完整的瓦片移動應該只要玩家必須休息在當前的瓷磚上)。

唯一的特例就是這個「轉身」,在那裏你可以讓玩家隨時回到他來的瓷磚上,只需要(timeToRecoverOnTile - (timeToRecoverOnTile - timeSinceMovementStarted))

1

我曾經在AS3中做過基本相同的事情,但概念轉移到了Java。我決定創造兩個主要價值觀來幫助追蹤運動,一個包含玩家x/y值的點(按瓦)以及一個方向指向運動方向的點。下面是一些僞代碼:

if(direction.x == 0 && direction.x == 0) { 
    if (up) direction.y = -1; 
    else if (down) direction.y = 1; 
    else if (left) direction.x = -1; 
    else if (right) direction.x = 1; 
} else { 
    player.x += direction.x; 
    player.y += direction.y; 
    distance--; 
    if(distance == 0) { 
     direction.x = direction.y = 0; 
     distance = tileWidth; 
    } 
} 

很明顯,你必須要調整,要滿足您的需求,但是這是基礎。另外,tileWidth可以用一個整數字面值替換,該值等於單個tile的寬度。