为什么在java应用程序上移动鼠标时运行更平稳?包括视频

为什么在java应用程序上移动鼠标时运行更平稳?包括视频,java,swing,animation,mouseover,java-2d,Java,Swing,Animation,Mouseover,Java 2d,我正在使用“固定时间步”部分的教程 这是密码- import javax.swing.*; 导入java.awt.*; 导入java.awt.event.*; 公共类GameLoopTest扩展JFrame实现ActionListener { private GamePanel GamePanel=新建GamePanel(); 私有JButton startButton=新JButton(“开始”); 私有JButton quitButton=新JButton(“退出”); 私有JButton

我正在使用“固定时间步”部分的教程

这是密码-

import javax.swing.*;
导入java.awt.*;
导入java.awt.event.*;
公共类GameLoopTest扩展JFrame实现ActionListener
{
private GamePanel GamePanel=新建GamePanel();
私有JButton startButton=新JButton(“开始”);
私有JButton quitButton=新JButton(“退出”);
私有JButton pauseButton=新JButton(“暂停”);
私有布尔运行=false;
private=false;
私人整数fps=60;
私有整数帧计数=0;
公共游戏测试()
{
超级(“固定时间步游戏循环测试”);
容器cp=getContentPane();
cp.setLayout(新的BorderLayout());
JPanel p=新的JPanel();
p、 setLayout(新网格布局(1,2));
p、 添加(开始按钮);
p、 添加(暂停按钮);
p、 添加(退出按钮);
cp.add(gamePanel,BorderLayout.CENTER);
cp.add(p,南部边界布局);
设置大小(500500);
addActionListener(这个);
quitButton.addActionListener(此);
pauseButton.addActionListener(这个);
}
公共静态void main(字符串[]args)
{
GameLoopTest glt=新GameLoopTest();
glt.setVisible(真);
}
已执行的公共无效操作(操作事件e)
{
对象s=e.getSource();
如果(s==开始按钮)
{
跑步=!跑步;
如果(正在运行)
{
startButton.setText(“停止”);
runGameLoop();
}
其他的
{
setText(“开始”);
}
}
如果(s==暂停按钮),则为else
{
暂停=!暂停;
如果(暂停)
{
pauseButton.setText(“取消暂停”);
}
其他的
{
pauseButton.setText(“暂停”);
}
}
如果(s==退出按钮),则为else
{
系统出口(0);
}
}
//启动一个新线程并在其中运行游戏循环。
public void runGameLoop()
{
线程循环=新线程()
{
公开募捐
{
gameLoop();
}
};
loop.start();
}
//只在另一个线程中运行这个!
私有void gameLoop()
{
//该值可能存储在其他位置。
最后一场双人赛,赫兹=30.0;
//计算我们的目标游戏赫兹每帧需要多少纳秒。
两次更新之间的最终双倍时间=100000000/游戏赫兹;
//在新的渲染之前,我们最多会更新游戏很多次。
//如果您担心的是视觉障碍而不是完美的时机,请将此设置为1。
最终int MAX_在_RENDER=5之前更新_;
//我们需要最后的更新时间。
double lastUpdateTime=System.nanoTime();
//存储上次渲染的时间。
double lastRenderTime=System.nanoTime();
//如果我们能够获得如此高的FPS,请不要再次渲染。
最终双目标_FPS=60;
两次渲染之间的最终双目标时间=100000000/目标每秒;
//寻找FPS的简单方法。
int lastSecondTime=(int)(lastUpdateTime/100000000);
(跑步时)
{
double now=System.nanoTime();
int updateCount=0;
如果(!暂停)
{
//尽可能多地更新游戏,尽可能地赶上进度。
while(现在-lastUpdateTime>两次更新之间的时间&&updateCount两次更新之间的时间)
{
lastUpdateTime=now—两次更新之间的时间;
}
//为此,我们需要计算平滑渲染的插值。
浮点插值=Math.min(1.0f,(float)((now-lastUpdateTime)/两次更新之间的时间);
抽签游戏(插值);
lastRenderTime=现在;
//更新我们得到的帧。
int thissond=(int)(lastUpdateTime/100000000);
如果(thisSecond>lastSecondTime)
{
System.out.println(“新秒数”+此秒数+“”+帧数);
fps=帧数;
帧数=0;
lastSecondTime=此秒;
}
//在至少达到两次渲染之间的目标时间之前,都可以进行调整。这样可以避免占用CPU。
while(now-lastRenderTimeimport javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GameLoopTest extends JFrame implements ActionListener
{
   private GamePanel gamePanel = new GamePanel();
   private JButton startButton = new JButton("Start");
   private JButton quitButton = new JButton("Quit");
   private JButton pauseButton = new JButton("Pause");
   private boolean running = false;
   private boolean paused = false;
   private int fps = 60;
   private int frameCount = 0;
   public GameLoopTest()
   {
      super("Fixed Timestep Game Loop Test");
      Container cp = getContentPane();
      cp.setLayout(new BorderLayout());
      JPanel p = new JPanel();
      p.setLayout(new GridLayout(1,2));
      p.add(startButton);
      p.add(pauseButton);
      p.add(quitButton);
      cp.add(gamePanel, BorderLayout.CENTER);
      cp.add(p, BorderLayout.SOUTH);
      setSize(500, 500);
      startButton.addActionListener(this);
      quitButton.addActionListener(this);
      pauseButton.addActionListener(this);
   }
   public static void main(String[] args)
   {
      GameLoopTest glt = new GameLoopTest();
      glt.setVisible(true);
   }
   public void actionPerformed(ActionEvent e)
   {
      Object s = e.getSource();
      if (s == startButton)
      {
         running = !running;
         if (running)
         {
            startButton.setText("Stop");
            runGameLoop();
         }
         else
         {
            startButton.setText("Start");
         }
      }
      else if (s == pauseButton)
      {
        paused = !paused;
         if (paused)
         {
            pauseButton.setText("Unpause");
         }
         else
         {
            pauseButton.setText("Pause");
         }
      }
      else if (s == quitButton)
      {
         System.exit(0);
      }
   }
   //Starts a new thread and runs the game loop in it.
   public void runGameLoop()
   {
      Thread loop = new Thread()
      {
         public void run()
         {
            gameLoop();
         }
      };
      loop.start();
   }
   //Only run this in another Thread!
   private void gameLoop()
   {
      //This value would probably be stored elsewhere.
      final double GAME_HERTZ = 30.0;
      //Calculate how many ns each frame should take for our target game hertz.
      final double TIME_BETWEEN_UPDATES = 1000000000 / GAME_HERTZ;
      //At the very most we will update the game this many times before a new render.
      //If you're worried about visual hitches more than perfect timing, set this to 1.
      final int MAX_UPDATES_BEFORE_RENDER = 5;
      //We will need the last update time.
      double lastUpdateTime = System.nanoTime();
      //Store the last time we rendered.
      double lastRenderTime = System.nanoTime();
      //If we are able to get as high as this FPS, don't render again.
      final double TARGET_FPS = 60;
      final double TARGET_TIME_BETWEEN_RENDERS = 1000000000 / TARGET_FPS;
      //Simple way of finding FPS.
      int lastSecondTime = (int) (lastUpdateTime / 1000000000);
      while (running)
      {
         double now = System.nanoTime();
         int updateCount = 0;
         if (!paused)
         {
             //Do as many game updates as we need to, potentially playing catchup.
            while( now - lastUpdateTime > TIME_BETWEEN_UPDATES && updateCount < MAX_UPDATES_BEFORE_RENDER )
            {
               updateGame();
               lastUpdateTime += TIME_BETWEEN_UPDATES;
               updateCount++;
            }
            //If for some reason an update takes forever, we don't want to do an insane number of catchups.
            //If you were doing some sort of game that needed to keep EXACT time, you would get rid of this.
            if ( now - lastUpdateTime > TIME_BETWEEN_UPDATES)
            {
               lastUpdateTime = now - TIME_BETWEEN_UPDATES;
            }
            //Render. To do so, we need to calculate interpolation for a smooth render.
            float interpolation = Math.min(1.0f, (float) ((now - lastUpdateTime) / TIME_BETWEEN_UPDATES) );
            drawGame(interpolation);
            lastRenderTime = now;
            //Update the frames we got.
            int thisSecond = (int) (lastUpdateTime / 1000000000);
            if (thisSecond > lastSecondTime)
            {
               System.out.println("NEW SECOND " + thisSecond + " " + frameCount);
               fps = frameCount;
               frameCount = 0;
               lastSecondTime = thisSecond;
            }
            //Yield until it has been at least the target time between renders. This saves the CPU from hogging.
            while ( now - lastRenderTime < TARGET_TIME_BETWEEN_RENDERS && now - lastUpdateTime < TIME_BETWEEN_UPDATES)
            {
               Thread.yield();
               //This stops the app from consuming all your CPU. It makes this slightly less accurate, but is worth it.
               //You can remove this line and it will still work (better), your CPU just climbs on certain OSes.
               //FYI on some OS's this can cause pretty bad stuttering. Scroll down and have a look at different peoples' solutions to this.
               try {Thread.sleep(1);} catch(Exception e) {}
               now = System.nanoTime();
            }
         }
      }
   }
   private void updateGame()
   {
      gamePanel.update();
   }
   private void drawGame(float interpolation)
   {
      gamePanel.setInterpolation(interpolation);
      gamePanel.repaint();
   }
   private class GamePanel extends JPanel
   {
      float interpolation;
      float ballX, ballY, lastBallX, lastBallY;
      int ballWidth, ballHeight;
      float ballXVel, ballYVel;
      float ballSpeed;
      int lastDrawX, lastDrawY;
      public GamePanel()
      {
         ballX = lastBallX = 100;
         ballY = lastBallY = 100;
         ballWidth = 25;
         ballHeight = 25;
         ballSpeed = 25;
         ballXVel = (float) Math.random() * ballSpeed*2 - ballSpeed;
         ballYVel = (float) Math.random() * ballSpeed*2 - ballSpeed;
      }
      public void setInterpolation(float interp)
      {
         interpolation = interp;
      }
      public void update()
      {
         lastBallX = ballX;
         lastBallY = ballY;
         ballX += ballXVel;
         ballY += ballYVel;
         if (ballX + ballWidth/2 >= getWidth())
         {
            ballXVel *= -1;
            ballX = getWidth() - ballWidth/2;
            ballYVel = (float) Math.random() * ballSpeed*2 - ballSpeed;
         }
         else if (ballX - ballWidth/2 <= 0)
         {
            ballXVel *= -1;
            ballX = ballWidth/2;
         }
         if (ballY + ballHeight/2 >= getHeight())
         {
            ballYVel *= -1;
            ballY = getHeight() - ballHeight/2;
            ballXVel = (float) Math.random() * ballSpeed*2 - ballSpeed;
         }
         else if (ballY - ballHeight/2 <= 0)
         {
            ballYVel *= -1;
            ballY = ballHeight/2;
         }
      }
      public void paintComponent(Graphics g)
      {
         //BS way of clearing out the old rectangle to save CPU.
         g.setColor(getBackground());
         g.fillRect(lastDrawX-1, lastDrawY-1, ballWidth+2, ballHeight+2);
         g.fillRect(5, 0, 75, 30);
         g.setColor(Color.RED);
         int drawX = (int) ((ballX - lastBallX) * interpolation + lastBallX - ballWidth/2);
         int drawY = (int) ((ballY - lastBallY) * interpolation + lastBallY - ballHeight/2);
         g.fillOval(drawX, drawY, ballWidth, ballHeight);
         lastDrawX = drawX;
         lastDrawY = drawY;
         g.setColor(Color.BLACK);
         g.drawString("FPS: " + fps, 5, 10);
         frameCount++;
      }
   }
   private class Ball
   {
      float x, y, lastX, lastY;
      int width, height;
      float xVelocity, yVelocity;
      float speed;
      public Ball()
      {
         width = (int) (Math.random() * 50 + 10);
         height = (int) (Math.random() * 50 + 10);
         x = (float) (Math.random() * (gamePanel.getWidth() - width) + width/2);
         y = (float) (Math.random() * (gamePanel.getHeight() - height) + height/2);
         lastX = x;
         lastY = y;
         xVelocity = (float) Math.random() * speed*2 - speed;
         yVelocity = (float) Math.random() * speed*2 - speed;
      }
      public void update()
      {
         lastX = x;
         lastY = y;
         x += xVelocity;
         y += yVelocity;
         if (x + width/2 >= gamePanel.getWidth())
         {
            xVelocity *= -1;
            x = gamePanel.getWidth() - width/2;
            yVelocity = (float) Math.random() * speed*2 - speed;
         }
         else if (x - width/2 <= 0)
         {
            xVelocity *= -1;
            x = width/2;
         }
         if (y + height/2 >= gamePanel.getHeight())
         {
            yVelocity *= -1;
            y = gamePanel.getHeight() - height/2;
            xVelocity = (float) Math.random() * speed*2 - speed;
         }
         else if (y - height/2 <= 0)
         {
            yVelocity *= -1;
            y = height/2;
         }
      }
      public void draw(Graphics g)
      {
      }
   }
}
final Robot robot = new Robot();
javax.swing.Timer timer = new javax.swing.Timer(initialDelay, new ActionListener()
{
    public void actionPerformed(ActionEvent e)
    {
        // update your image...

        robot.keyPress(62);
     }
});