Planetalia - Cursos

Cursos y Másters

Inicio    Profesores    Aulas    Testimonios    Cursos    Masters    Tecnologías    Cursos Gratuitos    Galería de Proyectos    Solicitar Información   

Curso - Programación de un Space Invaders en Java

  Página Anterior - Más disparos - Bombas de fragmentación Página Actual - 20 - Detección de colisiones   Página Siguiente - Barra de estado
  Índice de cursos Java gratuitos  

Detección de colisiones

(c) Alexander Hristov

Hasta ahora los monstruos se habían reido en nuestra cara de nuestros disparos porque ninguno de ellos les afectaba lo más mínimo. Ha llegado la hora de añadir la detección de colisiones a nuestro programa. En general es erróneo plantearse la detección de colisiones como un asunto de objetos puntuales, ya que nuestros sprites tienen tanto anchuras como alturas. De esta forma, habrá una colisión cuando los rectángulos que encierran cada sprite se intersecten:

Esta comprobación habrá que hacerla para todas las posibles parejas de actores, y además habrá que hacerla para cada actor con el jugador. Esta comprobación puesto que involucra manejar la lista global de actores, la debe hacer la clase Invaders

Afortunadamente, la clase Rectangle de Java incorpora el método intersects() que permite comprobar si un rectángulo intersecta con otro. Como necesitaremos saber los rectángulos que engloban cada sprite, podemos añadir un método (por ejemplo getBounds()) en la clase Actor que ya devuelva el objeto Rectangle construido.

Cuando detectamos una colisión, ¿qué es lo que hay que hacer?. De nuevo echamos mano del polimorfismo y de la delegación de responsabilidades y lo que haremos será limitarnos a notificar a cada actor que se ha producido una colisión con otro actor, y que ellos decidan lo que hacer en consecuencia. Esto significa que aparece un nuevo método en la clase Actor llamado collision(...). Por defecto este método no hace nada, siendo las clases hijas las responsables de sobreescribirlo como buenamente crean oportuno:



           . . .  
79      
80      public Rectangle getBounds() {
81        return new Rectangle(x,y,width,height);
82      }
83      
84      public void collision(Actor a){
85        
86      }
87    }
88    

Lógicamente, queremos que los monstruos mueran cuando ocurre una colisión con un misil o una bomba. Esto se realiza de la siguiente forma en la clase Monster:


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 version20;
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      
30 public void collision(Actor a) { 31 if (a instanceof Bullet || a instanceof Bomb) 32 remove(); 33 }
34 } 35

Y finalmente queda la propia detección de colisiones, que se realiza en la clase principal, en un nuevo método al que hemos llamado checkCollisions():


1     package version20;
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.Graphics2D;
16    import java.awt.Rectangle;
17    import java.awt.event.KeyEvent;
18    import java.awt.event.KeyListener;
19    import java.awt.event.WindowAdapter;
20    import java.awt.event.WindowEvent;
21    import java.awt.image.BufferStrategy;
22    import java.util.ArrayList;
23    
24    import javax.swing.JFrame;
25    import javax.swing.JPanel;
26    
27    public class Invaders extends Canvas implements Stage, KeyListener {
28      
29      private BufferStrategy strategy;
30      private long usedTime;
31      
32      private SpriteCache spriteCache;
33      private ArrayList actors; 
34      private Player player;
35      
36      public Invaders() {
37        spriteCache = new SpriteCache();
38        
39      
40        JFrame ventana = new JFrame("Invaders");
41        JPanel panel = (JPanel)ventana.getContentPane();
42        setBounds(0,0,Stage.WIDTH,Stage.HEIGHT);
43        panel.setPreferredSize(new Dimension(Stage.WIDTH,Stage.HEIGHT));
44        panel.setLayout(null);
45        panel.add(this);
46        ventana.setBounds(0,0,Stage.WIDTH,Stage.HEIGHT);
47        ventana.setVisible(true);
48        ventana.addWindowListener( new WindowAdapter() {
49          public void windowClosing(WindowEvent e) {
50            System.exit(0);
51          }
52        });
53        ventana.setResizable(false);
54        createBufferStrategy(2);
55        strategy = getBufferStrategy();
56        requestFocus();
57        addKeyListener(this);
58      }
59      
60      public void initWorld() {
61        actors = new ArrayList();
62        for (int i = 0; i < 10; i++){
63          Monster m = new Monster(this);
64          m.setX( (int)(Math.random()*Stage.WIDTH) );
65          m.setY( i*20 );
66          m.setVx( (int)(Math.random()*20-10) );
67          
68          actors.add(m);
69        }
70        
71        player = new Player(this);
72        player.setX(Stage.WIDTH/2);
73        player.setY(Stage.HEIGHT - 2*player.getHeight());
74      }
75      
76      public void addActor(Actor a) {
77        actors.add(a);
78      } 
79      
80      public void updateWorld() {
81        int i = 0;
82        while (i < actors.size()) {
83          Actor m = (Actor)actors.get(i);
84          if (m.isMarkedForRemoval()) {
85            actors.remove(i);
86          } else {
87            m.act();
88            i++;
89          }
90        }
91        player.act();
92      }
93      
94 public void checkCollisions() { 95 Rectangle playerBounds = player.getBounds(); 96 for (int i = 0; i < actors.size(); i++) { 97 Actor a1 = (Actor)actors.get(i); 98 Rectangle r1 = a1.getBounds(); 99 if (r1.intersects(playerBounds)) { 100 player.collision(a1); 101 a1.collision(player); 102 } 103 for (int j = i+1; j < actors.size(); j++) { 104 Actor a2 = (Actor)actors.get(j); 105 Rectangle r2 = a2.getBounds(); 106 if (r1.intersects(r2)) { 107 a1.collision(a2); 108 a2.collision(a1); 109 } 110 } 111 } 112 }
113 114 public void paintWorld() { 115 Graphics2D g = (Graphics2D)strategy.getDrawGraphics(); 116 g.setColor(Color.black); 117 g.fillRect(0,0,getWidth(),getHeight()); 118 for (int i = 0; i < actors.size(); i++) { 119 Actor m = (Actor)actors.get(i); 120 m.paint(g); 121 } 122 player.paint(g); 123 124 g.setColor(Color.white); 125 if (usedTime > 0) 126 g.drawString(String.valueOf(1000/usedTime)+" fps",0,Stage.HEIGHT-50); 127 else 128 g.drawString("--- fps",0,Stage.HEIGHT-50); 129 strategy.show(); 130 } 131 132 public SpriteCache getSpriteCache() { 133 return spriteCache; 134 } 135 136 public void keyPressed(KeyEvent e) { 137 player.keyPressed(e); 138 } 139 140 public void keyReleased(KeyEvent e) { 141 player.keyReleased(e); 142 } 143 public void keyTyped(KeyEvent e) {} 144 145 public void game() { 146 usedTime=1000; 147 initWorld(); 148 while (isVisible()) { 149 long startTime = System.currentTimeMillis(); 150 updateWorld();
151 checkCollisions();
152 paintWorld(); 153 usedTime = System.currentTimeMillis()-startTime; 154 try { 155 Thread.sleep(SPEED); 156 } catch (InterruptedException e) {} 157 } 158 } 159 160 public static void main(String[] args) { 161 Invaders inv = new Invaders(); 162 inv.game(); 163 } 164 } 165


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


Lista de archivos Java del programa en este paso

Actor.java Bomb.java Bullet.java Invaders.java
Monster.java Player.java SpriteCache.java Stage.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 - Más disparos - Bombas de fragmentación Página Actual - 20 - Detección de colisiones   Página Siguiente - Barra de estado
  Índice de cursos Java gratuitos  

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