Realizacrión de un videojuego (Capítulo 2)
sábado, marzo 22, 2003 at 1:00AM Programar un videojuego en Java II
Fecha de creación: 15.02.2003
Revisión 1.1 (22.03.2003)
Raúl Bonachía Castillo
rbonachia AT educaline DOT com
|
Introducción
Esta es la continuación del primer artículo sobre cómo programar un videojuego. Una nota importante: Voy a continuar con la jerarquía de clases utilizada hasta ahora. Básicamente por una razón: por todos aquellos que estén usándolas y no quieran volver a pensarsi las cambio. Pero dado que la obligación de un buen programador es hallar la mejor optimización, especialmente a la hora de diseñar juegos, propondré otra posibilidad para organizar las clases primitivas: clase Avion, clase Disparo etc...., en el tercer y último artículo sobre este videojuego
Síntesis.
En este segundo artículo desarrollaremos:
Clase ControladoraEstrellas
Clase ControladoraDisparos
Clase ControladoraAviones
Applet Videojuego
| Lista 1: Clases y applet desarrollados |
Construyendo la clase ControladoraEstrellas
Esta clase se va a encargar de generar todas las estrellas que veremos en la pantalla del videojuego.
Tendrán una traslación horizontal de derecha a izquierda. Notar que originalmente se le asignara a
cada una unas coordenadas (x,y) aleatorias, con las
restricciones lógicas: donde anchura y altura representan las
dimensiones del applet. Manejar con soltura la aleatoriedad es lo que proporcionará interés al
movimiento.
![]() |
| Figura 1: Movimiento de estrellas |
Ahora, el código:
import java.util.Random;
import java.awt.Graphics;
public class ControladorEstrellas{
Random r;
//Array de Estrellas
Estrella estrellas[];
int cantidad;
int anchura,altura;
public ControladorEstrellas(int anchura,int altura, int cantidad){
//Anchura del applet
this.anchura=anchura;
// Altura del applet
this.altura=altura;
// cantidad de estrellas q vamos a crear
this.cantidad=cantidad;
// Construimos el generador de aleatoriedad
r=new Random();
//Creamos el array de objetos Estrellas
estrellas=new Estrella[cantidad];
/*A cada estrella le dotamos de posiciones aleatorias gracias al generador.*/
for(int i=0;i<cantidad;i++){
estrellas[i]=new Estrella(r.nextInt(anchura),r.nextInt(altura));
}
}
public void actualizar(){
for(int i=0;iestrellas.length;i++){
//Calculamos la coordenada x de la estrella i
int posX=estrellas[i].locx-1;
//Calculamos la coordenada y de la estrella i
int posY=estrellas[i].locy;
if (posX0)
{
/*Importante: si la estrella se encuentra en el extremos izquierdo del applet,
le otorgamos una nueva posición en el extremos derecho del applet*/
estrellas[i].nuevaPosicion(anchura-r.nextInt(20),r.nextInt(altura));
}
else
/*Si no esta al final de su recorrido le hacemos retroceder
un píxel en sentido horizontal*/
estrellas[i].nuevaPosicion(posX,posY);
}
}
public void pintar(Graphics g){
// Pintamos cada una de las estrellas.
for(int i=0;icantidad;i++)
estrellas[i].pintar(g);
}
}
Construyendo la clase ControladorDisparos
Empieza la marcha. Con esta clase vamos a generar los disparos del avión protagonista. El código empieza a ser un poco más largo, pero siempre razonablemente comprensible. No debiera suponer mucho esfuerzo entender la razón de cada línea.
import java.awt.Graphics;
import java.awt.Image;
import java.applet.*;
public class ControladorDisparos{
// sonido que emitira el avion protagonista al disparar
AudioClip audio;
// la imagen del proyectil del protagonista
Image proyectil;
// Array de los aviones enemigos
Colisionable objetivos[];
// Array de los Disparos del protagonista
Disparo fuegoProta[];
// indice que ayudará a controlar el número de disparos
int indiceDisparosProta;
// anchura y altura del applet
static int anchura,altura;
// número de disparos del avion protagonista.
final int numDisparos;
//variables delimitadoras
private int minX,maxX,minimoX,maximoX,minimoY,maximoY;
ControladorDisparos(int anchura, int altura, Colisionable objetivos[],
Image proyectil, AudioClip audio ){
this.anchura=anchura;
this.altura=altura;
this.audio=audio;
this.proyectil=proyectil;
this.objetivos=objetivos;
minimoX=0;
maximoX=anchura;
minimoY=0;
maximoY=altura;
/*número de municiones que dispondrá el cargador del avión*/
numDisparos=20;
indiceDisparosProta=0;
//Creamos el cargador del avión
fuegoProta=new Disparo[numDisparos];
// Cargamos los disparos del avion
cargarDisparosProta();
}
/*Método que se invoca desde ControladorAviones para averiguar si los aviones son
derribados por el fuego del avion protagonista*/
public Disparo[] devolverDisparos(){
return fuegoProta;
}
/* devuelve el número de disparos*/
public int numeroDisparos(){
return numDisparos;
}
/* Carga el cargador, valga la redundancia J */
void cargarDisparosProta(){
for(int i=0;inumDisparos;i++){
fuegoProta[i]=new Disparo(proyectil,15,15);
}
}
/*Este método se invocará desde el applet para que se dispare una munición del
avión protagonista, pasándole las coordenadas (x,y) donde debe iniciar su recorrido
horizontal*/
public void dispararFuegoAvionProta(int xInicial, int yInicial){
indiceDisparosProta++;
if (indiceDisparosProta!=numDisparos){
indiceDisparosProta=indiceDisparosProta%numDisparos;
}
else{
indiceDisparosProta=1;
}
fuegoProta[indiceDisparosProta-1].restablecer();
fuegoProta[indiceDisparosProta-1].nuevaPosicion(xInicial, yInicial);
audio.play();
}
/* Método fundamental que provoca que los disparos del avión protagonista
avancen horizontalmente hacia la derecha de 40 en 40 pixeles*/
public void actualizarDisparos(){
int avionX,avionY;
for(int i=0;iindiceDisparosProta;i++){
avionX=fuegoProta[i].locx+40;
avionY=fuegoProta[i].locy;
if ( (avionXminimoX) || (avionX>maximoX) ||
(avionY<minimoY) || (avionY>maximoY) )
fuegoProta[i].suspender();
else
fuegoProta[i].nuevaPosicion(avionX,avionY);
}
}
/*Si un avion enemigo colisiona con un disparo del protagonista,
aquellos desaparecen*/
public void objetivoDerribado(){
int numero;
int coordX,coordY,ancho,alto;
for(int i=0;i<indiceDisparosProta;i++){
if (fuegoProta[i].esActivo()){
for(int j=0;jobjetivos.length;j++){
coordX=fuegoProta[i].locx;
coordY=fuegoProta[i].locy;
ancho=fuegoProta[i].anchura;
alto=fuegoProta[i].altura;
if (objetivos[j].intersecta(coordX, coordY,
coordX+ancho, coordY+alto )){
objetivos[j].colision();
fuegoProta[j].colision();
}
}
}
}
}
/*actualiza invocando a los métodos pertinentes*/
public void actualizar(){
objetivoDerribado();
actualizarDisparos();
}
/*pinta los disparos del avión protagonista*/
public void pintar(Graphics g){
for(int i=0;iindiceDisparosProta;i++){
if (fuegoProta[i].esActivo()){
fuegoProta[i].pintar(g);
}
}
}
}
Construyendo la clase ControladorAviones
Última clase necesaria antes del construir el applet y el hilo que dará vida al videojuego. Ánimo y suerte, ¡ya queda poco!.
import java.util.Random;
import java.applet.*;
import java.awt.Image;
import java.awt.Graphics;
public class ControladorAviones {
//numero de aviones enemigos que se verán siempre en pantalla
final int numAviones;
//numero de proyectiles imaginarios asignados a cada avion enemigo
final int numBombas=4;
// Array de aviones enemigos
public Avion aviones[];
//el avión protagonista
public Avion avionProta;
//anchura y altura del applet
static int anchura,altura;
//disparos del enemigo
Disparo bombasDeBombardero[];
//sonidos emitidos cuando dispare el enemigo
AudioClip audio,audio1;
Random r;
/*las imágenes del avion protagonista, de los aviones enemigos y los disparos de
estos últimos*/
Image bomba,avionEnemigo,avionProtagonista;
/*controla el número de bombas sueltas del enemigo*/
int numBombasSueltas;
/* array que colocará a cada avión enemigo en su posición correspondiente en el
margen derecho del applet*/
int posicionSalidaAviones[];
/*variables controladoras*/
int minimoX,minimoY,maximoX,maximoY;
/*CONSTRUCTOR de la clase*/
public ControladorAviones(int anchura, int altura, Image avionEnemigo,
Image avionProtagonista, Image bomba, AudioClip audio, AudioClip audio1){
this.anchura=anchura;
this.altura=altura;
this.audio=audio;
this.audio1=audio1;
this.avion=avion;
this.bomba=bomba;
this.avionEnemigo=avionEnemigo;
this.avionProtagonista=avionProtagonista;
numAviones=20;
minimoX=0;
maximoX=anchura;
minimoY=0;
maximoY=altura;
numBombasSueltas=0;
/*crea el array de aviones enemigos*/
aviones=new Avion[numAviones];
/* crea un array con los disparos de los que dispondrán
todos los aviones enemigos en total*/
bombasDeBombardero=new Disparo[numAviones*numBombas];
/* array con las posiciones iniciales de todos los aviones enemigos*/
posicionSalidaAviones=new int[numAviones];
r=new Random();
/*crea aviones enemigos como protagonistas*/
ca.cargarTodosLosAviones();
}
/*método que invocará a los que crean al avión protagonista y a los enemigos*/
void cargarTodosLosAviones(){
cargarAviones();
cargarAvionProtagonista();
}
/* inicializa el array de posiciones iniciales de los aviones enemigos a cero*/
void ponerAcero(int posicionSalidaAviones[]){
for(int i=0;iposicionSalidaAviones.length;i++){
posicionSalidaAviones[i]=0;
}
}
/*método que se asegurará de no asignar la misma posición de salida a dos aviones
enemigos a lo largo de toda la partida en cada actualización del repintado*/
void comprobarNoRepetidoY(int indice, int posicionSalidaAviones[]){
boolean choca=true;
int posI;
if (indice!=0){
while (choca){
for(int i=0;i<indice;i++){
posI=posicionSalidaAviones[i];
if ( (posicionSalidaAviones[indice] >= posI-20 ) &&
( posicionSalidaAviones[indice] <= posI+20) ){
posicionSalidaAviones[indice]=r.nextInt(altura-15);
break;
}
else if (i==(indice-1)){
choca=false;
}
}
}
}
}
/*crea los aviones enemigos. A cada uno de ellos les asigna una posición unívoca
de salida arbitraria a lo largo de todo el margen derecho del applet*/
void cargarAviones(){
for(int i=0;i<numAviones;i++){
aviones[i]=new Avion(avionEnemigo,audio,20,20);
aviones[i].restablecer();
posicionSalidaAviones[i]=r.nextInt(altura-15);
comprobarNoRepetidoY(i,posicionSalidaAviones);
aviones[i].nuevaPosicion(anchura,posicionSalidaAviones[i]);
}
ponerAcero(posicionSalidaAviones);
//carga los disparos de los aviones enemigos
cargarBombas();
}
/*Crea al avion protagonista y lo situa inicialmente en el centro del applet*/
void cargarAvionProtagonista(){
avionProta=new Avion(avionProtagonista,audio,20,20);
avionProta.restablecer();
avionProta.nuevaPosicion(anchura/2,altura/2);
}
/* Actualiza las posiciones de los aviones enemigos. Este método será invocado
en cada repintado del applet*/
public void actualizarAviones(){
int coorX;
for(int i=0;inumAviones;i++){
/*si el avión sigue siendo visible*/
if ( aviones[i].esActivo() ){
/*este método determinará si el avion enemigo tiene posibilidad de disparar sobre
nuestro protagonista y de ser así lo hará*/
soltarBombas(i);
coorX=aviones[i].locx-10;
if (coorXminimoX)
/* si el avion se situa a la izquierda del applet
desaparece*/
aviones[i].suspender();
else
aviones[i].nuevaPosicion(coorX, aviones[i].locy);
}
else{
/*se le vuelve asignar coordenadas en el margen derecho del applet.Este truco es
fundamental para dar la apariencia de que surgen nuevos aviones enemigos. En realidad,
en pantalla siempre están el mismo número de aviones enemigos*/
aviones[i].restablecer();
posicionSalidaAviones[i]=r.nextInt(altura);
comprobarNoRepetidoY(i, posicionSalidaAviones);
aviones[i].nuevaPosicion(anchura, posicionSalidaAviones[i]);
}
}
}
/*este método eliminará a los aviones enemigos que colisionen con el protagonista
o que reciban un impacto de los disparos del avion protagonista. Notar que el
protagonista debiera desaparecer también o, cuanto menos, perder un nivel de vida.
Pero eso lo terminaremos clarificar en el próximo artículo,(ahora está comentado)
cuando demos una presentación al videojuego.*/
void avionDerribado(Disparo proyectiles[]){
boolean derribado;
int coordX,coordY,ancho,alto;
int X=avionProta.locx;
int Y=avionProta.locy;
int anch=avionProta.anchura;
int alt=avionProta.altura;
for(int i=0;inumAviones;i++){
if (aviones[i].esActivo()){
for (int j=0;jproyectiles.length;j++){
coordX=proyectiles[j].locx;
coordY=proyectiles[j].locy;
ancho=proyectiles[j].anchura;
alto=proyectiles[j].altura;
if(aviones[i].intersecta(coordX, coordY, coordX+ancho,
coordY+alto )){
/*el avion enemigo ha sido alcanzado por un disparo del protagonista y, en
consecuencia, muere*/
aviones[i].colision
}
if(aviones[i].intersecta(X,Y,X+anch,Y+alt)){
/*en el próximo artículo daremos una alternativa a la desaparición del protagonista,
dándole una puntuación*/
aviones[i].colision();
//avionProta.colision();
}
}
}
}
}
/*Este método insta al avion enemigo situado en la posición indice del array de
aviones enemigos a lanzar un disparo si está situado en una franja horizonta de
diez pixeles de anchura respecto al protagonista*/
void soltarBombas(int indice){
int posY=avionProta.locy;
if ( ( aviones[indice].locy>= posY-5 ) && ( aviones[indice].locy<= posY+5) ){
bombasDeBombardero[numBombasSueltas].restablecer();
//suena un sonido;
audio.play();
/*se situa el disparo fuera de los límites del avion enemigo*/
bombasDeBombardero[numBombasSueltas].nuevaPosicion(
aviones[indice].locx-3, aviones[indice].locy+3 );
/* esto proporciona el numero de disparo realizado desde 0 a numBombasSueltas*/
numBombasSueltas=(numBombasSueltas+1)%(numBombas*numAviones);
}
}
/*Carga los disparos de los aviones enemigos*/
void cargarBombas(){
for(int i=0;i<numBombas*numAviones;i++){
bombasDeBombardero[i]=new Disparo(bomba,18,18);
}
}
/*comprueba si el disparo i ha colisionado con el avion protagonista*/
boolean comprobarAcierto(int i){
boolean acertar=false;
int x1=bombasDeBombardero[i].locx;
int y1=bombasDeBombardero[i].locy;
int ancho=bombasDeBombardero[i].anchura;
int alto=bombasDeBombardero[i].altura;
if (avionProta.intersecta(x1,y1,x1+ancho,y1+alto)){
// avionProta.colision();
bombasDeBombardero[i].suspender();
audio1.play();
acertar=true;
}
return acertar;
}
/*actualiza las posiciones de los disparos de los enemigos: si ha rebasado el margen
izquierdo del applet debe desaparecer y si no avanza horizontalmente a la izquierda
40 pixeles*/
void actualizarBombas(){
boolean acerto;
for(int i=0;inumBombas*numAviones;i++){
if (bombasDeBombardero[i].esVisible()){
acerto=comprobarAcierto(i);
if (bombasDeBombardero[i].locxminimoX){
bombasDeBombardero[i].suspender();
}
if (acerto==false){
bombasDeBombardero[i].nuevaPosicion(
bombasDeBombardero[i].locx-40, bombasDeBombardero[i].locy );
}
}
}
}
/*invoca a todos los métodos pertinentes*/
public void actualizar(Disparo proyectiles[]){
actualizarBombas();
avionDerribado(proyectiles);
ponerAcero(posicionSalidaAviones);
actualizarAviones();
}
/*devuelve todos los aviones enemigos*/
public Avion[] devolverAviones(){
return aviones;
}
/*devuelve el avion protagonista*/
public Avion devolverAvionProta(){
return avionProta;
}
/*pintar los disparos y aviones enemigos y al protagonista*/
public void pintar(Graphics g){
for(int i=0;inumBombas*numAviones;i++){
if (bombasDeBombardero[i].esActivo()){
bombasDeBombardero[i].pintar(g);
}
}
for(int i=0;inumAviones;i++){
if (aviones[i].esActivo()){
aviones[i].pintar(g);
}
}
avionProta.pintar(g);
}
}
CONSTRUYENDO EL APPLET
Bien, llegados a este punto, solo nos falta por construir el applet que instanciará a las clases controladoras y que permitirán dar sentido al videojuego. Aquí debemos introducir un aspecto crítico: el doble buffer. A la hora de realizar un videojuego, se debe aplicar una pequeña técnica que permite que las imágenes no tiemblen. Si no se aplicase en cada repintado de la escena se produciría una mezcla de imágenes entre el pintado nuevo los objetos en movimiento en primer plano y el color de fondo, provocando la apariencia de un molesto temblor visual. Los diseñadores de videojuegos aplican el doble buffer, que consiste en pintar en cada refresco todos los objetos en una imagen oculta, y plasmarla toda ella en el componente gráfico que se trate.
Así, digamos que el doble buffer actua así:
![]() |
| Figura 2: Utilizacion del doble buffer |
Bien, ahora mismo vayamos al applet principal. En el applet se utiliza un hilo. Se hará uso de un refresco: es decir, cada un cierto periodo de tiempo, muy pequeño y del orden de milisegundos, se realizará un repintando de la escena del videojuego, actualizando y modificando las posiciones de todos los objetos en movimiento, lo cual provocará el efecto del ansiado movimiento.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Videojuego extends Applet implements Runnable,KeyListener{
Thread animacion;
Graphics fueraDeEscena;
Image imagen;
//en milisegundos
static int REFRESCO=60;
// las imágenes que representaran a lo que indican
Image avionEnemigo,avionProtagonista,bomba,proyectil;
//sonidos q se realizaran al disparar
AudioClip audio,audio1;
//instancia de la clase ControladorAviones
ControladorAviones ca;
//instancia de la clase ControladorAviones
ControladorEstrellas ce;
// instancia de la clase ControladorDisparos
ControladorDisparos cd;
//dimensiones del applet
int altura,anchura;
//le otorgamos la velocidad al avion prota
int velocidadAvionProta;
public void init(){
//hallamos la anchura del applet
anchura=size().width;
//hallamos la altura del applet
altura=size().height;
//Dotamos de eventos de teclado al applet
addKeyListener(this);
//color de fondo rojo
setBackground(Color.red);
//cargamos las imágenes del videojuego
cargarImagenes();
//cargamos los sonidos del videojuego
audio=getAudioClip(getDocumentBase(),"sonidos/Bong.wav");
audio1=getAudioClip(getDocumentBase(),"sonidos/Laser.wav");
ce=new ControladorEstrellas(anchura,altura,500);
ca=new ControladorAviones(anchura, altura, avionProtagonista,
avionEnemigo, bomba, audio1, audio);
cd=new ControladorDisparos(anchura, altura, ca.devolverAviones(),
proyectil, audio);
//crear el buffer de pantalla
imagen=createImage(anchura,altura);
fueraDeEscena=imagen.getGraphics();
velocidadAvionProta=20;
}
/*Utilizamos la util clase de MediaTracker en este método, que aguarda a que todas
las imágenes estén guardadas*/
public void cargarImagenes(){
MediaTracker t=new MediaTracker(this);
proyectil=getImage(getCodeBase(),"imagenes/ufo0.GIF");
t.addImage(proyectil,0);
avionProtagonista=getImage(getCodeBase(),"imagenes/avion1.gif");
t.addImage(avionProtagonista,0);
avionEnemigo=getImage(getCodeBase(),"imagenes/avion2.gif");
t.addImage(avionEnemigo,0);
bomba=getImage(getCodeBase(),"imagenes/ufo2.GIF");
t.addImage(bomba,0);
/*espera a que se carguen todas las imágenes*/
try{
t.waitForAll();
}catch(InterruptedException e){}
/*comprueba si se ha producido algun error;*/
if (t.isErrorAny()){
showStatus("Error al cargar las imagenes");
}
else if (t.checkAll()){
showStatus("Imagenes suficientemente cargadas");
}
}
/* Método responsable de la interacción total entre el jugador y el videojuego,
desplanzando en tiempo real la posición del avió protagonista*/
public void keyPressed(KeyEvent el){
//Obtenemos el código de la tecla pulsada
int numeroTecla=el.getKeyCode();
//hallamos la coordena X actual del avion protagonista
int ord=ca.avionProta.locx;
//hallamos la coordena Y actual del avion protagonista
int abs=ca.avionProta.locy;
/*Si hemos pulsado el botón del cursor derecho el avión retrocede hacia la izquierda*/
if (numeroTecla==KeyEvent.VK_LEFT){
if (ord>velocidadAvionProta){
ca.avionProta.nuevaPosicion(ord - velocidadAvionProta, abs);
}
}
/*Si hemos pulsado el botón del cursor derecho el avión retrocede hacia la derecha*/
if (numeroTecla==KeyEvent.VK_RIGHT){
if (ord<anchura-velocidadAvionProta){
ca.avionProta.nuevaPosicion(ord + velocidadAvionProta, abs);
}
}
/*Si hemos pulsado el botón del cursor superior el avión asciende hacia arriba*/
if(numeroTecla==KeyEvent.VK_UP){
if (abs>velocidadAvionProta){
ca.avionProta.nuevaPosicion(ord,abs-velocidadAvionProta);
}
}
/*Si hemos pulsado el botón del cursor inferior el avión desciende hacia abajo*/
if(numeroTecla==KeyEvent.VK_DOWN){
if (abs<altura-velocidadAvionProta){
ca.avionProta.nuevaPosicion(ord,abs+velocidadAvionProta);
}
}
/*Si hemos pulsado la barra espaciadora producimos un disparo del avión, indicando
la posición de salida del disparo, que es la posición del avión protagonista*/
if(numeroTecla==KeyEvent.VK_SPACE){
cd.dispararFuegoAvionProta(ca.avionProta.locx,ca.avionProta.locy);
}
}
/* Métodos de la interfaz KeyListener a los que nos damos código*/
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){}
/*Método de creación del hilo del applet*/
public void start(){
animacion=new Thread(this);
if (animacion!=null){
animacion.start();
}
}
/*Método que llama al método de actualización de cada clase controladora. METODO CLAVE*/
public void iniciarControladores(){
cd.actualizar();
ca.actualizar(cd.devolverDisparos());
ce.actualizar();
}
/*Esta redifinición de update es básica para que el doble buffer funcione correctamente*/
public void update(Graphics g){
paint(g);
}
/*El método paint del applet se encargará de pintar todos los objetos en movimiento,
para lo cual llamará al método pintar de cada clase controladora*/
public void paint(Graphics g){
fueraDeEscena.setColor(Color.black);
//borrar el buffer oculto
fueraDeEscena.fillRect(0,0,anchura,altura);
ca.pintar(fueraDeEscena);
ce.pintar(fueraDeEscena);
cd.pintar(fueraDeEscena);
/*vuelca el buffer oculto en el buffer actual*/
g.drawImage(imagen,0,0,this);
}
/* Método invocado cuando se ejecuta el start del hilo animación y que es el
responsable de producir un refresco en la animación y que continuamente se repinte
la escena con las respectivas actualizaciones de las posiciones de todos los objetos
en movimiento/*
public void run(){
while (true){
repaint();
/*llamada a las actualizaciones de todos los objetos en movimiento*/
iniciarControladores();
Thread.currentThread().yield();
try{
/*refresco del videojuego*/
Thread.sleep(REFRESCO);
}catch(Exception e){}
}
}
/*El hilo se detiene si se cierra la ventana del applet*/
public void stop(){
if(animacion!=null){
animacion.stop();
animacion=null;
}
}
}
RESULTADO DEL VIDEOJUEGO
Cuando se ejecute el applet debiera verse algo similar a la imagen abajo representada, dependiendo del dibujo elegido. Así que, podríamos estar satisfechos del resultado, después de tantos avatares.
| Figura 3: Videojuego Ruly |
En el enlace de abajo podeis ver el videojuego en accion. Eso si, tened instalado el JRE 1.4.1 para evitar problemas en la visualización.
FASES POR REALIZAR
Ahora quedaría por definir una presentación, el nivel de vida del avión protagonista, frases significativas animando al jugador...etc...Si os ha gustado este artículo, esperad al tercero y recordad: vuestra PASIÓN hará el resto. ;)
Recursos
[Videojuego-en-accion] Videojuego en accion,
http://www.javared.com/Videojuego1-0Ruly.htm
Acerca del autor
Raúl Bonachía Castillo
Raúl Bonachía Castillo (Ruly). Licenciado en Matemáticas por la U.R,
y un gran apasionado por el desarrollo de juegos en java, y deseoso
por emular juegos multijugador en red de calidad en esa plataforma.
Actualmente trabaja en el desarrollo de un proyecto para la creación
de un sistema de edición de acceso universal para la empresa Educaline S.L
j2se 


Reader Comments