Training and Consulting | ||
| Home |
| Previous Page - JDK Support for Double Buffering | Current Page - 12 - Counting FPS | Next Page - Refactoring the code |
| Return to the index of free Java tutorials |
Counting FPSOne of the most fundamental aspects of any game is the speed with which we are able to "pump" graphics on the screen. It is worthless to have a fantastic ultr-realistic dungeon with a dragon featuring an IQ of 250 if we take five seconds to draw everything and perform all calculations (Well, we always have the choice of changing the genre of the game from "arcade" to "turn-based strategy", following the rule "it's not a bug, it's a feature!"). However we are designing an arcade and we'd like to stick to that. It's very easy to be carried away by the initial enthusiasm and start adding features on top of features and then in the final moment of truth, see in dispair that the game has become unplayable. For this reason it's imperative that as soon as possible we implement in our game a "frames per second" counter that will tell us how many times per second we can update and paint the world. We shouldn't, however, go to the other extreme becoming obsessed with the value of this counter. Visually, a 90 fps game is as smooth as a 1200 fps one. The reason is that if the monitor has a refresh rate of 100 Hz - in the best of the worlds - this would mean that in each second the electron beam refreshes the screen 100 times. It doesn't matter if our program during the same second has produced a thousand images, because the monitor will have had the time to show only 100 of them. There are many monitors that have refrsh rates of 50, 60 and 75 Hz, and in any case the eye is more than happy with 50 fps, so if our counter doesn't go below that amount, we shouldn't be excessively worried. The fps counter, however, is also a measure of the complexity we will be able to add in the future. For example, if we have a thousand critters moving all around and this gives us 77 fps, then it's a good indication that adding textures probably will drop the counter below the usability limit. How to calculate the fps? We simply take a look at the main game loop and calculate how much time we spend for each turn (without taking into account the artificial pause, which can be always removed should the need arise). For example, assume that we have calculated that a single turn takes 14 ms. Then 1000 / 14 = 71 fps. The Invaders class, with the new fps counter, becomes as follows:
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; 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);
Initially our main game loop takes less than 1 ms, so we can breathe in relief... However we shouldn't be confident as things will quite soon become more complex... |
||||||||
Do you want to be notified when new tutorials or lessons are published? Press here
| Invaders.java |
| Previous Page - JDK Support for Double Buffering | Current Page - 12 - Counting FPS | Next Page - Refactoring the code |
| Return to the index of free Java tutorials |
(c) 2004 Planetalia S.L. All rights reserved. Unauthorized reproduction and/or mirroring is not permitted