我正在制作一个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;
}
}
答案 0 :(得分: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,但这意味着它不会与主循环同步。
移动精灵调用循环中的方法,如果条件为真,则相应地移动精灵,否则不执行任何操作。
编辑:在审核了您的代码后,我有一些建议。
首先,查看子像素渲染。子像素渲染用于使精灵的移动看起来更平滑。
要查找的另一件事是可变时间步(有时称为delta时间步长)。 Delta时间可用于确保操作与玩家fps同步执行。如果一个玩家有60fps而另一个玩家有30fps,那么30fps的玩家将看到以一半速度执行的动作。但是,使用delta时间步长,操作始终以相同的速度执行。 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。
答案 1 :(得分:0)
问题在于操作系统处理关键事件并将其传递给应用程序的方式。当您按某个键时,它会触发一个事件。然后根据您的重复设置,它会在一段时间后以一定的频率再次按下该键。 (键入时可以看到这一点。按一个键,然后按住它)。
当您按另一个键时,它会停止另一个键的重复触发。您也可以在打字时看到这一点。按住一个键,然后开始另一个键。正如您所料,原始键会停止。
这甚至不会与每个操作系统保持一致,人们可以通过在键盘上更快地重复计时器来欺骗你的游戏。
由于这些原因,在关键监听器中进行动画是一个非常糟糕的主意。你应该将设置标志设置为true / false并在游戏循环中读取它们。 (如@ Troubleshoot的回答所示)。