1

I am making a java 2d side scroller and im having problems with multiple keys at the same time. Such as right + up. Whenever you release the up you stop moving right as you slowly go back to the ground even though right is still being pressed. Here are the keyboard listeners I have setup. dx is my horizontal movement speed and dy is the vertical height. Below is from the character class

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();
        }

This is some code from the main game window that deals with calling the key press/release methods as well as dealing with the jump.

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;
    }

}
4

2 回答 2

2

不要在 AL 课程中直接处理你的动作。相反,使用布尔值并相应地将它们设置为 true/false:

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 在按键被操作时被调用,尽管这意味着它不会与你的主循环同步。

要移动您的精灵,请在循环中调用一个方法,如果您的条件为真,则相应地移动您的精灵,否则什么也不做。

编辑:在查看了您的代码之后,我有一些建议。

首先,查找亚像素渲染。亚像素渲染用于使精灵的运动看起来更平滑。

要查找的另一件事是可变时间步长(有时称为增量时间步长)。增量时间可用于确保动作与玩家 fps 同步执行。如果一个玩家有 60 fps 而另一个玩家有 30 fps,则有 30 fps 的玩家将看到以一半速度执行的动作。然而,对于增量时间步,动作总是以相同的速度执行。这是一篇好文章

第三件事是你的时机。目前您正在使用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时你会降落.

于 2013-10-15T15:29:23.703 回答
0

问题在于操作系统处理关键事件并将它们传递给您的应用程序的方式。当你按下一个键时,它会触发一个向下事件。然后根据您的重复设置,它会在一段时间后以一定的频率再次开始按键。(你可以在打字时看到这个。按下一个键并按住它)。

当您按下另一个键时,它会停止另一个键的重复触发。您也可以在打字时看到这一点。握住一把钥匙,然后开始握住另一个。如您所料,原始键停止。

这甚至不会与每个操作系统都保持一致,人们可以通过加快键盘上的重复计时器来在你的游戏中作弊。

由于这些原因,在关键侦听器内部制作动画是一个非常糟糕的主意。您应该将标志设置为真/假并在游戏循环中读取它们。(如@Troubleshoot 的回答所示)。

于 2013-10-15T15:40:35.310 回答