2013-10-15 95 views
1

我正在製作一個java 2d側滾動器,並且在同一時間有多個鍵出現問題。如右+上。無論何時釋放起來,即使右側仍然被按下,當你慢慢地回到地面時,也會停止向右移動。這裏是我設置的鍵盤監聽器。 dx是我的水平移動速度,dy是垂直高度。下面是從字符類釋放密鑰時遊戲滯後

public void keyPressed(KeyEvent e) { 
    int key = e.getKeyCode(); 
    if (key == KeyEvent.VK_LEFT) { 
     dx = -5; 
     mainCharacterImageFacing = l.getImage(); 
     } 

    if (key == KeyEvent.VK_RIGHT) { 
     dx = 5; 
     mainCharacterImageFacing = r.getImage(); 
    } 

    if (key == KeyEvent.VK_UP) { 
     dy = 1; 
     mainCharacterImageFacing = r.getImage(); 
    } 

} 

public void keyReleased(KeyEvent e) { 
    int key = e.getKeyCode(); 
    if (key == KeyEvent.VK_LEFT); 
    dx = 0; 
    if (key == KeyEvent.VK_RIGHT) 
     dx = 0; 
    if (key == KeyEvent.VK_UP) 
     {dy = 0; 
     mainCharacterImageFacing = r.getImage(); 
     } 

這是從與調用按鍵/釋放方法以及處理與跳躍都將遊戲主窗口中的一些代碼。

private class AL extends KeyAdapter{ 
    public void keyReleased(KeyEvent e) { 
     p.keyReleased(e); 
    } 

    public void keyPressed(KeyEvent e) { 
     p.keyPressed(e); 
    } 
} 

@Override 
public void run() 
{ 
    long beforeTime; 
    long timeDiff; 
    long sleep; 

    beforeTime = System.currentTimeMillis(); 
    while(done == false) 
    { 
     cycle(); 
     timeDiff = System.currentTimeMillis() - beforeTime; 
     sleep = 10 - timeDiff; 
     if (sleep < 0) 
      sleep = 2; 
     try { 
      Thread.sleep(sleep); 
     } catch (Exception e) 
     {} 
     beforeTime = System.currentTimeMillis(); 
    } 
    done = false; 
    h = false; 
    k = false; 
} 

boolean h = false; 
boolean done = false; 
public void cycle() { 
    if (h == false) 
     v = v - 2; //jump speed falling 
    if (v == 350) //max y value of jump. Lower numbers = higher jumps 
     h = true; 
    if (h == true && v <= 470) //starting y value 
     { 
     v = v + 2; //jump speed rising 
     if (v == 470) 
      done = true; 
    } 

} 

回答

2

不要直接在AL類中處理你的動作。相反,使用布爾值並相應設置爲真/假:

private class AL extends KeyAdapter{ 
    public void keyPressed(KeyEvent e) { 
     int key = e.getKeyCode(); 
     if (key == KeyEvent.VK_LEFT) { 
      left = true; 
     } 

     if (key == KeyEvent.VK_RIGHT) { 
      right = true 
     } 

     if (key == KeyEvent.VK_UP) { 
      //... 
     } 

    } 

    public void keyReleased(KeyEvent e) { 
     int key = e.getKeyCode(); 
     if (key == KeyEvent.VK_LEFT) 
      left = false 
     if (key == KeyEvent.VK_RIGHT) 
      right = false 
     if (key == KeyEvent.VK_UP) 
      //... 
     } 
    } 

這樣做的原因是因爲的keyPressed和的keyReleased當鍵作用時被調用,儘管這意味着它不會在同步與你的主循環。

要移動你的精靈在循環中調用一個方法,如果你的條件是真的,相應地移動你的精靈,否則什麼也不做。

編輯:在審查你的代碼之後,我還有一些建議。

首先,查看子像素渲染。子像素渲染用於使精靈的運動看起來更加平滑。

要查找的另一件事是可變時間步(有時稱爲增量時間步)。 Delta時間可用於確保動作與玩家fps同步執行。如果一個玩家擁有60fps而另一個玩家擁有30fps,則30fps的玩家將看到以一半速度執行的動作。然而,使用增量時間步長,動作始終以相同的速度執行。 Here's a good article

第三件事是你的時機。目前您正在使用System.getCurrentTimeMills。這是不好的,也不準確。相反,請使用System.nanoTime

我發現的第四件事是你的跳躍算法。更好的方法是包括加速。首先,你需要聲明一個加速常數(0.1或0.2是好的)並計算垂直速度。然後,當垂直速度達到一定值時,您可以下降。這是一小段代碼,但如果你有重力,你可能想編輯它。首先設置vSpeed默認爲-8。

public void jump() { 
    vSpeed += ACCELERATION; 
    if(vSpeed < 8) 
     dy += vSpeed; 
    else 
     vSpeed = -8; 
     falling = false; 
} 

我只是寫這離我的頭頂,但基本上,因爲向上移動被帶走了一些,你似乎跳的時候,它增加了負數,那麼你就會開始當它到達0下降,再到達8時陸地。

0

問題是操作系統處理關鍵事件並將它們傳遞給應用程序的方式。當你按下一個鍵時,它會觸發一個事件。然後根據您的重複設置,在一段時間後以某種頻率再次按下該鍵。 (你可以在打字時看到這個,按住一個鍵並按住它)。

當您按另一個鍵時,它會停止重複觸發另一個鍵。你也可以在打字時看到這一點。按住一個鍵,然後開始另一個。正如您所期望的那樣,原始鑰匙停下來。

這甚至不會與每個操作系統一致,並且人們可以通過使鍵盤上的重複計時器更快地在遊戲中作弊。

由於這些原因,在關鍵偵聽器中執行動畫是一個非常糟糕的主意。你應該設置標誌爲true/false並在遊戲循環中讀取它們。 (如@ @ Troubleshoot的答案中所示)。