Planetalia - Java Training

Training and Consulting

Home

Tutorial - Writing a Space Invaders game in Java

  Previous Page - Frames Current Page - 15 - Frames - II   Next Page - The Player
  Return to the index of free Java tutorials  

Frames - II

(c) Alexander Hristov

In our previous version, we managed to add frames to all the critters, but the frames change so quickly that we don't have time to see them. Si tenemos un ordenador suficientemente rápido, los fotogramas del programa anterior avanzan a una velocidad excesiva y apenas da tiempo a verlos como fotogramas diferenciados. Sin embargo, la frecuencia con la que se llama al método act() es algo que es general para todo el juego y no podemos variarlo para cada caso individual

We can borrow a possible solution from the world of electronics - we can introduce a time base. Using this idea, the main loop sleeps for a period of time that is the biggest common divisor of the intervals required by the rest of the actors. For example, let's imagine that we have a game in which monsters move once per second, the player moves twice per second and we have a volcano that erupts once every 10 seconds. This means that each one of these entities get a turn each 1,0.5 an 10 seconds respectively. The greatest common divisor of these numbers is 0.5, which means that the main game loop should sleep 0.5 seconds, and this number is called the time base. All other intervals in the game are expressed using this number. For example, if some entity needs to do something every 4 seconds, it counts 4/0.5 = 8 "ticks" of the time counter.

Inside the main loop, every time we wake up from Thread.sleep, we increment a sequential counter which represents the "current time". Whenever this counter is divisible by the appropriate amount, the entity gets a turn. For our example, these quantities would be

  • Player - Gets a turn every time ( 0.5 / 0.5 = 1 )
  • Monstruo - Moves each second, or each 2 units of time. Thus, gets a turn every time the counter is divisible by 2
  • Volacno - Erupts each 10 seconds, or each 20 units of time. Thus, gets a turn every time the counter is divisible by 20

We can apply the same idea to the frames : we can define a time counter inside the Actor class and update the current frame only when this counter is divisible by a certain "frame speed":


1     /**
2      * Curso B?sico de desarrollo de Juegos en Java - Invaders
3      * 
4      * (c) 2004 Planetalia S.L. - Todos los derechos reservados. Prohibida su reproducci?n
5      * 
6      * http://www.planetalia.com
7      * 
8      */
9     package version15;
10    
11    import java.awt.Graphics2D;
12    import java.awt.image.BufferedImage;
13    
14    public class Actor {
15      protected int x,y;
16      protected int width, height;
17      protected String[] spriteNames;
18      protected int currentFrame;
19 protected int frameSpeed; 20 protected int t;
21 protected Stage stage; 22 protected SpriteCache spriteCache; 23 24 public Actor(Stage stage) { 25 this.stage = stage; 26 spriteCache = stage.getSpriteCache(); 27 currentFrame = 0; 28 frameSpeed = 1; 29 t=0; 30 } 31 32 public void paint(Graphics2D g){ 33 g.drawImage( spriteCache.getSprite(spriteNames[currentFrame]), x,y, stage ); 34 } 35 36 public int getX() { return x; } 37 public void setX(int i) { x = i; } 38 39 public int getY() { return y; } 40 public void setY(int i) { y = i; } 41 42 public int getFrameSpeed() {return frameSpeed; } 43 public void setFrameSpeed(int i) {frameSpeed = i; } 44 45 46 public void setSpriteNames(String[] names) { 47 spriteNames = names; 48 height = 0; 49 width = 0; 50 for (int i = 0; i < names.length; i++ ) { 51 BufferedImage image = spriteCache.getSprite(spriteNames[i]); 52 height = Math.max(height,image.getHeight()); 53 width = Math.max(width,image.getWidth()); 54 } 55 } 56 57 public int getHeight() { return height; } 58 public int getWidth() { return width; } 59 public void setHeight(int i) {height = i; } 60 public void setWidth(int i) { width = i; } 61 62 public void act() {
63 t++; 64 if (t % frameSpeed == 0){ 65 t=0; 66 currentFrame = (currentFrame + 1) % spriteNames.length; 67 }
68 } 69 } 70

The descendants of this class are free to set their own frame speed. For example for Monster, we could have:


1     /**
2      * Curso B?sico de desarrollo de Juegos en Java - Invaders
3      * 
4      * (c) 2004 Planetalia S.L. - Todos los derechos reservados. Prohibida su reproducci?n
5      * 
6      * http://www.planetalia.com
7      * 
8      */
9     package version15;
10    
11    public class Monster extends Actor {
12      protected int vx;
13      
14      public Monster(Stage stage) {
15        super(stage);
16        setSpriteNames( new String[] {"bicho0.gif","bicho1.gif"});
17 setFrameSpeed(35);
18 } 19 20 public void act() { 21 super.act(); 22 x+=vx; 23 if (x < 0 || x > Stage.WIDTH) 24 vx = -vx; 25 } 26 27 public int getVx() { return vx; } 28 public void setVx(int i) {vx = i; }} 29

Declaring the variable t as protected allows other classes that extend from Actor to use the time counter for other things, like deciding when to shoot, when to span new monsters, etc..



Do you want to be notified when new tutorials or lessons are published? Press here


Full list of Java source files for this step

Actor.java Invaders.java Monster.java SpriteCache.java
Stage.java      

Full list of resources

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      

  Previous Page - Frames Current Page - 15 - Frames - II   Next Page - The Player
  Return to the index of free Java tutorials  

(c) 2004 Planetalia S.L. All rights reserved. Unauthorized reproduction and/or mirroring is not permitted