Java 如何为我的程序获得流体运动?

Java 如何为我的程序获得流体运动?,java,Java,程序运行良好,但当我按住关键点或更改关键点时,运动并不平滑。在变得平滑之前,它会暂停一秒钟。我还是Java的初学者,请详细解释 import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Game2015 { JFrame frame; DrawRect mainPanel; GridBagLayout gridbag; GridBagConstraints constra

程序运行良好,但当我按住关键点或更改关键点时,运动并不平滑。在变得平滑之前,它会暂停一秒钟。我还是Java的初学者,请详细解释

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Game2015
{
   JFrame frame;
   DrawRect mainPanel;
   GridBagLayout gridbag;
   GridBagConstraints constraints;
   Data data;
   int width;
   int height;

   public static void main(String[] args)
   {
      new Game2015();
   }

   public Game2015()
   {
      frame = new JFrame();
      width = 400;
      height = 500;

      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.setVisible(true);
      frame.setSize(width, height);
      frame.setResizable(false);

      data = new Data();
      mainPanel = new DrawRect(data);
      mainPanel.setFocusable(true);
      mainPanel.setBackground(Color.WHITE);
      KeyHandler keys = new KeyHandler();
      mainPanel.addKeyListener(keys);

      frame.add(mainPanel);
      frame.validate();
      frame.setLocationRelativeTo(null);
      Thread thread = new Thread(new Runnable(){
         public void run()
         {
            while(true)
            {
               mainPanel.repaint();
               mainPanel.requestFocus(true);
            }
         }
      });
      thread.start();
   }

   public class KeyHandler implements KeyListener
   {
      public void keyReleased(KeyEvent event)
      {

      }
      public void keyTyped(KeyEvent event)
      {

      }

      public void keyPressed(KeyEvent event)
      {
         if(event.getKeyCode() == KeyEvent.VK_W || event.getKeyCode() == KeyEvent.VK_UP)
         {
            if(data.getY() >= data.getSpeed())
            {
               data.setY(data.getY() - data.getSpeed());
            }
            else
            {
               data.setY(0);
            }
         }
         else if(event.getKeyCode() == KeyEvent.VK_S || event.getKeyCode() == KeyEvent.VK_DOWN)
         {
            if(data.getY() + 95 <= height - data.getSpeed())
            {
               data.setY(data.getY() + data.getSpeed());
            }
            else
            {
               data.setY(height - 95);
            }
         }
         else if(event.getKeyCode() == KeyEvent.VK_A || event.getKeyCode() == KeyEvent.VK_LEFT)
         {
            if(data.getX() >= data.getSpeed())
            {
               data.setX(data.getX() - data.getSpeed());
            }
            else
            {
               data.setX(0);
            }
         }
         else if(event.getKeyCode() == KeyEvent.VK_D || event.getKeyCode() == KeyEvent.VK_RIGHT)
         {
            if(data.getX() + 75 <= width - data.getSpeed())
            {
               data.setX(data.getX() + data.getSpeed());
            }
            else
            {
               data.setX(width - 75);
            }
         }
         else if(event.getKeyCode() == KeyEvent.VK_ESCAPE)
         {
            frame.dispose();
            System.exit(0);
         }
      }
   }
}
数据类的代码如下:

public class Data
{
   int x, y, speed;

   public Data()
   {
      x = 0;
      y = 0;
      speed = 10;
   }

   public void setSpeed(int new_speed)
   {
      speed = new_speed;
   }

   public int getSpeed()
   {
      return speed;
   }

   public void setX(int new_x)
   {
      x = new_x;
   }

   public int getX()
   {
      return x;
   }

   public void setY(int new_y)
   {
      y = new_y;
   }

   public int getY()
   {
      return y;
   }
}

这是因为have-java处理事件:当您第一次按下一个键时,它会触发一个事件(按下该键),并且只有在一小段时间后它才会继续触发事件(按住该键)。您可以通过在每次触发事件时打印出来来测试这一点,并且在第一个事件和其余事件之间会有一个小的延迟

解决这个问题的方法不是每次按一个键改变角色的位置,而是改变角色的速度

例如,代替

if(event.getKeyCode() == KeyEvent.VK_W || event.getKeyCode() == KeyEvent.VK_UP){
       if(data.getY() >= data.getSpeed())
       {
           data.setY(data.getY() - data.getSpeed());
       } else {
           data.setY(0);
       }
}   ... etc ...
是的

if(event.getKeyCode() == KeyEvent.VK_W || event.getKeyCode() == KeyEvent.VK_UP){
       data.setVelocityY(-data.getSpeed());
}   ... etc ...
除此之外,当他们释放钥匙时,你还需要停止他们的速度。在
keyreased()
方法中,只需执行相同的操作,但不要将“速度”设置为“速度”,而是将其设置为0

if(event.getKeyCode() == KeyEvent.VK_W || event.getKeyCode() == KeyEvent.VK_UP){
       data.setVelocityY(0);
}   ... etc ...
然后在游戏循环中,使用一个方法
update()
,处理计算(将速度添加到位置)

所以

会是

public void run() {
    while(true) {
        update();
        mainPanel.repaint();
        mainPanel.requestFocus(true);
    }
}
更新方法将在哪里

public static void update() {
    data.setY(data.getY() + data.getVelocityY());
    data.setX(data.getX() + data.getVelocityX());
}

您应该查阅java游戏的基本教程。例如,我总能找到一个很好的入门教程。

通常的解决方案是让计时器以特定的速率运行,在计时器中,检查键是否按下(可以使用keyPressed、keyReleased和布尔字段)。这难道不会使播放器永远不会停止移动吗?因为线程一直在调用方法更新,所以玩家会不断地更改它的位置,即使他/她放开了键,它也不会停止。
public void run() {
    while(true) {
        update();
        mainPanel.repaint();
        mainPanel.requestFocus(true);
    }
}
public static void update() {
    data.setY(data.getY() + data.getVelocityY());
    data.setX(data.getX() + data.getVelocityX());
}