viernes, 17 de abril de 2009

Deteccion de Colision

Collision Detection, Hit Test, etc, basicamente, saber cuando se tocan dos sprites. Esto es topico de discusion algunas veces, de los metodos mas usados es usando rectangulos y ver cuando se tocan, en Java esto es facil, gracias a la clase Rectangle, de awt. He viso otros metodos que tienen hasta precision de pixel, pero no en Java, y creo que para este tutorial y las necesidades que tendremos, esto sera suficiente.
Lo que haremos para detectar colision es encerrar el sprite en un rectangulo que lo cubra "perfectamente", y vemos cuando colisiona con otro rectangulo, que sera el que encierra el sprite con el que queremos ver si hay colision o no.
Para esto, primero tenemos que tener como minimo dos sprites, asi que crearemos otro sprite fijo, y haremos que algo ocurra cuando nuestro sprite (al cual movemos con nuestro teclado) lo toque.
Vamos a crear una nueva clase, renombre el package a "hittest", llamada "Coin" (el sprite que mostraremos sera una moneda) asi que la nueva clase se ve algo asi

package hittest;

import java.awt.Image;

import javax.swing.ImageIcon;

/**
*
* @author fede
*/
public class Coin {
Image image;
public Coin(){
ImageIcon ii = new ImageIcon(this.getClass().getResource("coin.png"));
image = ii.getImage();
}
}


Veran que ya importe Image e ImageIcon y carge la imagen, como veniamos haciendo, ahora vamos a definir la posicion de la imagen para despues dibujarla, simplemente creamos dos variables privadas, x e y, y en el constructor les asignamos cualquier valor dentro de la ventana. Hacemos los respectivos get's.

public class Coin {
private Image image;
private int x,y;
public Coin(){
ImageIcon ii = new ImageIcon(this.getClass().getResource("coin.png"));
image = ii.getImage();
x = 10;
y = 40;
}

public int getX(){
return x;
}

public int getY(){
return y;
}

public Image getImage(){
return image;
}
}


Ahora vamos a agregar una funcion que me devuelve un rectangulo que "envuelve" completamente nuestro sprite, para eso, importamos "java.awt.Rectangle" y hacemos la siguiente funcion

public Rectangle getBounds(){
return new Rectangle(x, y, image.getWidth(null), image.getHeight(null));
}


Volvamos ahora a la clase Board, a agregar nuestro nuevo sprite. Simplemente hacemos un objeto privado, luego hacemos una instancia de este objeto en el constructor, y en la parte de dibujar, lo agregamos.



Como podran ver, ya esta dibujado, ahora vamos a agregar una funcion para que nuestro sprite anterior (al cual debimos haber hecho en otra clase, pero preferi en la misma por simplicidad) nos devuelva un rectangulo que lo encierre, es practicamente igual a la funcion en Coin, pero para poder hacerla en Board, tambien tenemos que importar java.awt.Rectangle.
Una vez que hallamos hecho la funcion, vamos a la parte de la logica (actionPerformed) y agregamos la condicion

Rectangle rectanglePlayer = getBounds();
Rectangle rectangleCoin = coin.getBounds();
if(rectangleCoin.intersects(rectanglePlayer))
x = y = 200;


Como veran, es bastante simple, basta con ver si se intersectan, y luego especificar que sucede, en este caso, el personaje se mueve a las coordenadas 200, 200 como muestra la siguiente imagen.



Sprites mas complejos pueden constrar de varios rectangulos, definidos en su clase, y la comparacion se volveria mas minuciosa, pero eso se lo dejo a su imaginacion y complejidad de juego que tengan en mente hacer, para los ejemplos de este blog esto sera suficiente.
Descargar codigo fuente: de 4shared

4 comentarios:

  1. hola, podrias subir de nuevo el codigo. Gracias!.

    ResponderEliminar
  2. Podés subir el código? te lo agradecería...

    ResponderEliminar
  3. podeis colgar otra vez el codigo ando algo perdido desde "Volvamos ahora a la clase Board..." no se seguir

    ResponderEliminar
  4. hey q primero q todo muchisimas gracias x estos tutoriales me han ayudado muchisimo :) bueno mira quisiera q dijeras como se hace para colocarle una imagen de fondo a los juegos? ya q el setBackground(color.???) es muy sencillo y solo permite un color :/

    ResponderEliminar