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

时间:2015-01-06 04:47:57

标签: java

该程序工作正常,但当我按住一个键或更改键时,动作不顺畅。在变得平滑之前暂停一瞬间。我还是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);
         }
      }
   }
}

绘制矩形的代码是:

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;

public class DrawRect extends JPanel
{
   BufferedImage img_player;
   File file;
   Data data;

   public DrawRect(Data newData)
   {
      data = newData;
      try
      {
         file = new File("Images\\Player.png");
         img_player = ImageIO.read(file);
      }
      catch (Exception exception)
      {

      }
   }

   @Override
   public void paintComponent(Graphics graphics)
   {
      super.paintComponent(graphics);
      Graphics2D graphics2D = (Graphics2D) graphics;
      graphics2D.drawImage(img_player, data.getX(), data.getY(), null);
   }
}

并且Data类的代码是:

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

1 个答案:

答案 0 :(得分:0)

这是因为有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 ...

除此之外,你还需要在释放钥匙时停止速度。在keyReleased()方法中,只需执行相同的操作,但不要将速度设置为速度,而是将其设置为0.

if(event.getKeyCode() == KeyEvent.VK_W || event.getKeyCode() == KeyEvent.VK_UP){
       data.setVelocityY(0);
}   ... etc ...

然后在游戏循环和方法update()中处理计算(将速度添加到位置)

所以

public void run() {
    while(true) {
        mainPanel.repaint();
        mainPanel.requestFocus(true);
    }
}

将是

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游戏的基础教程。例如,我总是发现this是一本很好的入门教程。