Foros de programación informática - Comunidad de programadores
Foros de programación informática, diseño gráfico y Web
En esta comunidad intentaremos dar soporte de programación a todos los niveles, desde principiantes a profesionales de la informática, desarrollo de programas, programación web y mucho más.
Registrado: 20 Mar 2009 Mensajes: 3136 Ubicación: y*width+x
Publicado: Martes 03 Ago 2010 18:16
Título del mensaje: [JAVA] Bases y demo de un juego sencillo 2D
Intro
Pues debido a las inquietudes de algunos usuarios, he decidido hacer algo sencillo en java que pueda ser aprovechado para otros que quieran hacer juegos sobre ésta plataforma o aplicaciones, la idea principal es sentar las bases, porque se que muchos que empezáis con la programación, copiáis de aquí de allá, sin tener una idea clara del porque del diseño, restándole importancia a ésto, y al final llegan los problemas, los errores, y todo se vuelve incomprensible e ilegible.
Sprites
Así que me dejo de chachara, y vamos con lo que vamos. Primeramente, si hablamos de un juego 2D, necesitaremos Sprites, el bitmap es la base del Sprite, principalmente obtendremos la imagen de los recursos que previamente almacenamos en un paquete predeterminado, por eso es bueno que seamos organizados y que los nombres a usar en un proyecto, siempre se encuentren en nuestra lengua nativa, y que tengan nombres comprensibles. Se que a muchos os da pereza escribir variables con más de tres caracteres seguidos, pero eso nos ayudará a entender bien el código, y si trabajamos en equipo, nos ayudará a que el equipo lo entienda también.
Código:
/*
* To change this template, choose Tools | Templates
publicvoid setSprite(String nombre)// Asignamos el fichero imagen al Sprite
{
sprite=nombre;
}
publicString getSprite()// Nos devuelve el fichero imagen del Sprite
{
return sprite;
}
publicvoid putSprite(Graphics grafico,int coordenadaHorizontal,int coordenadaVertical)// Pegamos el Sprite en la pantalla
{
x=coordenadaHorizontal;
y=coordenadaVertical;
if(visible) grafico.drawImage(newImageIcon(getClass().getResource(sprite)).getImage(), x, y, null);
}
}
En la ésta clase, hemos incluido lo básico de un Sprite, su finalidad es que pueda ser imprimido en cualquier dispositivo Graphics, que permita desplazamientos y obtener algunas de sus propiedades, las cuales podremos modificar, entre ellas destacar la de visible. Ésta propiedad nos puede dar mucho juego. Imaginemos que mi personaje mata a un enemigo de un balazo, si luego nos interesa repetir el nivel, no necesitaremos destruir al enemigo, y solo le diremos que no sea visible. Visible también nos puede servir para optimizar la aplicación, por ejemplo, tenemos el caso que tenemos un juego con scroll de pantalla, y nos interesa mostrar los que actualmente se encuentren en la área del personaje protagonista, y los que se encuentren moviéndose fuera de la pantalla no nos interesa que los imprima, con su consecuente proceso de pintado, que ralentiza el juego, y más cuando tenemos tropecientos Sprites, entonces modificamos la propiedad visible a false y problema resuelto, ya que aunque lo peguemos, seguirá actualizando sus coordenadas.
Ejemplo de uso
Voy a poner un ejemplo de uso de la clase, porque ya me veo venir las piedras...
Código:
/*
* To change this template, choose Tools | Templates
Registrado: 20 Mar 2009 Mensajes: 3136 Ubicación: y*width+x
Publicado: Martes 03 Ago 2010 22:57
Título del mensaje: Re: [JAVA] Bases y demo de un juego sencillo 2D
Gracias Tesis. La verdad es que la parte ociosa de la programación es la que mejor se me da y además me gusta.
Personaje Jugable
Bueno, cómo ya tenemos la base Sprite, ya podemos ponernos con el objeto que moverá el jugador o usuario. El Personaje Jugable, en adelante PJ, tiene la característica que posee los atributos y propiedades que requieran para el juego que estemos diseñando y será controlado mediante algún tipo de dispositivo de entrada, cómo un joystick o en éste caso, con el teclado. Entre sus atributos por ejemplo, podemos añadirle un propiedad de vida, que puede ser inicializada en el constructor con un valor, el cual ira reduciéndose según recibamos daño o colisionemos con algo, hasta que llegue a cero, que entonces será la muerte del Pj. También podemos incluir una matriz de Sprites que nos podrá servir para almacenar los fotogramas de la animación, si es que queremos animarlo. La estructura cómo comentaba puede ser variable pero lo básico y necesario, que es el control de éste mediante las teclas, es el cuerpo esencial.
Código:
/*
* To change this template, choose Tools | Templates
Ahora el problema que no encontraremos, cómo expuso una compañera en un hilo, es que podamos perder el foco mientras se crean los componentes. También hay que decir que necesitaremos implementar el KeyListener al objeto que éste por encima, para que éste sea focalizado y direccione la captura de teclas por medio del addKeyListener(), al objeto Pj ya creado, que contiene los métodos para procesar las teclas. De igual forma, siempre podremos direccionar dinámicamente en tiempo de ejecución la toma de eventos a un determinado objeto.
Ejemplo de uso
Código:
/*
* To change this template, choose Tools | Templates
Básicamente es el mismo ejemplo que el anterior, sólo que hemos añadido en la declaración de la clase juego, implements KeyListener, y antes de llegar al bucle infinito del juego hemos focalizado y redireccionado.
Registrado: 20 Mar 2009 Mensajes: 3136 Ubicación: y*width+x
Publicado: Viernes 13 Ago 2010 17:29
Título del mensaje: Re: [JAVA] Bases y demo de un juego sencillo 2D
Animación de Sprites
Ahora que ya sabemos mover un Sprite, lo ideal sería animarlo mediante varias imágenes una detrás de otra. Para ello deberemos mejorar la clase Sprite. La nueva mejora incorpora un par de métodos; resizeArray,setFrame y getFrame. Basicamente es idéntica a la primera que hicimos, sólo que esta vez se trabaja con una matriz que almacena los nombres de los ficheros de imagen que conformaran la animación. El funcionamiento difiere un poco; si antes asignábamos la imagen con setSprite, ahora no sólo podemos asignarle una única imagen, ya que si volvemos a repetir el proceso con setSprite, conseguimos almacenar la siguiente imagen y así sucesivamente hasta que nos quedemos sin memoria . La variable encargada de mostrar la imagen que deseemos es fotograma, la cual será gestionada con los métodos getFrame y setFrame.
publicString getSprite()// Nos devuelve el fichero imagen del Sprite
{
return sprite[fotograma];
}
publicvoid putSprite(Graphics grafico,int coordenadaHorizontal,int coordenadaVertical)// Pegamos el Sprite en la pantalla
{
x=coordenadaHorizontal;
y=coordenadaVertical;
if(visible) grafico.drawImage(newImageIcon(getClass().getResource(sprite[fotograma])).getImage(), x, y, null);
}
}
Si pero, y la animación? jajjajaja vale vale, la animación la haremos manualmente trabajando con los métodos anteriormente mencionados, setFrame y getFrame. Pero si ya quisiéramos tener una función o método especial que lo haga todo, ya tendríamos que trabajarlo en el objeto Personaje o derivado de Sprite, porque no siempre todos los personajes u objetos visuales tienen el mismo comportamiento. Entonces lo aconsejable es personalizarlos.
En éste caso hemos personalizado un poco la clase PersonajeJugable y le hemos añadido el método anima y también un par de variables para controlar el tiempo de la animación que vendrá determinado por las acciones del teclado.
Entonces ahora lo ideal es que si vamos a crear un personaje protagonista, sería crear una clase específicamente para él, pero que herede todas las propiedades del PersonajeJuagable, por ejemplo así:
Código:
/**
*
* @author whiteskull
*/
publicclass Lorna extends PersonajeJugable {
public Lorna()
{
super();
this.setSprite("/Imagenes/lorna_camina1.png");
this.setSprite("/Imagenes/lorna_camina2.png");
this.setSprite("/Imagenes/lorna_camina3.png");
this.setSprite("/Imagenes/lorna_camina4.png");
}
publicvoid actualiza()
{
if(this.actualizar()>0)this.anima(0,3,3);
}
}
Vemos cómo en el constructor añadimos los fotogramas al protagonista con el setSprite, luego para evitar confusiones, creamos un método actualiza, y al de la clase PersonajeJugable le renombramos su actualiza por actualizar. La clase actualiza del protagonista, será la encargada de capturar las teclas, mover el Sprite y ahora de animarlo siempre que se cumpla la condición que le demos, de lo contrario siempre estaría animado, pero por ejemplo, habrá que acondicionarlo según donde se mueve, si se mueve, si no lo hace, si salta, si reciobe daño, etc... en el caso de nuetsro protagonista mostrará la secuencia de animación mientras el Sprite se mueva en cualquier dirección, actualizar()>0 .
Título del mensaje: Re: [JAVA] Bases y demo de un juego sencillo 2D
Buenas, estoy siguiendo tu tutorial para guiarme en como hacer mi proyecto de programaciçon de este cuatrimestre, si quisiera hacer diferentes niveles para el juego, me bastaría con crear una clase nivel e ir modificándola en el juego.java haciéndola más complicada a medida que avanza el juego?
Una pregunta aparte mi idea era hacer una especie de sonic sencillito si es necesario sin enemigos, pero que tuviese que coger ciertos objetos en cierto tiempo y llegar al final del recorrido, es muy complejo hacer un recorrido?
Registrado: 20 Mar 2009 Mensajes: 3136 Ubicación: y*width+x
Publicado: Lunes 14 Nov 2011 01:23
Título del mensaje: Re: [JAVA] Bases y demo de un juego sencillo 2D
Nacho escribió:
si quisiera hacer diferentes niveles para el juego, me bastaría con crear una clase nivel e ir modificándola en el juego.java haciéndola más complicada a medida que avanza el juego?
bueno...mmm... digamos que nla clase Nivel sería la que interpreta un nivel, pero dependiendo de la descripción de este. Vamos, es que no se como explicarlo. Yo haría que la clase Nivel tomara unos datos, por ejemplo, me comentas que quieres hacerlo al estilo Sonic, pero sin enemigos, pues entonces sabrás que los niveles contenía bitmaps para el fondo y objetos donde interactuaba el PJ, como los anillos, los muelles que te impulsaban, etc...
Código:
class Nivel
{
...
BloqueDinamico bloquesD[];
BloqueStatico bloqueS[];
Anillo anillos[];
void actualizar()... // que sería llamado desde el bucle del juego
...
Habría que hacer una clase para éstos objetos, por ejemplo usar la Sprite como base y luego añadirle un comportamiento en base a las circunstancias y acciones del PJ.
Según queramos modificar el nivel, no deberías crear otra clase extra, si no parametrizar la clase, como por ejemplo modificar el número de plataformas, colocar lso anillos en lugares más inaccesibles, etc... entiendes?
Código:
Nivel primerNivel=new Nivel(); // Podriamos añadirle en el constructor el ancho y alto del nivel para impedir que el PJ se saliera fuera, etc...
Aún así, los niveles sería aconsejado que los realizaras desde un editor, hecho por ti, y que este generara un fichero que luego sería embebido en la aplicación. Luego cargas esos ficheros que representan o describen el nivel desde un método.
Código:
...
segundoNivel.Load("nivel2.map");
...
Espero que hayas captado la idea. Me gustaría haberte puesto un ejemplo más práctico y funcional pero en estos momentos no puedo por falta de tiempo, quizás más adelante siga el hilo y continúe el tutorial, añadiendo por ejemplo el tema de los mapas y niveles, así como sonido, etc...
Título del mensaje: Re: [JAVA] Bases y demo de un juego sencillo 2D
Si se me ha quedado claro la idea y la veo interesante, solo que viendo que esto tiene bastante curro y es un proyecto que debo entregar para el mes que viene creo que me voy a decantar por acabar haciendo una especie de pang y también ponerle niveles, que tengo algún código que me servirá de ayuda, muchísimas gracias, si me surge alguna duda te la postearé aquí si no te importa.
P.D : Felicidades por el tutorial está muy claro y bien hecho.
WhiteSkull escribió:
Nacho escribió:
si quisiera hacer diferentes niveles para el juego, me bastaría con crear una clase nivel e ir modificándola en el juego.java haciéndola más complicada a medida que avanza el juego?
bueno...mmm... digamos que nla clase Nivel sería la que interpreta un nivel, pero dependiendo de la descripción de este. Vamos, es que no se como explicarlo. Yo haría que la clase Nivel tomara unos datos, por ejemplo, me comentas que quieres hacerlo al estilo Sonic, pero sin enemigos, pues entonces sabrás que los niveles contenía bitmaps para el fondo y objetos donde interactuaba el PJ, como los anillos, los muelles que te impulsaban, etc...
Código:
class Nivel
{
...
BloqueDinamico bloquesD[];
BloqueStatico bloqueS[];
Anillo anillos[];
void actualizar()... // que sería llamado desde el bucle del juego
...
Habría que hacer una clase para éstos objetos, por ejemplo usar la Sprite como base y luego añadirle un comportamiento en base a las circunstancias y acciones del PJ.
Según queramos modificar el nivel, no deberías crear otra clase extra, si no parametrizar la clase, como por ejemplo modificar el número de plataformas, colocar lso anillos en lugares más inaccesibles, etc... entiendes?
Código:
Nivel primerNivel=new Nivel(); // Podriamos añadirle en el constructor el ancho y alto del nivel para impedir que el PJ se saliera fuera, etc...
Aún así, los niveles sería aconsejado que los realizaras desde un editor, hecho por ti, y que este generara un fichero que luego sería embebido en la aplicación. Luego cargas esos ficheros que representan o describen el nivel desde un método.
Código:
...
segundoNivel.Load("nivel2.map");
...
Espero que hayas captado la idea. Me gustaría haberte puesto un ejemplo más práctico y funcional pero en estos momentos no puedo por falta de tiempo, quizás más adelante siga el hilo y continúe el tutorial, añadiendo por ejemplo el tema de los mapas y niveles, así como sonido, etc...
Título del mensaje: Re: [JAVA] Bases y demo de un juego sencillo 2D
Hola , te escribo esta duda de un proyecto de un juego que estoy modificando, creo que sería más correcto
enviarla por privado pero debido a que acabo de registrarme en el foro no tengo permisos aún.
El caso es que el juego que estoy modificando es una especie de Pang, y las bolas están dibujadas
mediante el método dibujarCirculo de Java, al igual que el protagonista que está dibujado mediante
métodos del estilo como dibujarRectángulo,Triángulo etc y el fondo del juego es un graphics y se guarda
mediante un image.
1)Entonces lo que yo he intentado conseguir es introducir tu personaje mediante sprite, personaje jugable etc..
de tal forma que pueda usar imágenes en vez que tener que dibujar.
2)También he intentado añadir un fondo mediante un bufferedImage de tal manera que en cada nivel del juego
pueda poner una imagen diferente de fondo.
Pero tampoco he conseguido hacerlo funcionar.
3)Por último también quisiera hacer lo mismo con las bolas del juego, y en vez que tener que dibujarlas
asignarles una imagen.
Las clases en las qué se manejan estos aspectos son:
1) Protagonista, Juego y Ventana
2) Juego y Ventana
3) Bola, Juego y Ventana
Te adjunto el código en un link, ya que es muy extenso para copiarlo.
megaupload.com/?d=OSHJFJ1L
Si es necesario posteo los link, pero como ya digo son bastante extensos
Muchas gracias y entiendo que ya que como dices no es que te sobre el tiempo, agradeceré
cualquier tipo de ayuda que me des por muy pequeña que sea.
Registrado: 20 Mar 2009 Mensajes: 3136 Ubicación: y*width+x
Publicado: Sábado 10 Dic 2011 00:09
Título del mensaje: Re: [JAVA] Bases y demo de un juego sencillo 2D
Nacho5C escribió:
...y las bolas están dibujadas
mediante el método dibujarCirculo de Java, al igual que el protagonista que está dibujado mediante
métodos del estilo como dibujarRectángulo,Triángulo etc...
...no esta mal, pero seguro es más sencillo que usaras simples bitmaps.
Nacho5C escribió:
1)Entonces lo que yo he intentado conseguir es introducir tu personaje mediante sprite, personaje jugable etc..
de tal forma que pueda usar imágenes en vez que tener que dibujar.
Y? no es nada difícil, y como puedes apreciar usa métodos sencillos y lógicos.
Nacho5C escribió:
2)También he intentado añadir un fondo mediante un bufferedImage de tal manera que en cada nivel del juego
pueda poner una imagen diferente de fondo.
Pero tampoco he conseguido hacerlo funcionar.
Si vas a utilizar la clase Sprite no necesitas usar bufferImage para poner un fondo, ya que con ella puedes cargar todo tipo de imagen. Más adelante expongo una pequeña demo con scroll horizontal, usando solamente la clase Sprite.
Nacho5C escribió:
3)Por último también quisiera hacer lo mismo con las bolas del juego, y en vez que tener que dibujarlas
asignarles una imagen.
// El ENd
grafico.drawImage(pantalla, 0, 0, this);
...
.. ya que los Sprites se dibujaran en ese orden, por lo que el fondo, siempre deberá ir el primero, resto de sprites y por último el interfaz con marcadores de vida, puntos, etc...
Como hacer un scroll sencillo (moviendo un bitmap gigante)
El scroll consiste en el movimiento acompasado del jugador con el fondo, para ello delimitamos zonas en la pantalla que permitirá que eso suceda.
Código:
...
if (jugador.getX()<80) // indicamos la zona izquierda de la pantalla
{ // donde comenzaremos a mover el fondo, que se mover en sentido contrario al movimiento del jugador
jugador.setX(Xanterior);
fondo.setX(fondo.getX()+jugador.getSteps().x);
} else if (jugador.getX()>(this.getWidth()-110)) // zona derecha
{
jugador.setX(Xanterior);
fondo.setX(fondo.getX()-jugador.getSteps().x);
}
...
En la demo que incluyo, usé un bitmap gigante, ya que en un ordenador, hoy en día, la memoria no es un impedimento. En dispositivos portátiles, se pueden usar otras técnicas ya mencionadas como es la de usar una matriz de bloques, que consisten en pequeños Sprites. Pero en ambos casos, sigue el mismo principio.
Título del mensaje: Re: [JAVA] Bases y demo de un juego sencillo 2D
Tengo una duda lo único que yo compruebo la colisión con el disparo o el protagonista mediante los atributos de la clase bola, radio etc
Si cambio la bola dibujada por un sprite como compruebaría esa colisión?
Registrado: 20 Mar 2009 Mensajes: 3136 Ubicación: y*width+x
Publicado: Domingo 11 Dic 2011 03:53
Título del mensaje: Re: [JAVA] Bases y demo de un juego sencillo 2D
Cómo la comprobarías? no entiendo.
Yo por lo menos, incluí una función que funciona en la misma clase del juego, que trabaja con el ancho y alto de un Sprite (fotograma actual), y comprueba si se solapa con otro Sprite especificado. Devuelve True si colisiona, y False si no lo hace. Para su buen funcionamiento, debe ser puesta después de actualizar las coordenadas de los Sprites, osea, después de un actualiza() o un setX()/setY().
Registrado: 20 Mar 2009 Mensajes: 3136 Ubicación: y*width+x
Publicado: Lunes 16 Ene 2012 00:10
Título del mensaje: Re: [JAVA] Bases y demo de un juego sencillo 2D
Te parpadea, porque seguro que estás pintando encima de una imagen o un control... el control o la imagen, se intenta actualizar, bien por un proceso de repintado o el que sea. Por eso aparece ese efecto molesto de parpadeo, por eso para solucionar eso, todo el mundo usa una única pantalla donde trabaja, en ella antes de visualizarla, se dibujan los personajes, los objetos, el fondo, etc... una vez acabado el proceso, se pega la imagen o se vuelca sobre el lienzo o sobre la imagen visualizadora.
A este tipo de pantallas se el denomina "buffer", por eso si observas dentro de la función dibuja... verás que la imagen que uso para pintar y trabajar con ella es pantalla, desde ahí dibujo los sprites.
Código:
public void dibuja(Graphics grafico)
{
// El Begin de OpenGL o DirectX
BufferedImage pantalla=new BufferedImage(this.getWidth(),this.getHeight(), BufferedImage.TYPE_INT_RGB );
Luego vuelco el contenido de pantalla al objeto donde trabajo (this), ya que hereda las características de la clase Canvas, que le permiten visualizar y trabajar adecuadamente con los gráficos.
Código:
....
// El ENd
grafico.drawImage(pantalla, 0, 0, this);
}
Entonces, lo que estás haciendo es lo siguiente; primero llamas a la función dibuja(), que como tienes en el comentario, dibuja la imagen del fondo , luego inicias un bucle y dentro, imprimes i veces (personajes.size() ) un gráfico, perdiendo en cada vuelta el anterior gráfico, de esa forma está produciendo el efecto parpadeo.
Debes trabajar con imagen y luego volcarla, lo ideal es que fuera dentro de dibuja, porque te en cuenta, que podemos modificar las propiedades del personaje desde cualquier parte.
Tu imagina este proceso como cuando vas al teatro, mientras se muestra la escena de un acto, detrás del escenario hay otro que se está decorando, y cuando acaba el acto, moverá el actual para mostrar el que hay detrás, normalmente con la caída del telón.
//Metodo de dibujado de la imagen
public void dibujar(Graphics2D g, int x, int y)
{
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
// Antes de que copiemos la VolatileImage, necesitaremos tenerla en buen estado.
if ( imagenVolatil.validate(gc) != VolatileImage.IMAGE_OK )
{
imagenVolatil = crearImagenVolatil( anchura, altura, imagenVolatil.getTransparency() );
rutina();
}
for( int i = 0; i< personajes.size(); i++ )
{
personajes.elementAt(i).putSprite( imagenVolatil.getGraphics(), personajes.elementAt(i).getX() , personajes.elementAt(i).getY() );
}
} while ( imagenVolatil.contentsLost());
}
Es un poco complicado por que carga una imagenVolatil y verifica que no la hemos perdido antes de dibujarla, lo he puesto como atributo de la clase canvas en vez de crearlo cada vez en el metodo dibuja.
PutSprite() funciona cuando pasas la imagen que va a pintar primeramente con setSprite(), el primer argumento de putSprite() es para indicarle donde lo pinta.
En resumen, debes comprobar dos cosas, que si está pintando sobre el dispositivo del control y si las imagenes que le pasaste a personajes mediante setSprite() contienen algo, bien porque no existe o porque la ruta no es la correcta, date cuenta que es una ruta de clase, ya que supuestamente la imagen debe estár agregada como un recurso.
Para comprobar si está pintando correctamente, prueba sustituir la línea ...
g.drawImage( imagenVolatil, 0, 0, imagenVolatil.getWidth(), imagenVolatil.getHeight(), this);
...por un g.drawLine o similar.