Planetalia - Cursos

Cursos y Másters

Inicio    Profesores    Aulas    Testimonios    Cursos    Masters    Tecnologías    Cursos Gratuitos    Solicitar Información    Ofertas de Empleo   

Curso - Programación de un Space Invaders en Java

  Página Anterior - Doble Búfer automático Página Actual - 12 - Medición del rendimiento   Página Siguiente - Reorganización del código Java
  Índice de cursos Java gratuitos  

Medición del rendimiento

(c) Alexander Hristov

Uno de los aspectos fundamentales de cualquier juego es la velocidad con la que es capaz de dibujar el escenario. De nada sirve que el juego sea maravilloso si el dibujo de la mazmorra tarda 2 segundos (aunque siempre cabe la opción de cambiar la denominación de arcade a "juego de estrategia por turnos"). Es muy fácil al principio dejarse llevar por el entusiasmo y comenzar a añadir opciones y más opciones a nuestro juego, con gráficos cada vez más complicados y grandes y al final encontrarse con que el redibujo del escenario se ha convertido en algo tan lento que ya no es jugable

Por este motivo es fundamental que lo antes posible implementemos en nuestro juego un contador de "fotogramas por segundo" - los famosos frames per second (fps) que nos diga cuántas veces por segundo somos capaces de dibujar el escenario. Sin embargo, no tenemos tampoco que obsesionarnos con el valor de este contador.

Visualmente, un juego a 90 fps es exactamente igual de suave que uno de 1200 fps. El motivo es muy sencillo y es que si el monitor es de 100 Hz - en el mejor de los casos - eso significará que en un segundo hace cien barridos de la pantalla. Da igual si en ese tiempo nuestro programa ha actualizado el escenario mil veces, porque al monitor sólo le ha dado tiempo a presentar uno. Hay una gran mayoría de monitores que funcionan a 50, 60 y 75 Hz, y en cualquier caso al ojo le es suficiente con 50 fps, con lo cual si nuestro contador no baja de esa cifra, no deberíamos precuparnos en exceso. Sin embargo, debemos ser conscientes de que el número de fotogramas por segundo limita seriamente las ampliaciones que seremos capaces de hacer en el futuro. Si tenemos mil bichos moviéndose simultáneamente en la pantalla y ello nos lleva a 77 fps, entonces es poco probable que consigamos añadir texturas desplazándose en el fondo sin que caigamos por debajo del umbral de usabilidad

¿Cómo calcular los fps? Simplemente miramos el bucle principal del juego y examinamos cuanto tiempo tarda en realizarse un turno - con todos sus cambios, actualizaciones, dibujos, etc... Supongamos que obtenemos una cierta cantidad de milisegundos. Ahora dividimos 1000 (1 segundo) por la cantidad calculada y obtenemos los fps. Por ejemplo, si el cuerpo de nuestro bucle tarda 14Invaders.java ms (sin contar con la pausa, que es totalmente artificial y se puede reducir o incluso eliminar), entonces estaríamos proporcionando 71 fps.

Con nuestro contador fps, el programa queda así:


