2012-11-30 273 views
3

所以我在將一些問題在JPanel中全面移動時遇到了一些問題。現在它不是JPanel的問題或錯誤,我只是不能像應該那樣移動Snake。我知道問題出在哪裏,但我無法想出一個辦法讓它在沒有問題的情況下正常工作。將蛇的身體全部移動導致身體結塊

問題:Snake被認爲距離彼此大約10 px,但是它正在聚集成大約彼此相距1 px。

這是它應該看起來如何。

This is how it is supposed to look.

這是它的外觀時,它叢叢了

This is how it looks when it clumps up

我都試過,我能想到的幾種不同的方式,我有它的工作好幾天。

蛇應該保持在1px的速度運動,所以它是流暢的動畫。無論如何,頭部無需受到影響。但是一旦迴路碰到頭部,就會找到頭部的位置,並將位置提供給身體。

移動的蛇。

int playerVel = 1; 

public void MovePlayer(){ 
    //Move the snake tail 
    if(IsMoving()){ 
     //Move the head by its velocity 
     if(left){ 
      X[0] -= playerVel; 
     } 
     else if(right){ 
      X[0] += playerVel; 
     } 
     else if(up){ 
      Y[0] -= playerVel; 
     } 
     else if(down){ 
      Y[0] += playerVel; 
     } 

     for(int i = getSizeWithArmor(); i > 0; i--){ 
      //Issue is when the for loop finishes counting down it located the Head's position that is 1 px away, and the rest of the body clumps up to it. 
      int newLocX = X[i] - X[i-1]; 
      int newLocY = Y[i] - Y[i-1]; 

      if(newLocX != 0){ 
       if(newLocX == 10 || newLocX == -10){ 
        X[i] = X[i-1]; 
       } 
       else if(newLocX > 0){ 
        X[i] = X[i-1] + 10; 
       } 
       else if(newLocX < 0){ 
        X[i] = X[i-1] - 10; 
       } 
       else{ 
        X[i] = X[i-1]; 
       } 
      } 

      if(newLocY != 0){ 
       if(newLocY == 10 || newLocY == -10){ 
        Y[i] = Y[i-1]; 
       } 
       else if(newLocY > 0){ 
        Y[i] = Y[i-1] + 10; 
       } 
       else if(newLocY < 0){ 
        Y[i] = Y[i-1] - 10; 
       } 
       else{ 
        Y[i] = Y[i-1]; 
       } 
      } 
     } 
    } 
} 

編輯1:

任何幫助將不勝感激!如果我需要添加更多的細節,請隨時讓我知道!

編輯2:

Move X[0] X[1] X[2] X[3] X[4] X[5] 
    ----------------------------------------------------- 

    1  60  50  40  30  20  10 
    2  61  51  41  31  21  11 
    3  62  52  42  32  22  12 
    4  63  53  43  33  23  13 
    5  64  54  44  34  24  14 
    6  65  55  45  35  25  15 
    7  66  56  46  36  26  16 
    8  67  57  47  37  27  17 

就是我看要怎樣做。但隨着蛇越來越長,它必須適應。

編輯3:

這裏是整個類的播放器。玩家階層負責所有的移動,並對齊自己。

級的球員:

