Advertisement
Guest User

Untitled

a guest
Sep 8th, 2013
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.55 KB | None | 0 0
  1. import javax.swing.*;
  2. import java.awt.*;
  3. import java.awt.event.*;
  4.  
  5. public class GameLoopTest extends JFrame implements ActionListener
  6. {
  7.    private GamePanel gamePanel = new GamePanel();
  8.    private JButton startButton = new JButton("Start");
  9.    private JButton quitButton = new JButton("Quit");
  10.    private JButton pauseButton = new JButton("Pause");
  11.    private boolean running = false;
  12.    private boolean paused = false;
  13.    private int fps = 60;
  14.    private int frameCount = 0;
  15.    
  16.    public GameLoopTest()
  17.    {
  18.       super("Fixed Timestep Game Loop Test");
  19.       Container cp = getContentPane();
  20.       cp.setLayout(new BorderLayout());
  21.       JPanel p = new JPanel();
  22.       p.setLayout(new GridLayout(1,2));
  23.       p.add(startButton);
  24.       p.add(pauseButton);
  25.       p.add(quitButton);
  26.       cp.add(gamePanel, BorderLayout.CENTER);
  27.       cp.add(p, BorderLayout.SOUTH);
  28.       setSize(500, 500);
  29.      
  30.       startButton.addActionListener(this);
  31.       quitButton.addActionListener(this);
  32.       pauseButton.addActionListener(this);
  33.    }
  34.    
  35.    public static void main(String[] args)
  36.    {
  37.       GameLoopTest glt = new GameLoopTest();
  38.       glt.setVisible(true);
  39.    }
  40.    
  41.    public void actionPerformed(ActionEvent e)
  42.    {
  43.       Object s = e.getSource();
  44.       if (s == startButton)
  45.       {
  46.          running = !running;
  47.          if (running)
  48.          {
  49.             startButton.setText("Stop");
  50.             runGameLoop();
  51.          }
  52.          else
  53.          {
  54.             startButton.setText("Start");
  55.          }
  56.       }
  57.       else if (s == pauseButton)
  58.       {
  59.         paused = !paused;
  60.          if (paused)
  61.          {
  62.             pauseButton.setText("Unpause");
  63.          }
  64.          else
  65.          {
  66.             pauseButton.setText("Pause");
  67.          }
  68.       }
  69.       else if (s == quitButton)
  70.       {
  71.          System.exit(0);
  72.       }
  73.    }
  74.    
  75.    //Starts a new thread and runs the game loop in it.
  76.    public void runGameLoop()
  77.    {
  78.       Thread loop = new Thread()
  79.       {
  80.          public void run()
  81.          {
  82.             gameLoop();
  83.          }
  84.       };
  85.       loop.start();
  86.    }
  87.    
  88.    //Only run this in another Thread!
  89.    private void gameLoop()
  90.    {
  91.       //This value would probably be stored elsewhere.
  92.       final double GAME_HERTZ = 30.0;
  93.       //Calculate how many ns each frame should take for our target game hertz.
  94.       final double TIME_BETWEEN_UPDATES = 1000000000 / GAME_HERTZ;
  95.       //At the very most we will update the game this many times before a new render.
  96.       //If you're worried about visual hitches more than perfect timing, set this to 1.
  97.       final int MAX_UPDATES_BEFORE_RENDER = 5;
  98.       //We will need the last update time.
  99.       double lastUpdateTime = System.nanoTime();
  100.       //Store the last time we rendered.
  101.       double lastRenderTime = System.nanoTime();
  102.      
  103.       //If we are able to get as high as this FPS, don't render again.
  104.       final double TARGET_FPS = 60;
  105.       final double TARGET_TIME_BETWEEN_RENDERS = 1000000000 / TARGET_FPS;
  106.      
  107.       //Simple way of finding FPS.
  108.       int lastSecondTime = (int) (lastUpdateTime / 1000000000);
  109.      
  110.       while (running)
  111.       {
  112.          double now = System.nanoTime();
  113.          int updateCount = 0;
  114.          
  115.          if (!paused)
  116.          {
  117.              //Do as many game updates as we need to, potentially playing catchup.
  118.             while( now - lastUpdateTime > TIME_BETWEEN_UPDATES && updateCount < MAX_UPDATES_BEFORE_RENDER )
  119.             {
  120.                updateGame();
  121.                lastUpdateTime += TIME_BETWEEN_UPDATES;
  122.                updateCount++;
  123.             }
  124.    
  125.             //If for some reason an update takes forever, we don't want to do an insane number of catchups.
  126.             //If you were doing some sort of game that needed to keep EXACT time, you would get rid of this.
  127.             if ( now - lastUpdateTime > TIME_BETWEEN_UPDATES)
  128.             {
  129.                lastUpdateTime = now - TIME_BETWEEN_UPDATES;
  130.             }
  131.          
  132.             //Render. To do so, we need to calculate interpolation for a smooth render.
  133.             float interpolation = Math.min(1.0f, (float) ((now - lastUpdateTime) / TIME_BETWEEN_UPDATES) );
  134.             drawGame(interpolation);
  135.             lastRenderTime = now;
  136.          
  137.             //Update the frames we got.
  138.             int thisSecond = (int) (lastUpdateTime / 1000000000);
  139.             if (thisSecond > lastSecondTime)
  140.             {
  141.                System.out.println("NEW SECOND " + thisSecond + " " + frameCount);
  142.                fps = frameCount;
  143.                frameCount = 0;
  144.                lastSecondTime = thisSecond;
  145.             }
  146.          
  147.             //Yield until it has been at least the target time between renders. This saves the CPU from hogging.
  148.             while ( now - lastRenderTime < TARGET_TIME_BETWEEN_RENDERS && now - lastUpdateTime < TIME_BETWEEN_UPDATES)
  149.             {
  150.                Thread.yield();
  151.            
  152.                //This stops the app from consuming all your CPU. It makes this slightly less accurate, but is worth it.
  153.                //You can remove this line and it will still work (better), your CPU just climbs on certain OSes.
  154.                //FYI on some OS's this can cause pretty bad stuttering. Scroll down and have a look at different peoples' solutions to this.
  155.                try {Thread.sleep(1);} catch(Exception e) {}
  156.            
  157.                now = System.nanoTime();
  158.             }
  159.          }
  160.       }
  161.    }
  162.    
  163.    private void updateGame()
  164.    {
  165.       gamePanel.update();
  166.    }
  167.    
  168.    private void drawGame(float interpolation)
  169.    {
  170.       gamePanel.setInterpolation(interpolation);
  171.       gamePanel.repaint();
  172.    }
  173.    
  174.    private class GamePanel extends JPanel
  175.    {
  176.       float interpolation;
  177.       float ballX, ballY, lastBallX, lastBallY;
  178.       int ballWidth, ballHeight;
  179.       float ballXVel, ballYVel;
  180.       float ballSpeed;
  181.      
  182.       int lastDrawX, lastDrawY;
  183.      
  184.       public GamePanel()
  185.       {
  186.          ballX = lastBallX = 100;
  187.          ballY = lastBallY = 100;
  188.          ballWidth = 25;
  189.          ballHeight = 25;
  190.          ballSpeed = 25;
  191.          ballXVel = (float) Math.random() * ballSpeed*2 - ballSpeed;
  192.          ballYVel = (float) Math.random() * ballSpeed*2 - ballSpeed;
  193.       }
  194.      
  195.       public void setInterpolation(float interp)
  196.       {
  197.          interpolation = interp;
  198.       }
  199.      
  200.       public void update()
  201.       {
  202.          lastBallX = ballX;
  203.          lastBallY = ballY;
  204.          
  205.          ballX += ballXVel;
  206.          ballY += ballYVel;
  207.          
  208.          if (ballX + ballWidth/2 >= getWidth())
  209.          {
  210.             ballXVel *= -1;
  211.             ballX = getWidth() - ballWidth/2;
  212.             ballYVel = (float) Math.random() * ballSpeed*2 - ballSpeed;
  213.          }
  214.          else if (ballX - ballWidth/2 <= 0)
  215.          {
  216.             ballXVel *= -1;
  217.             ballX = ballWidth/2;
  218.          }
  219.          
  220.          if (ballY + ballHeight/2 >= getHeight())
  221.          {
  222.             ballYVel *= -1;
  223.             ballY = getHeight() - ballHeight/2;
  224.             ballXVel = (float) Math.random() * ballSpeed*2 - ballSpeed;
  225.          }
  226.          else if (ballY - ballHeight/2 <= 0)
  227.          {
  228.             ballYVel *= -1;
  229.             ballY = ballHeight/2;
  230.          }
  231.       }
  232.      
  233.       public void paintComponent(Graphics g)
  234.       {
  235.          //BS way of clearing out the old rectangle to save CPU.
  236.          g.setColor(getBackground());
  237.          g.fillRect(lastDrawX-1, lastDrawY-1, ballWidth+2, ballHeight+2);
  238.          g.fillRect(5, 0, 75, 30);
  239.          
  240.          g.setColor(Color.RED);
  241.          int drawX = (int) ((ballX - lastBallX) * interpolation + lastBallX - ballWidth/2);
  242.          int drawY = (int) ((ballY - lastBallY) * interpolation + lastBallY - ballHeight/2);
  243.          g.fillOval(drawX, drawY, ballWidth, ballHeight);
  244.          
  245.          lastDrawX = drawX;
  246.          lastDrawY = drawY;
  247.          
  248.          g.setColor(Color.BLACK);
  249.          g.drawString("FPS: " + fps, 5, 10);
  250.          
  251.          frameCount++;
  252.       }
  253.    }
  254.    
  255.    private class Ball
  256.    {
  257.       float x, y, lastX, lastY;
  258.       int width, height;
  259.       float xVelocity, yVelocity;
  260.       float speed;
  261.      
  262.       public Ball()
  263.       {
  264.          width = (int) (Math.random() * 50 + 10);
  265.          height = (int) (Math.random() * 50 + 10);
  266.          x = (float) (Math.random() * (gamePanel.getWidth() - width) + width/2);
  267.          y = (float) (Math.random() * (gamePanel.getHeight() - height) + height/2);
  268.          lastX = x;
  269.          lastY = y;
  270.          xVelocity = (float) Math.random() * speed*2 - speed;
  271.          yVelocity = (float) Math.random() * speed*2 - speed;
  272.       }
  273.      
  274.       public void update()
  275.       {
  276.          lastX = x;
  277.          lastY = y;
  278.          
  279.          x += xVelocity;
  280.          y += yVelocity;
  281.          
  282.          if (x + width/2 >= gamePanel.getWidth())
  283.          {
  284.             xVelocity *= -1;
  285.             x = gamePanel.getWidth() - width/2;
  286.             yVelocity = (float) Math.random() * speed*2 - speed;
  287.          }
  288.          else if (x - width/2 <= 0)
  289.          {
  290.             xVelocity *= -1;
  291.             x = width/2;
  292.          }
  293.          
  294.          if (y + height/2 >= gamePanel.getHeight())
  295.          {
  296.             yVelocity *= -1;
  297.             y = gamePanel.getHeight() - height/2;
  298.             xVelocity = (float) Math.random() * speed*2 - speed;
  299.          }
  300.          else if (y - height/2 <= 0)
  301.          {
  302.             yVelocity *= -1;
  303.             y = height/2;
  304.          }
  305.       }
  306.      
  307.       public void draw(Graphics g)
  308.       {
  309.          
  310.       }
  311.    }
  312. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement