2013-10-15 66 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的答案中所示)。