public class Player implements Runnable{ 
//Info about the Player 
private int[] X; 
private int[] Y; 
private int[] size; 
private int blockPickup; 
private int points; 
private int armor; 
private int blockSize = 10; 

//Speeds 
private int playerVel = 1; 
private int speedDelay = 100; 

//Direction the player is moving 
private boolean up = false; 
private boolean down = false; 
private boolean right = false; 
private boolean left = false; 
private boolean inGame = false; 
private boolean gamePaused = false; 

private int boardWidth; 
private int boardHeight; 
private int allSpaces; 

public void AddBlock(){ 
    size = new int[getSizeWithArmor() + 1]; 

    points++; 
    blockPickup++; 
} 
private void AddBlock(int increase){ 
    size = new int[getSizeWithArmor() + increase]; 
    points++; 
} 

public void AddArmor(){ 
    armor++; 
    AddBlock(1); 
} 

public void RemoveArmor(){ 
    armor--; 
    size = new int[getSizeWithArmor() - 1]; 
} 

public int getArmor(){ 
    return armor; 
} 
public int getSizeWithArmor(){ 
    return size.length; 
} 

public int getSizeWithoutArmor(){ 
    return size.length - armor; 
} 

public void ResetSize(){ 
    size = new int[1 + getArmor()]; 
} 

public int getPoints(){ 
    return points; 
} 
public void IsGamePlaying(boolean playing){ 
    inGame = playing; 
} 
public void IsGamePaused(boolean pause){ 
    gamePaused = pause; 
} 

public void Reset(){ 
    points = 0; 
    armor = 0; 
    blockPickup = 0; 

    ResetSize(); 
    InitPlayer(); 
} 

public Image Head(){ 
    if(up){ 
     return headUp; 
    } 
    else if(down){ 
     return headDown; 
    } 
    else if(right){ 
     return headRight; 
    } 
    else if(left){ 
     return headLeft; 
    } 
    else{ 
     return headRight; 
    } 
} 

public void InitPlayer(){ 
    for(int i = 0; i <= getSizeWithArmor(); i++){ 
     X[i] = (boardWidth/2) - (i * blockSize); 
     Y[i] = boardHeight/2; 
    } 
} 

public void SetDirection(int key){ 
    if(key == KeyEvent.VK_UP && !down){ 
     up = true; 
     left = false; 
     down = false; 
     right = false; 
    } 
    else if(key == KeyEvent.VK_DOWN && !up){ 
     up = false; 
     left = false; 
     down = true; 
     right = false; 
    } 
    else if(key == KeyEvent.VK_LEFT && !right){ 
     up = false; 
     left = true; 
     down = false; 
     right = false; 
    } 
    else if(key == KeyEvent.VK_RIGHT && !left){ 
     up = false; 
     left = false; 
     down = false; 
     right = true; 
    } 
} 

public void MovePlayer(){ 
    //Move the snake tail 
    if(IsMoving()){ 
     //Move the head by its velocity 

     for(int i = getSizeWithArmor(); i > 0; i--){ 

      int newLocX = X[i] - X[i-1]; 
      int newLocY = Y[i] - Y[i-1]; 

      //Block going left 
      if(newLocX > 0){ 
       if(newLocX == -1){ 

       } 
       else if(newLocX < -1){ 
        X[i] = X[i-1] + 10; 
       } 
      } 
      //Block going right 
      else if(newLocX < 0){ 
       X[i] = X[i-1] - 10; 
      } 

      //Block going up 
      if(newLocY > 0){ 
       Y[i] = Y[i-1] + 10; 
      } 
      //Block going down 
      else if(newLocY < 0){ 
       Y[i] = Y[i-1] - 10; 
      } 
     } 

     if(left){ 
      X[0] -= playerVel; 
     } 
     else if(right){ 
      X[0] += playerVel; 
     } 
     else if(up){ 
      Y[0] -= playerVel; 
     } 
     else if(down){ 
      Y[0] += playerVel; 
     } 
    } 
} 

public boolean IsMoving(){ 
    if(up || down || left || right){ 
     return true; 
    } 
    else{ 
     return false; 
    } 
} 

public int getX(int i){ 
    return X[i]; 
} 

public int getY(int i){ 
    return Y[i]; 
} 

public void paint(Graphics2D g){ 
    for(int i = 0; i < getSizeWithArmor(); i++){ 
     if(i == 0){ 
      g.drawImage(Head(), X[0], Y[0], null); 
     } 
     else if(getArmor() >= i){ 
      g.drawImage(armorImage, X[i], Y[i], null); 
     } 
     else{ 
      g.setColor(Color.YELLOW); 
      g.fillRect(X[i], Y[i], blockSize, blockSize); 
     } 
    } 
} 

@Override 
public void run() { 
    try{ 
     while(inGame){ 
      if(!gamePaused){ 
       MovePlayer(); 
       Thread.sleep(20); 
      } 
     } 
    } 
    catch(Exception e){ 
     System.err.println("Player has encoundered an error: "+e.getMessage()); 
    } 
} 
} 

