Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import javax.swing.*;
- import java.awt.event.*;
- import java.awt.*;
- public class gamePanel extends JPanel implements Runnable
- {
- private static long MAX_STATS_INTERVAL = 1000000000L;
- // private static long MAX_STATS_INTERVAL = 1000L;
- // record stats every 1 second (roughly)
- private static final int NO_DELAYS_PER_YIELD = 16;
- /* Number of frames with a delay of 0 ms before the animation thread yields
- to other running threads. */
- private static int MAX_FRAME_SKIPS = 5; // was 2;
- // no. of frames that can be skipped in any one animation loop
- // i.e the games state is updated but not rendered
- private static int NUM_FPS = 10;
- // number of FPS values stored to get an average
- private int pWidth, pHeight; // dimensions of the panel
- // used for gathering statistics
- private long statsInterval = 0L; // in ns
- private long prevStatsTime;
- private long totalElapsedTime = 0L;
- private long gameStartTime;
- private int timeSpentInGame = 0; // in seconds
- private long frameCount = 0;
- private double fpsStore[];
- private long statsCount = 0;
- private double averageFPS = 0.0;
- private long framesSkipped = 0L;
- private long totalFramesSkipped = 0L;
- private double upsStore[];
- private double averageUPS = 0.0;
- private Thread animator; // the thread that performs the animation
- private volatile boolean running = false; // used to stop the animation thread
- private volatile boolean isPaused = false;
- private long period; // period between drawing in _nanosecs_
- private Game wcTop;
- // used at game termination
- private volatile boolean gameOver = false;
- private int score = 0;
- private Font font;
- private FontMetrics metrics;
- // off screen rendering
- private Graphics dbg;
- private Image dbImage = null;
- World world;
- public gamePanel(Game wc, long period, int w, int h)
- {
- wcTop = wc;
- this.period = period;
- pWidth = w; pHeight = h;
- setBackground(Color.white);
- setPreferredSize( new Dimension(pWidth, pHeight));
- setFocusable(true);
- requestFocus(); // the JPanel now has focus, so receives key events
- buttonListener();
- // create game components
- world=new World(w,h);
- gameOver = false;
- addMouseListener( new MouseAdapter() {
- public void mousePressed(MouseEvent e)
- { testPress(e.getX(), e.getY()); }
- });
- // set up message font
- font = new Font("SansSerif", Font.BOLD, 24);
- metrics = this.getFontMetrics(font);
- // initialise timing elements
- fpsStore = new double[NUM_FPS];
- upsStore = new double[NUM_FPS];
- for (int i=0; i < NUM_FPS; i++) {
- fpsStore[i] = 0.0;
- upsStore[i] = 0.0;
- }
- } // end of WormPanel()
- private void buttonListener()
- {
- addKeyListener( new KeyAdapter() {
- // listen for esc, q, end, ctrl-c on the canvas to
- // allow a convenient exit from the full screen configuration
- public void keyPressed(KeyEvent e)
- { int keyCode = e.getKeyCode();
- if ((keyCode == KeyEvent.VK_ESCAPE) || (keyCode == KeyEvent.VK_Q) ||
- (keyCode == KeyEvent.VK_END) ||
- ((keyCode == KeyEvent.VK_C) && e.isControlDown()) ) {
- running = false;
- }//end if
- else{
- world.moveCamera(keyCode);
- }
- }
- });
- } // end of readyForTermination()
- public void addNotify()
- // only start the animation once the JPanel has been added to the JFrame
- { super.addNotify(); // creates the peer
- startGame(); // start the thread
- }
- private void startGame()
- // initialise and start the thread
- { if (animator == null || !running) {
- animator = new Thread(this);
- animator.start();
- }
- }
- // ------------- game life cycle methods ------------
- // called by the JFrame's window listener methods
- public void resumeGame()
- // called when the JFrame is activated / deiconified
- { isPaused = false; }
- public void pauseGame()
- // called when the JFrame is deactivated / iconified
- { isPaused = true; }
- public void stopGame()
- // called when the JFrame is closing
- { running = false; }
- // ----------------------------------------------
- private void testPress(int x, int y)
- {
- } // end of testPress()
- public void run()
- /* The frames of the animation are drawn inside the while loop. */
- {
- long beforeTime, afterTime, timeDiff, sleepTime;
- long overSleepTime = 0L;
- int noDelays = 0;
- long excess = 0L;
- Graphics g;
- //gameStartTime = J3DTimer.getValue();
- gameStartTime=System.currentTimeMillis();
- prevStatsTime = gameStartTime;
- beforeTime = gameStartTime;
- running = true;
- while(running) {
- gameUpdate();
- gameRender(); // render the game to a buffer
- paintScreen(); // draw the buffer on-screen
- //afterTime = J3DTimer.getValue();
- afterTime=System.currentTimeMillis();
- timeDiff = afterTime - beforeTime;
- sleepTime = (period - timeDiff) - overSleepTime;
- if (sleepTime > 0) { // some time left in this cycle
- try {
- Thread.sleep(sleepTime/1000000L); // nano -> ms
- }
- catch(InterruptedException ex){}
- //overSleepTime = (J3DTimer.getValue() - afterTime) - sleepTime;
- overSleepTime = (System.currentTimeMillis() - afterTime) - sleepTime;
- }
- else { // sleepTime <= 0; the frame took longer than the period
- excess -= sleepTime; // store excess time value
- overSleepTime = 0L;
- if (++noDelays >= NO_DELAYS_PER_YIELD) {
- Thread.yield(); // give another thread a chance to run
- noDelays = 0;
- }
- }
- //beforeTime = J3DTimer.getValue();
- beforeTime = System.currentTimeMillis();
- /* If frame animation is taking too long, update the game state
- without rendering it, to get the updates/sec nearer to
- the required FPS. */
- int skips = 0;
- while((excess > period) && (skips < MAX_FRAME_SKIPS)) {
- excess -= period;
- gameUpdate(); // update state but don't render
- skips++;
- }
- framesSkipped += skips;
- storeStats();
- }
- printStats();
- System.exit(0); // so window disappears
- } // end of run()
- private void gameUpdate()
- { if (!isPaused && !gameOver){}
- } // end of gameUpdate()
- private void gameRender()
- {
- if (dbImage == null){
- dbImage = createImage(pWidth, pHeight);
- if (dbImage == null) {
- System.out.println("dbImage is null");
- return;
- }
- else
- dbg = dbImage.getGraphics();
- }
- // clear the background
- dbg.setColor(Color.white);
- dbg.fillRect(0, 0, pWidth, pHeight);
- dbg.setColor(Color.blue);
- dbg.setFont(font);
- // report frame count & average FPS and UPS at top left
- // dbg.drawString("Frame Count " + frameCount, 10, 25);
- dbg.drawString("Average FPS/UPS: "+(int)(averageFPS) + ", " +
- (int)(averageUPS), 20, 25); // was (10,55)
- dbg.setColor(Color.black);
- // draw game elements: the obstacles and the worm
- //obs.draw(dbg);
- //fred.draw(dbg);
- world.draw(dbg);
- if (gameOver)
- gameOverMessage(dbg);
- } // end of gameRender()
- private void gameOverMessage(Graphics g)
- // center the game-over message in the panel
- {
- String msg = "Game Over. Your Score: " + score;
- int x = (pWidth - metrics.stringWidth(msg))/2;
- int y = (pHeight - metrics.getHeight())/2;
- g.setColor(Color.red);
- g.setFont(font);
- g.drawString(msg, x, y);
- } // end of gameOverMessage()
- private void paintScreen()
- // use active rendering to put the buffered image on-screen
- {
- Graphics g;
- try {
- g = this.getGraphics();
- if ((g != null) && (dbImage != null))
- g.drawImage(dbImage, 0, 0, null);
- // Sync the display on some systems.
- // (on Linux, this fixes event queue problems)
- Toolkit.getDefaultToolkit().sync();
- g.dispose();
- }
- catch (Exception e) // quite commonly seen at applet destruction
- { System.out.println("Graphics error: " + e); }
- } // end of paintScreen()
- private void storeStats() {
- frameCount++;
- statsInterval += period;
- if (statsInterval >= MAX_STATS_INTERVAL) { // record stats every MAX_STATS_INTERVAL
- //long timeNow = J3DTimer.getValue();
- long timeNow=System.currentTimeMillis();
- timeSpentInGame = (int) ((timeNow - gameStartTime)/1000000000L); // ns --> secs
- wcTop.setTimeSpent( timeSpentInGame );
- long realElapsedTime = timeNow - prevStatsTime; // time since last stats collection
- totalElapsedTime += realElapsedTime;
- double timingError =
- ((double)(realElapsedTime - statsInterval) / statsInterval) * 100.0;
- totalFramesSkipped += framesSkipped;
- double actualFPS = 0; // calculate the latest FPS and UPS
- double actualUPS = 0;
- if (totalElapsedTime > 0) {
- actualFPS = (((double)frameCount / totalElapsedTime) * 1000000000L);
- actualUPS = (((double)(frameCount + totalFramesSkipped) / totalElapsedTime)
- * 1000000000L);
- }
- // store the latest FPS and UPS
- fpsStore[ (int)statsCount%NUM_FPS ] = actualFPS;
- upsStore[ (int)statsCount%NUM_FPS ] = actualUPS;
- statsCount = statsCount+1;
- double totalFPS = 0.0; // total the stored FPSs and UPSs
- double totalUPS = 0.0;
- for (int i=0; i < NUM_FPS; i++) {
- totalFPS += fpsStore[i];
- totalUPS += upsStore[i];
- }
- if (statsCount < NUM_FPS) { // obtain the average FPS and UPS
- averageFPS = totalFPS/statsCount;
- averageUPS = totalUPS/statsCount;
- }
- else {
- averageFPS = totalFPS/NUM_FPS;
- averageUPS = totalUPS/NUM_FPS;
- }
- /*
- System.out.println(timedf.format( (double) statsInterval/1000000000L) + " " +
- timedf.format((double) realElapsedTime/1000000000L) + "s " +
- df.format(timingError) + "% " +
- frameCount + "c " +
- framesSkipped + "/" + totalFramesSkipped + " skip; " +
- df.format(actualFPS) + " " + df.format(averageFPS) + " afps; " +
- df.format(actualUPS) + " " + df.format(averageUPS) + " aups" );
- */
- framesSkipped = 0;
- prevStatsTime = timeNow;
- statsInterval = 0L; // reset
- }
- } // end of storeStats()
- private void printStats()
- {
- System.out.println("Frame Count/Loss: " + frameCount + " / " + totalFramesSkipped);
- System.out.println("Average FPS: " + (int)averageFPS);
- System.out.println("Average UPS: " + (int)(averageUPS));
- System.out.println("Time Spent: " + timeSpentInGame + " secs");
- // System.out.println("Boxes used: " + obs.getNumObstacles());
- } // end of printStats()
- } // end of WormPanel class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement