Ver la versión completa : Gurus de Java, yo os invoco!
neostalker
14/02/2011, 19:13
Necesito que alguien me eche una mano con ésto:
Estoy haciendo un pequeño juego de naves basándome en un ejemplo que me pasó el famigo Trafuga y ya lo tengo casi listo salvo por una cosilla. Estoy intentando hacer que al matar un enemigo de un disparo aparezca una pequeña animación encima de él que represente una explosión (ya sabéis la típica animación de explosión de 4 o 5 sprites) y la mejor idea me pareció crear una clase "Animacion" que heredase de Thread para que pudiese llamarse desde el método "morir()" de la clase Enemigo, de forma que se ejecutase de forma independiente al Main, pero no consigo que funcione. El código de la clase animación es éste:
package marcianitos;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import javax.imageio.ImageIO;
public class Animacion extends Thread{
//PROPIEDADES (CONSTANTES)
private static final String RUTA_BASE = Main.miRuta() + "image" + File.separator + "anim" + File.separator;
//PROPIEDADES (VARIABLES)
private ArrayList <BufferedImage> imagenesAnimacion = new ArrayList();
private int numSprites, posX, posY, milisegundos;
private Graphics2D g;
//CONSTRUCTOR
public Animacion(String [] rutaImagenes){
this.numSprites = rutaImagenes.length;
for(int i = 0; i < this.numSprites; i++){
File f = new File(RUTA_BASE + rutaImagenes[i]);
if(f.exists()) try{ this.imagenesAnimacion.add(ImageIO.read(f)); }catch(Exception e){}
}
this.numSprites = this.imagenesAnimacion.size();
}
//INICIA EL HILO DE EJECUCIÓN
@Override
public void run(){
try{
for(int i = 0; i < this.numSprites; i++){
this.dibujar(this.imagenesAnimacion.get(i));
sleep(this.milisegundos);
}
}catch(Exception e){}
}
//INICIA EL PROCESO DE MUESTRA DE LA ANIMACIÓN
public void mostrar(Graphics2D g, int posX, int posY, int milisegundos){
this.g = g;
this.posX = posX;
this.posY = posY;
this.milisegundos = milisegundos;
this.start();
}
//DIBUJAR
private void dibujar(BufferedImage imagen){
this.g.drawImage(imagen, this.posX, this.posY, null);
}
}
Ya he comprobado que llega bien la método "dibujar(BufferedImage imagen)".
Alguien me echa un cable? Se os ocurre alguna forma mejor de hacerlo?
Un saludo y gracias! :brindis:
akualung
14/02/2011, 19:22
Igual digo una gilipollez como un piano pero.... ¿has probado a mirar que, aparte de llegar bien al método, le esté pasando bien el objeto BufferedImage y que la ruta a la imagen sea correcta? Aparte de eso, no se me ocurre nada más. Caso contrario, es algo que ya se escapa a mis conocimientos no muy profundos de Java.
Por cierto, otra cosa. En vez de hacer que la clase animacion herede de Thread, ¿no serviría igualmente que, desde el contructor de la clase, llamaras al método run? (el cual, al no ser ya dependiente de Thread, podrías renombrar como quisieras.. no se, "animaExplosion()" o como lo quieras llamar).
Y ya para acabar. Veo que el método "mostrar" lo tienes definido pero no veo que lo llames desde ningún otro sitio de la clase Animación. ¿Lo llamas desde otra clase para algo, o cómo?
Y además de lo que dice akualung, ¿el Graphics2D de dónde sale?
neostalker
14/02/2011, 19:26
Igual digo una gilipollez como un piano pero.... ¿has probado a mirar que, aparte de llegar bien al método, le esté pasando bien el objeto BufferedImage y que la ruta a la imagen sea correcta? Aparte de eso, no se me ocurre nada más. Caso contrario, es algo que ya se escapa a mis conocimientos no muy profundos de Java.
Sí, accede bien a las imágenes y quedan cargadas en el ArrayList, por lo que llegan bien al método "dibujar()", ya lo he comprobado.
Y además de lo que dice akualung, ¿el Graphics2D de dónde sale?
El Graphics2D se pasa desde el método "morir()" de la clase Enemigo y básicamente proviene del Main (de hecho es una propiedad pública suya)
jduranmaster
14/02/2011, 19:34
el objeto graphics2D (o como se escriba) tiene un contructor protected que no puedes usar, tienes que asignale al objeto "g" una instancia de otro objeto graphics sobre el que se realiza la modificacion del sprite (me imagino)
< - >
......ademas yo lo que haria seria que la clase animación heredase de la clase "enemigo" o como la hayas llamado e implemente la interfaz Runnable (para conservar el threading --> si es que lo necesitas porque no lo veo claro) de tal forma que se modifique el objeto g en la clase derivada y llames a un super() pasandole el obejto g modificado para que se modifique el enemigo
^MiSaTo^
14/02/2011, 19:36
Yo, como te ha dicho Akualung, no heredaría de Thread...no recuerdo como era...implements Runnable? Esque ahora mismo no me acuerdo y no se si estoy mezclándolo con Android.
El rollo es que hagas run(), pero sin heredar de Thread directamente.
Sobre Graphics2D, pues la verdad es que lo usé hace como 6-7 años, para una práctica de la uni en la que hice un Tower Defense, y ya no recuerdo ni cómo iba xD
jduranmaster
14/02/2011, 19:37
hola..... que alguien me lea. :D
^MiSaTo^
14/02/2011, 19:39
hola..... que alguien me lea. :D
Yo te he leído por eso había puesto que sobre Graphics2D no tengo ni idea.Pero lo que has puesto nuevo lo has debido escribir a la vez que yo xDD Porque veo que has puesto tb lo de implements Runnable y eso cuando he ido a contestar, no estaba xD
akualung
14/02/2011, 19:45
yo una cosa que no entiendo de ese código es... ese método "mostrar()" que está ahí, pero que no parece ser llamado desde ningún sitio, para qué está? O sencillamente es que el método "dibujar()" ya hace lo mismo?
Además, el fallo que da cual es? Sencillamente no se ve la explosión y ya está, o se cuelga el juego al llegar a ese punto, o cómo es?
neostalker
14/02/2011, 19:54
El tema es que no quiero que herede de "Enemigo", porque mi idea es que la clase "Animacion" pueda usarse en cualquier momento, usándola desde cualquier otra clase para representar la animación que sea por pantalla (en este caso quiero utilizarla para representar una explosión que se dibuje encima de un enemigo, pero en otro momento podría querer representar una luz parpadeante o un letrero luminoso, por ejemplo)
Por cierto, qué ventajas tiene implementar el interfaz runnable? A parte de darme la posibilidad de usar la herencia con otra clase que no sea Thread, claro. Quizá podría ser mejor salida el implementar runnable y heredar de JPanel y usar su propio Graphics2D para pintar las imagenes?
< - >
yo una cosa que no entiendo de ese código es... ese método "mostrar()" que está ahí, pero que no parece ser llamado desde ningún sitio, para qué está? O sencillamente es que el método "dibujar()" ya hace lo mismo?
Además, el fallo que da cual es? Sencillamente no se ve la explosión y ya está, o se cuelga el juego al llegar a ese punto, o cómo es?
Sí, no hay ningún error, ni ninguna excepción ni nada de nada (ya he comprobado a meter "System.out.println(e.getMessage())" en los "catch". Simplemente no pinta nada.
El método "mostrar()" se llama desde el método "morir()" de la clase Enemigo (no está en el código que os he puesto)
jduranmaster
14/02/2011, 20:00
Java es un lenguaje que por definición no tiene herencia multiple "directa" como si lo tienen otros lenguajes de programación del estilo C++ o Ada. ¿Porque? --> porque cuando heredas de muchos objetos es un autentico caos y los problemas pueden venir sobre todo cuando usas threads y herencia multiple: interbloqueos (mas comunes), violaciones de segmento y cosas asi.
En java se ha optado por un mecanismo de herencia multiple "indirecta", es decir las clases solo pueden heredar de un unica clase padre pero pueden implementar varias interfaces, pero a su vez una interfaz puede heredar de multiples interfaces, de tal forma que si implementas una interfaz que hereda otras, estas indirectamente dando a tu objeto la funcionalidad de muchas interfaces.
Debido a que java solo permite herencia de una unica clase padre el mecanismo de implementar runnable permite tener threads a la vez que tu objeto hereda la funcionalidad de un objeto que tu conseideras mas importante.
akualung
14/02/2011, 20:00
Sí, no hay ningún error, ni ninguna excepción ni nada de nada (ya he comprobado a meter "System.out.println(e.getMessage())" en los "catch". Simplemente no pinta nada.
El método "mostrar()" se llama desde el método "morir()" de la clase Enemigo (no está en el código que os he puesto)
Vale, ya lo entiendo, es lo que yo pensaba, se llama desde fuera. Pues lo que sea que haga fallar ese código ya está claro que se escapa a mi nivel. Solo se me ocurre que, si estas programando usando un IDE, pongas algun breakpoint dentro de esa clase y vayas paso a paso ejecutando hasta ver algo raro. Yo me retiro y le dejo hacer a los "mayores", jeje. Suerte ;)
jduranmaster
14/02/2011, 20:04
y si llamas a repaint() o ese metodo ya esta deprecated???
neostalker
14/02/2011, 20:11
Java es un lenguaje que por definición no tiene herencia multiple "directa" como si lo tienen otros lenguajes de programación del estilo C++ o Ada. ¿Porque? --> porque cuando heredas de muchos objetos es un autentico caos y los problemas pueden venir sobre todo cuando usas threads y herencia multiple: interbloqueos (mas comunes), violaciones de segmento y cosas asi.
En java se ha optado por un mecanismo de herencia multiple "indirecta", es decir las clases solo pueden heredar de un unica clase padre pero pueden implementar varias interfaces, pero a su vez una interfaz puede heredar de multiples interfaces, de tal forma que si implementas una interfaz que hereda otras, estas indirectamente dando a tu objeto la funcionalidad de muchas interfaces.
Debido a que java solo permite herencia de una unica clase padre el mecanismo de implementar runnable permite tener threads a la vez que tu objeto hereda la funcionalidad de un objeto que tu conseideras mas importante.
Sí, sí estoy familiarizado con todo ésto, por eso preguntaba si era mejor usar runnable y a su vez usar la herencia con otro tipo de clase.
"repaint()" no existe en la clase Thread, así que no puedo usarlo de momento :p
jduranmaster
14/02/2011, 20:18
"repaint()" no existe en la clase Thread, así que no puedo usarlo de momento :p
ya se que no es de thread, y creo que tampoco es de Graphics, ni de Graphics2D, pero mi pregunta es, debes de tener de algun componente gráfico donde pintas el sprite o llama a un metodo de enemigo/animación o algo así..... porque no haces un reapaint() de ese objeto (a lo mejor has usado un canvas o alguna cosa por el estilo)
neostalker
14/02/2011, 21:17
ya se que no es de thread, y creo que tampoco es de Graphics, ni de Graphics2D, pero mi pregunta es, debes de tener de algun componente gráfico donde pintas el sprite o llama a un metodo de enemigo/animación o algo así..... porque no haces un reapaint() de ese objeto (a lo mejor has usado un canvas o alguna cosa por el estilo)
El repaint se hace en el Main, que es el que crea un JFrame sobre el que se dibuja toda la escena, de ahí procede el Graphics2D. De hecho, ninguna de las clases que uso salvo el Main usa "repaint()".
< - >
Creo que se me ha ocurrido una manera de hacerlas sin tener que recurrir a nuevos hilos ni a herencias. Seguramente no será una forma tan óptima, pero funcionará (o debería xDDD)
Mi pregunta iba porque el Graphics2D va asociado a algún contexto/componente/bitmap/loquesea. No te lo puedes sacar de la manga así como así. ¿De dónde sale? Y como dice jduranmaster ¿Quién llama al repaint() de quien sea que tenga asociado ese Graphics2D?
Lo más normal es que el Graphics2D no se vuelque en la pantalla hasta que llames al repaint() del componente correspondiente. Mientras, estarás dibujando en el buffer interno y no verás nada en la pantalla.
¿Y no será que cuando llamas al repaint() borras toda la pantalla, pones un fondo o lo que sea, y por tanto te cargas todo lo que hayas dibujado antes?
Por cierto, intenta dibujar todo en el mismo thread. De hecho, cuantos menos threads tengas casi que mejor. Idealmente uno solo, el principal.
neostalker
14/02/2011, 23:36
Vale, ya lo he conseguido. He tenido que modificar las clases un poco para poder controlar ciertas cosas nuevas (como por ejemplo retrasar el borrado del enemigo golpeado de la cola de enemigos hasta que acabe la animación, etc) y al final sin tener que usar un thread, por lo que todo se pinta en la pantalla desde el Main.
Gracias por vuestros esfuerzos a todos :)
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions Inc. All rights reserved.