1     package version12;
2     /**
3      * Curso B?sico de desarrollo de Juegos en Java - Invaders
4      * 
5      * (c) 2004 Planetalia S.L. - Todos los derechos reservados. Prohibida su reproducci?n
6      * 
7      * http://www.planetalia.com
8      * 
9      */
10    
11    
12    import java.awt.Canvas;
13    import java.awt.Color;
14    import java.awt.Dimension;
15    import java.awt.Graphics;
16    import java.awt.event.WindowAdapter;
17    import java.awt.event.WindowEvent;
18    import java.awt.image.BufferStrategy;
19    import java.awt.image.BufferedImage;
20    import java.net.URL;
21    import java.util.HashMap;
22    
23    import javax.imageio.ImageIO;
24    import javax.swing.JFrame;
25    import javax.swing.JPanel;
26    
27    public class Invaders extends Canvas {
28      public static final int WIDTH = 640;
29      public static final int HEIGHT = 480;
30      public static final int SPEED = 10;
31      
32      public BufferStrategy strategy;
33      public HashMap sprites;
34      public int posX,posY,vX;
35 public long usedTime;
36 37 public Invaders() { 38 sprites = new HashMap(); 39 posX = WIDTH/2; 40 posY = HEIGHT/2; 41 vX = 2; 42 43 JFrame ventana = new JFrame("Invaders"); 44 JPanel panel = (JPanel)ventana.getContentPane(); 45 setBounds(0,0,WIDTH,HEIGHT); 46 panel.setPreferredSize(new Dimension(WIDTH,HEIGHT)); 47 panel.setLayout(null); 48 panel.add(this); 49 ventana.setBounds(0,0,WIDTH,HEIGHT); 50 ventana.setVisible(true); 51 ventana.addWindowListener( new WindowAdapter() { 52 public void windowClosing(WindowEvent e) { 53 System.exit(0); 54 } 55 }); 56 ventana.setResizable(false); 57 createBufferStrategy(2); 58 strategy = getBufferStrategy(); 59 requestFocus(); 60 } 61 62 public BufferedImage loadImage(String nombre) { 63 URL url=null; 64 try { 65 url = getClass().getClassLoader().getResource(nombre); 66 return ImageIO.read(url); 67 } catch (Exception e) { 68 System.out.println("No se pudo cargar la imagen " + nombre +" de "+url); 69 System.out.println("El error fue : "+e.getClass().getName()+" "+e.getMessage()); 70 System.exit(0); 71 return null; 72 } 73 } 74 75 public BufferedImage getSprite(String nombre) { 76 BufferedImage img = (BufferedImage)sprites.get(nombre); 77 if (img == null) { 78 img = loadImage("res/"+nombre); 79 sprites.put(nombre,img); 80 } 81 return img; 82 } 83 84 public void paintWorld() { 85 Graphics g = strategy.getDrawGraphics(); 86 g.setColor(Color.black); 87 g.fillRect(0,0,getWidth(),getHeight()); 88 g.drawImage(getSprite("bicho.gif"), posX, posY,this); 89 90 g.setColor(Color.white);
91 if (usedTime > 0) 92 g.drawString(String.valueOf(1000/usedTime)+" fps",0,HEIGHT-50); 93 else 94 g.drawString("--- fps",0,HEIGHT-50);
95 strategy.show(); 96 } 97 98 99 100 public void updateWorld() { 101 posX += vX; 102 if (posX < 0 || posX > WIDTH) vX = -vX; 103 } 104 105 public void game() {
106 usedTime=1000; 107 while (isVisible()) { 108 long startTime = System.currentTimeMillis(); 109 updateWorld(); 110 paintWorld(); 111 usedTime = System.currentTimeMillis()-startTime;
112 try { 113 Thread.sleep(SPEED); 114 } catch (InterruptedException e) {} 115 } 116 } 117 118 public static void main(String[] args) { 119 Invaders inv = new Invaders(); 120 inv.game(); 121 } 122 } 123

Curso Space Invaders en Java

Inicialmente el cuerpo tarda tan poco (menos de 1 ms), así que podemos estar tranquilos. Sin embargo, esto no debe hacer que nos confiemos puesto que en seguida veremos que las cosas se van a ir complicando a medida que añadamos más funcionalidad a nuestro juego



¿Quieres ser notificado cuando salan nuevos tutoriales y cursos?. Pulsa aquí


Lista de archivos Java del programa en este paso

Invaders.java      

Lista de recursos

bicho.gif bicho0.gif bicho1.gif bicho2.gif
bombD.gif bombDL.gif bombDR.gif bombL.gif
bombR.gif bombU.gif bombUL.gif bombUR.gif
disparo.gif disparo0.gif disparo1.gif disparo2.gif
explosion.wav misil.gif missile.wav musica.wav
nave.gif oceano.gif photon.wav test.gif
Thumbs.db      

  Página Anterior - Doble Búfer automático Página Actual - 12 - Medición del rendimiento   Página Siguiente - Reorganización del código Java
  Índice de cursos Java gratuitos  

(c) 2004 Planetalia S.L. Todos los derechos reservados. Prohibida su reproducción