我Board類調用所有進行修改,這個類所需要的數據。如果這個班非常無組織,我很抱歉。我沒有回去重新組織它,並減少了很多垃圾。另外我知道很多代碼是多餘的,不需要。我正在解決所有這些問題。現在我只是想解決蛇的身體問題。

編輯4:

我已經想通了一部分。我已經順利地向右下方動畫。然而,一旦你離開或上升,它將會發生碰撞,並開始再次注意問題。它就像我需要檢查它是否在之前和向哪個方向移動。

public void MovePlayer(){ 
    //Move the snake tail 
    if(IsMoving()){ 
     //Move the head by its velocity 

     for(int i = getSizeWithArmor(); i > 0; i--){ 
      int newLocX = X[i] - X[i-1]; 
      int newLocY = Y[i] - Y[i-1]; 

      //Figure out the last direction it was going in 
      if(newLocX != 0 && newLocY != 0){ 

      } 

      //Block going left 
      if(newLocX > 0){ 
       if(newLocX > 0 && newLocX <= 10){ 
        X[i] -= 1; 
       } 
       else if(newLocX > 10){ 
        X[i] = X[i-1] - 10; 
       } 
      } 
      //Block going right 
      else if(newLocX < 0){ 
       if(newLocX < 0 && newLocX >= -10){ 
        X[i] += 1; 
       } 
       else if(newLocX < -10){ 
        X[i] = X[i-1] + 10; 
       } 
      } 
      //Block going up 
      else if(newLocY > 0){ 
       if(newLocY == 1){ 
        Y[i] -= 1; 
       } 
       else if(newLocY > 1){ 
        Y[i] = Y[i-1] - 10; 
       } 
      } 
      //Block going down 
      else if(newLocY < 0){ 
       if(newLocY < 0 && newLocY >= -10){ 
        Y[i] += 1; 
       } 
       else if(newLocY < -10){ 
        Y[i] = Y[i-1] + 10; 
       } 
      } 

     if(left){ 
      X[0] -= playerVel; 
     } 
     else if(right){ 
      X[0] += playerVel; 
     } 
     else if(up){ 
      Y[0] -= playerVel; 
     } 
     else if(down){ 
      Y[0] += playerVel; 
     } 
    } 
} 
+0

@TomSmilack即使我確實將環路改爲類似的東西,頭部並不需要受到影響,因爲它正在被移動。但是一旦迴路碰到頭部,就會找到頭部的位置,並在頭部被放置之前將位置提供給身體。 – Twister1002

+0

你說得對,我沒有仔細閱讀其餘部分。 –

+0

添加一個[SSCCE](http://sscce.org),你將得到更快的幫助,你的循環也應該像'for(int i = getSizeWithArmor(); i> = 0; i - )'和不是'for(int i = getSizeWithArmor(); i> 0; i - )'因爲這永遠不會檢查數組的第一個值,即'array [0]' –

回答

2

This JSFiddle (which generates the table below)表明您的循環不按其應有的方式運行。與[50, 40, 30, 20, 10, 0]假想的X立場出發,這是它看起來像10次迭代後:

moves X[0] X[1] X[2] X[3] X[4] X[5] 
---------------------------------------------------- 
0  50  40  30  20  10  0 
1  51  41  40  30  20  10 
2  52  42  31  40  30  20 
3  53  43  32  41  40  30 
4  54  44  33  42  31  40 
5  55  45  34  43  32  41 
6  56  46  35  44  33  42 
7  57  47  36  45  34  43 
8  58  48  37  46  35  44 
9  59  49  38  47  36  45 
10  60  50  39  48  37  46 

我一直在玩弄它,但想不出好辦法來解決這個代碼移動棋子他們應該的方式。我認爲這比使用數學或單個for循環要複雜一點。一種可能性是存儲每個塊正在移動的方向。

你也可以找出每個塊的目的地(即它將在​​10步中的哪個位置?),然後進行插值以使其平穩移動。這種方法的優點是,您可以在處理動畫之前確保塊到達正確的位置 - 確保遊戲邏輯可以工作,然後再擔心它的外觀。


認爲this is closer到你想要做什麼(不包含數字的移動行是目標數組):

moves X[0] X[1] X[2] X[3] X[4] X[5] X[6] X[7] X[8] X[9] X[10] 
-------------------------------------------------------------------------------------------- 
0  50  40  30  30  30  20  20  20  30  40  50 
     50  40  30  30  30  20  20  20  30  40  50 
1  51  41  31  30  30  21  20  20  29  39  49 
2  52  42  32  30  30  22  20  20  28  38  48 
3  53  43  33  30  30  23  20  20  27  37  47 
4  54  44  34  30  30  24  20  20  26  36  46 
5  55  45  35  30  30  25  20  20  25  35  45 
6  56  46  36  30  30  26  20  20  24  34  44 
7  57  47  37  30  30  27  20  20  23  33  43 
8  58  48  38  30  30  28  20  20  22  32  42 
9  59  49  39  30  30  29  20  20  21  31  41 
10  60  50  40  30  30  30  20  20  20  30  40 
     60  50  40  30  30  30  20  20  20  30  40 
11  61  51  41  31  30  30  21  20  20  29  39 
12  62  52  42  32  30  30  22  20  20  28  38 
13  63  53  43  33  30  30  23  20  20  27  37 
14  64  54  44  34  30  30  24  20  20  26  36 
15  65  55  45  35  30  30  25  20  20  25  35 
16  66  56  46  36  30  30  26  20  20  24  34 
17  67  57  47  37  30  30  27  20  20  23  33 
18  68  58  48  38  30  30  28  20  20  22  32 
19  69  59  49  39  30  30  29  20  20  21  31 
20  70  60  50  40  30  30  30  20  20  20  30 
     70  60  50  40  30  30  30  20  20  20  30 
21  71  61  51  41  31  30  30  21  20  20  29 

或者圖形:

enter image description here

我會嘗試將它翻譯成Java,但是我的Java很生疏,我不能將它插入到你的代碼中, o我不能保證它會是完美的。重要的部分是邏輯。另外請注意,這只是對x值,但它應該是微不足道的增加y值:

你需要一個目標陣列是X副本:

int[] dests = (int[])X.clone();

然後,裏面MovePlayer,將它設置基於移動的方向只有當塊已達到其目的地(因而需要新的):

if(IsMoving() && X.equals(dests)) { 
    for(int i = dests.length - 1; i > 0; i--) { 
     if(X[i] != X[i-1]) 
      dests[i] = X[i-1]; 
    } 

    if(left) { 
     dests[0] = X[0] - 10; 
    } else if(right) { 
     dests[0] = X[0] + 10; 
    } 
} 

最後,寸塊朝目的地:

for(var i = 0; i < X.length; i++) { 
    X[i] += Integer.signum(dests[i] - X[i]); 
} 

signum根據參數的符號返回[-1, 0, 1]之一。

+0

這幾乎是它在做什麼。我還沒有想出如何繞過循環。 – Twister1002

+0

已更新。如果這不是你要找的東西,那麼你需要發佈一張圖片或一張帶有一些數字的表格。 –

+0

「編輯2」字段中更新的預期結果。 – Twister1002