Ahora trabajeremos sobre una pantalla que no tiene barra de titulo ni cajas de texto, entonces para poder salir haremos botones de pausa y salida del juego.
La clase worm Chase ya no necesitara de WindowListener es por eso que las funciones pauseGame(), resumeGame(), o stopGame() ya no seran requeridos.
2.1. The WormChase Class
Se reduce bastante el codigo que se usa en esta clase.
public WormChase(long period) { super("The Worm Chase"); Container c = getContentPane(); c.setLayout( new BorderLayout() ); WormPanel wp = new WormPanel(this, period); c.add(wp, "Center"); setUndecorated(true); // no hay bordes ni barra de titulo setIgnoreRepaint(true); // apaga todos los eventis de pintado ya que //habra renderizado activamente pack(); setResizable(false); setVisible(true); } // fin de WormChase() // ----------------------------------------- public static void main(String args[]) { int fps = DEFAULT_FPS; if (args.length != 0) fps = Integer.parseInt(args[0]); long period = (long) 1000.0/fps; System.out.println("fps: " + fps + "; period: " + period + " ms"); new WormChase(period*1000000L); // ms --> nanosecs } } // fin de la clase WormChase
setIgnoreRepaint() es utilizado ya que no existe ningun componente GUI, y no se becesitaran eventos de pintado
2.2. The WormPanel Class
El constructor de WormPanel pone el tamaño de la pantalla y guarda las dimensiones en las globales pWidth y pHeight
Toolkit tk = Toolkit.getDefaultToolkit(); Dimension scrDim = tk.getScreenSize(); setPreferredSize(scrDim);// pone el tamaño al panel pWidth = scrDim.width;// guarda las dimensiones para despues pHeight = scrDim.height;
El constructor crea 2 rectangulos, llamados pauseArea y quitArea, el dibujo de estos se describe abajo:
private Rectangle pauseArea, quitArea; // globales // en WormPanel() // especifica las areas en pantalla para los botones pauseArea = new Rectangle(pWidth-100, pHeight-45, 70, 15); quitArea = new Rectangle(pWidth-100, pHeight-20, 70, 15);
2.3. Button Behaviour
Para darle una mejoria a los botones, le vamos a dar efectos, por ejemplo cuando pase sobre los botones se pondra verde y cuando el juego este pausado el boton se va a llamar “paused” para esto:
addMouseMotionListener( new MouseMotionAdapter() { public void mouseMoved(MouseEvent e) { testMove(e.getX(), e.getY()); } }); - - - private void testMove(int x, int y) // esta (x,y) encima de los obtones de pausa o salida? { if (running) { // para los problemas con un movimiento rapido despues //de presionar "quit" isOverPauseButton = pauseArea.contains(x,y) ? true : false; isOverQuitButton = quitArea.contains(x,y) ? true : false; } }
Ahora tenemos que definir como lidiar con el click del mouse si choca con un boton, extendermos testPress para esto:
// en el constructor WormPanel addMouseListener( new MouseAdapter() { public void mousePressed(MouseEvent e) { testPress(e.getX(), e.getY()); } }); : private void testPress(int x, int y) { if (isOverPauseButton) isPaused = !isPaused; else if (isOverQuitButton) running = false; else { if (!isPaused && !gameOver) { //presionaron el mouse erca de la cabeza? . . . } } }
2.4. Drawing the Game Canvas
Hay nuevos elementos, la info del tiempo y las cajas ahora sera dibujada en la parte de abjo, y los botones de pausa y salida. todo esto se implementa en gamerender()
private void gameRender() { if (dbImage == null){ dbImage = createImage(pWidth, pHeight); if (dbImage == null) { System.out.println("dbImage is null"); return; } else dbg = dbImage.getGraphics(); } // limpia el background dbg.setColor(Color.white); dbg.fillRect(0, 0, pWidth, pHeight); dbg.setColor(Color.blue); dbg.setFont(font); //En la esquina izquierda se hara un conteo y promedio de FPS y UPS dbg.drawString("Average FPS/UPS: " + df.format(averageFPS) + ", " + df.format(averageUPS), 20, 25); // was (10,55) // reporta el tiempo y cajas usadas en la esquina de abajo a la izquierda dbg.drawString("Time Spent: " + timeSpentInGame + " secs", 10, pHeight-15); dbg.drawString("Boxes used: " + boxesUsed, 260, pHeight-15); // Dibuja los botones de pausa y salida drawButtons(dbg); dbg.setColor(Color.black); // dibuja los elementos del juego obs.draw(dbg); fred.draw(dbg); if (gameOver) gameOverMessage(dbg); } // fin de gameRender() - - - private void drawButtons(Graphics g) { g.setColor(Color.black); // dibujar el boton de pausa if (isOverPauseButton) g.setColor(Color.green); g.drawOval( pauseArea.x, pauseArea.y, pauseArea.width, pauseArea.height); if (isPaused) g.drawString("Paused", pauseArea.x, pauseArea.y+10); else g.drawString("Pause", pauseArea.x+5, pauseArea.y+10); if (isOverPauseButton) g.setColor(Color.black); // dibujar el boton de salida if (isOverQuitButton) g.setColor(Color.green); g.drawOval(quitArea.x, quitArea.y, quitArea.width, quitArea.height); g.drawString("Quit", quitArea.x+15, quitArea.y+10); if (isOverQuitButton) g.setColor(Color.black); } // dibujar los botones
2.5. Exiting the Game
se crea un nuevo metodo:
private void finishOff() { if (!finishedOff) { finishedOff = true; printStats(); System.exit(0); } }
Hay un codigo que nos permite hacer los reportes de las estadisticas aun si el programa fue terminado inesperaamente, esta funcion es critica por ejemplo si necesitas que se guarde algo antes de que salga del programa.
Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { running = false; System.out.println("Shutdown hook executed"); finishOff(); } });
2.6. Timings for UFS
Las estadisticas de UFS