You are on page 1of 13

Programar un videojuego en Java.

Fecha de creación: 10.01.2003

Revisión 1.0 (30.01.2003)

Raúl Bonachía Castillo (rbonachia AT educaline DOT com)

http://www.javaHispano.org

Copyright (c) 2002, Raúl Bonachía Castillo. Este documento puede ser distribuido solo bajo los
términos y condiciones de la licencia de Documentación de javaHispano v1.0 o posterior (la última
versión se encuentra en http://www.javahispano.org/licencias/).
Programar un videojuego en Java.

Programar un videojuego en Java.


La intención de estos artículo es proporcionar una técnica para poder
organizar la programación de un sencillo videojuego en 2D utilizando J2SE. El
propósito es estructurar la mentalidad del programador para atacar el objetivo
de emular un videojuego, un juego en movimiento. Para tal fin, desarrollaremos
uno sencillo.
La idea es que todo lo escrito sea criticable. Mi experiencia en Java es
reciente y seguramente todo sea muy mejorable, pueda optimizarse de alguna
manera...etc. Pero como me suele gustar decir, lo importante es ofrecer
PASIÓN a lo que dedicas tu tiempo. Con ello quiero animar a quienes puedan
aportar conocimientos en estos temas a que escriban algo parecido a lo que se
pretende con estos artículos, para favorecer la difusión y aprendizaje del
desarrollo de juegos en java, como Java3D...etc Aunque Java no parece ser la
plataforma adecuada para desarrollar juegos o videojuegos, ¿es impensable
que algún día cambie tal situación?. Opinad e ilustrarnos.

Síntesis.
En este artículo vamos a introducir los conceptos básicos que nos permitirán desarrollar
un videojuego sencillo en posteriores entregas. Así, al acabar la lectura del presente
tutorial habremos creado las siguiente clases (pequeñas y comprensibles): En este
artículo vamos a introducir los conceptos básicos que nos permitirán desarrollar un
videojuego sencillo en posteriores entregas. Así, al acabar la lectura del presente tutorial
habremos creado las siguiente clases (pequeñas y comprensibles):
» Clase Molde

» Clase Dimension2D

» Clase Rectangulo

» Clase Estrella

» Clase Imagen

» Clase Avion

» Clase Disparo

1. Clases desarrolladas

Y estas dos interfaces:


» Interfez Colisionable

» Interfez Movimiento

2. Interfaces desarrolladas

Página 2
Programar un videojuego en Java.

NOTA: no acentuaré nunca nombres de métodos ni de clases

Primeros conceptos.
No olvidemos nuestro objetivo. Programar un videojuego. Bien, para ello
concentrémonos en uno. Necesitaremos:
1. Un argumento

2. Un componente gráfico en el que se produzca la acción del argumento.


(eligiremos el applet).
3. Objetos en movimiento que den vida al argumento.

3. Lo que necesitamos

Argumento.
Somos un avión, y nos ataca un numero incierto de aviones enemigos. ¡¡¡Nosotros
tenemos que defendernos!!!. Ellos disparan fuego y nosotros tenemos la capacidad de
disparar también, siempre en trayectoria horizontal. (Pero claro, eso es modificable. En
una mejora del juego, ¿por qué no introducir trayectorias sinusoidales...?. Puede
programarse...) Nuestra capacidad de movimiento se limita a ascender y descender en
vertical, y a desplazarnos a izquierda y derecha horizontalmente. Nuestros enemigos se
desplazan horizontalmente de derecha a izquierda, surgiendo del extremo derecho de la
pantalla y desapareciendo por el extremo izquierdo de ella. Si alcanzamos a alguno con
un solo disparo, desaparece de la pantalla. ¡Lo hemos eliminado!. Ello debiera suponer
una puntuación, preestablecida anteriormente. Ahora bien, si sucede vicerversa, si son
ellos lo que nos alcanzan...bueno, seamos generosos con nosotros mismos.
Dispondremos de un nivel de vida. No nos eliminarán del juego hasta que hayamos
recibido un cierto número de impactos.
Como cualquier batalla que se precie, debemos enmarcarla dentro de una escena
amigable. Por ejemplo, una noche tachonada de estrellas. Programaremos estrellas que
se desplazan también horizontalmente, independientemente de lo que suceda en el
campo de batalla, proporcionando una mayor sensación de movimiento.
Hay ciertos elementos que no deben faltar, tales como avisos de mensajes (suponga
que hemos eliminado un elevado número de aviones, como recompensa podríamos
quedar inmunes a los disparos enemigos durante un cierto lapso de tiempo), indicándonos
ciertas situaciones, un indicador gráfico del nivel de vida ( lo emularemos mediante una
corona circular, cuyo color desciende progresivamente a medida que recibimos impactos),
sonidos al disparar ...etc. Estos pequeños detalles configuran y dar cuerpo al videojuego,
permitiendo que el usuario se sienta más protagonista e identificado con el argumento.
Este breve esquema resulta más que suficiente para clarificar cuál será nuestro objetivo
y podría representar la primera pantalla del videojuego. En una segunda pantalla, el
protagonista podría ser un tanque, con distintas posiciones para su cañón en un ángulo
de 180 grados. Ahora los aviones nos bombardearían y sus proyectiles tendrían
desplazamientos verticales.....Durante el desarrollo de este tutorial, en principio nos
limitararemos a programar la primera pantalla, pero hecho esto lo demás no debiera tener

Página 3
Programar un videojuego en Java.

mayor problema.

Componente gráfico.
He aquí un tema crucial. Vamos a utilizar un applet. Por varias razones. La primera,
porque es lo que recomendaba el libro que he seguido. Segundo, porque da la
oportunidad de utilizarlo en los navegadores, y tercero porque la herramienta appletviewer
permite visualizar casi siempre todos nuestras variaciones sin mayores problemas. Para
programar el juego utilizé el IDE Jcreator. Con él u otro editor se hará la tarea más fácil. Si
no, si estás empezando y no dispones de ninguno no te preocupes. El block de notas te
sirve igualmente.
Alternativas: podría hacerse con otro componente gráfico distinto de un applet. No se
alteraría demasiado la programación. Además, daría la oportunidad de utilizar Java Web
Star... Una u otra alternativa parecen igualmente razonables. De todas formas, podría ser
un buen punto para dar lugar a la discusión.
Como todo esto es muy opinable, yo opto por elegir un applet.

Objetos en movimiento.
Denoto como objetos en movimiento a todos aquello que van a formar parte del
videojuego y que son visibles o no, según la situación. Ejemplo de ellos serían las
estrellas, los disparos, los aviones..... Todos ellos tienen un denominador común: son
entes pertenecientes al juego, aunque su naturaleza y funcionalidad sean diferentes. Aquí
entra el concepto de modularidad. Tenemos que diseñar el programa teniendo en cuenta
que debemos poder eliminar o añadir elementos nuevos sin destrozar el código de forma
severa. ¿Cómo se consigue esto?.Utilizando adecuadamente clases jerárquicas,
extendiendo unas de otras, de tal manera que la relación de herencia nos permita
sobreescibir métodos para la aparición de nuevos elementos. Del libro al que se hace
referencia en la bibliografía extraje las siguientes ideas para organizar las clases
Una clase madre, que denotaremos Molde. Una instancia de Molde representa
cualquier objeto participante en el videojuego, pero en su concepto más abstracto.
Contendrá métodos para decidir si es visible o no y si está activo o no. Heredaremos de
Molde para construir las clases Dimension2D y Imagen. Estas clases son fundamentales.
De Dimension2D obtendremos aquellos objetos que queramos construir y que se
visualizarán sin utilizar imágenes, usando procedimientos de pintura de Java. De Imagen
obtendremos, en cambio, aquellos objetos que necesitarán una imagen para ser
representados. Así, por ejemplo, si necesitamos que aparezca un rectángulo que
ascienda y descienda (para simular una maza que aplaste aviones) heredaremos de
Dimension2D. Y para simular a los aviones en sí necesitaremos heredar de Imagen, con
una clase que se denote MolveAvion, por ejemplo. De Avion haremos que hereden
diferentes tipos de aviones, si es necesario. Bombardero, Caza....lo que haga falta, cada
uno con la imagen que le caracterice.

Interfaces básicas.
En nuestro esfuerzo por adquirir una destreza y una técnica lo más general posible,
emplearemos interfaces. Las interfaces se denominarán:

Página 4
Programar un videojuego en Java.

1. Interfaces básicas

¿Por qué hacer uso de ellas?. Porque para nosotros, todos los objetos van a ser
objetos en movimiento, algunos de ellos con la capacidad de poder intersecar unos con
otros. Luego en un procedimiento de abstracción, nos dará igual que sea una estrella que
un avión. Lo cierto es que la estrella y el avión se mueven, luego debemos dotarles de
métodos para que ACTUALICEN sus posiciones en el componente gráfico. Para eso se
utilizan las interfaces: dotan de métodos de nombre común a las clases que las
implementan y que deben realizar misiones similares. Veremos posteriormente que son
ciertamente utiles en aras de una mayor organización en la programación.

Interfaz Movimiento.

interface Movimiento{
/* Actualizará (modificará) la antigua posición del Molde en cuestión a
la coordenada (x,y) */
public abstract void nuevaPosicion(int x, int y);
/* En caso de necesidad, podemos asignarle mayor velocidad
aparente de movimiento al molde, llamando a este método*/
public abstract void nuevaVelocidad(int x, int y);
}

Interfaz Colisionable.
Aclaraciones: cuando hablamos de colisión de moldes, cada molde está representado
por una imagen (si hereda de Imagen), o una figura geométrica pintada por java (si
hereda de Dimension2D). Aquí debemos trabajar con una limitación. Para imaginar la
colisión de la forma más general posible, debemos considerar siempre el rectángulo más
pequeño en el que se inscribe la imagen o figura, respectivamente, y trabajar con las
coordenadas de la esquina superior izquierda e inferior derecha para poder hablar de
intersección (colisión) de rectángulos, que es mucho más fácil que hablar de otro tipo de
colisiones.

interface Colisionable{
/*indica al molde que implemente esta interfaz si ha colisionado con
otro molde ajeno encapsulado por el rectángulo de menor dimensión con
bordes paralelos a los ejes X e Y, de coordenadas (x1,y1) e (x2,y2)*/
public boolean intersecta(int x1, int y1, int x2, int y2);
// Llamaremos a este método si la intersección se ha producido.
public void colision();
}

NOTA: Para determinar si dos moldes han colisionado, podemos aplicar esta caracterización, que es muy útil.

Si { (x1,y1),(x2,y2) } y { (x3,y3),(x4,y4) } conforman los límites de dos moldes ambos


intersecan si y solo si: (x2>=x3) && (x4>=x1) && //las x se solapan

Página 5
Programar un videojuego en Java.

(y2>=y3)&&(y4>=y1)//las y se solapan

2. Detección de colisiones

Jerarquía de clases básicas.


Poco a poco, vayamos diseñando las clases necesarias para poder desarrollar después
aquellas que representen los aviones, disparos, estrellas....etc. Mostremos sus relaciones
jerárquicas para ponernos en situación:

3. Jerarquía de clases

Clases báscias.
Construyendo la clase Molde.

import java.awt.Graphics;
abstract class Molde{
protected boolean visible; //¿es visible el molde?
protected boolean activo; //¿ Es actualizable el molde?
//metodos abstractos
abstract void pintar(Graphics g);
//metodos basicos;
public boolean esVisible(){
return visible;
}
public void cambiarVisible(boolean b){
Página 6
Programar un videojuego en Java.

visible=b;
}
public boolean esActivo(){
return activo;
}
public void cambiarActivo(boolean b){
activo=b;
}
//Suspende el molde
public void suspender(){
cambiarVisible(false);
cambiarActivo(false);
}
//Reactiva el molde
public void restablecer(){
cambiarVisible(true);
cambiarActivo(true);
}
}

Los métodos son bastante claros. Con ellos determinamos si la clase que herede de
Molde, y que representará un objeto visual, está visible y/o activo y nos damos la
posiblidad de modificarlo cuando sea necesario. Además, contamos con dos métodos
BÁSICOS, como son pintar y actualizar. Todos los objetos heredados de molde serán
supceptibles de ser pintados, (de eso se trata...), y deberán actualizarse. Este concepto
es FUNDAMENTAL. Cada objeto que pertenezca al videojuego estará en movimiento,
aunque esté parado en algún instante. Eso significa que deberemos ACTUALIZAR su
posición, es decir, modificarla. Esto habrá que hacerlo para todos los objetos. Aunque
pueda parecer un poco complicado a priori (si hay mucho objetos...), se solucionará
utilizando unas clases Controladoras. Habrá una ControladoraAviones, otra
ControladoraDisparos...etc, que se encargarán de actualizar A LA VEZ, todos los objetos
que controlen. Así, el repintado se realizará sin mayores problemas.
Poco a poco....

Construyendo la clase Dimension2D.

import java.awt.Color;
abstract class Dimension2D extends Molde{
protected int locx;//coordenada X del molde
protected int locy;//coordenada Y del molde
Color color;
boolean relleno;
//si tiene color de relleno o no
public boolean obtenerRelleno(){
return relleno;
}
public void cambiarRelleno(boolean b){
relleno=b;
}
public void cambiarColor(Color c){
color=c;
}
public Color obtenerColor(){
return color;
}
}

Página 7
Programar un videojuego en Java.

locx, locy representarán las coordenadas en el componente gráfico seleccionado del


molde en cuestión. Tener en cuenta que todo videojuego, este en particular, depende
continuamente de las posiciones y, por tanto, de las coordenadas. Habrá que hacer uso
de estas variables continuamente, tanto aquí como en Imagen.
Para observar cómo utilizar la clase Dimension2D construyamos la clase Rectangulo.

Construyendo la clase Rectangulo

import java.awt.Graphics;
import java.awt.Color;
class Rectangulo extends Dimension2D implements
Movimiento,Colisionable{
public int anchura,altura;
//CONSTRUCTOR de Rectangulo
public Rectangulo(int x,int y,int anchura, int altura,Color c){
locx=x;
locy=y;
this.anchura=anchura;
this.altura=altura;
color=c; //Inicializamos variables de
Dimension2D
relleno=false;
restablecer();
cambiarRelleno(true);
}
/* cambiarPosición es fundamental para ACTUALIZAR la
posición. ( actualizar=modificar)*/
public void nuevaPosicion(int x, int y){
locx=x;
locy=y;
}
/* si en algún momento deseamos INCREMENTAR la ACTUALIZACION y,
por tanto, incrementar la velocidad aparente de movimiento.*/
public void nuevaVelocidad(int vx, int vy){
locx+=vx;
locy+=vy;
}
// Para saber si intersecta con un avion, un disparo...etc
public boolean intersecta(int x1, int y1, int x2, int y2){
return visible&&(x2>=locx)
&&(locx+anchura>=x1)&&(y2>=locy)
&&(locy+altura>=y1);
}
public void colision (){
suspender();/*Si le damos la función de aplastar
aviones, lo lógico es que desaparezca al intersecar con uno.*/
}
public void cambiarOrigen(int x,int y){
locx=x;
locy=y; //Método Propio de Rectangulo
}
public void actualizar(int an,int al){//Método Propio de
Rectangulo
anchura=an;
altura=al;
}
public void pintar(Graphics g){
if (visible){
g.setColor(color);
if (relleno){
g.fillRect(locx,locy,anchura,altura);
}

Página 8
Programar un videojuego en Java.

else{
g.drawRect(locx,locy,anchura,altura);
}
}
}
}

Con Rectangulo obtenemos un molde Dimension2D que define a un rectángulo: sus


coordenadas x,y, respecto a la esquina superior izquierda por él definida, y su anchura y
altura. Además, le asignamos un color y le proporcionamos la posibilidad de
ACTUALIZAR su posición gracias a la interfaz Movimiento y de PINTARLO en un
componente gráfico. Por otra parte, es supceptible de colisionar con otros objetos al
implementarle la interfaz Colisionable. Paciencia, todavía no hemos realizado el código
necesario para ver en acción su utilidad. Para ello necesitaremos un hilo dentro del applet,
pero esto lo veremos en el/los siguientes artículos. Sigamos viendo más código.
Ahora, veamos cómo construir la clase Estrella, que representa a una estrella.

Construyendo la clase Estrella.

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
public class Estrella extends Dimension2D implements Movimiento{
Random r;
int aleatorio;
boolean apagar;
Estrella(int x, int y){
r=new Random();
this.apagar=apagar;
/*para ofrecer vistosidad, otorgaremos color aleatorio
a cada Estrella*/
color=new
Color(r.nextInt(255),r.nextInt(255),r.nextInt(255));
cambiarVisible(true);// Estrella nacerá visible
locx=x;
locy=y;
}
// cambiarPosición es fundamental para ACTUALIZAR la
posición.
public void nuevaPosicion(int x, int y){
locx=x;
locy=y;
}
/* si en algún momento deseamos INCREMENTAR la ACTUALIZACION y,
por tanto, incrementar la velocidad aparente de movimiento.*/
public void nuevaVelocidad(int vx, int vy){
locx+=vx;
locy+=vy;
}
void pintar(Graphics g){
g.setColor(color);
/* Un punto se puede representar como una recta de
mismo origen y final.*/
g.drawLine(locx,locy,locx,locy);
}
}

Página 9
Programar un videojuego en Java.

Aquí introducimos un aspecto fundamental que forma parte de cualquier videojuego:


aleatoriedad. La clase Random (java.util.Random) proporcina números aleatorios. En
concreto, el método nextInt(n) obtiene un número cualesquiera entre 0 y n. A la estrella
vamos a darle color aleatorio. Volveremos a utilizarlo posteriormente.

Construyendo la clase Imagen.

import java.awt.Image;
import java.awt.Graphics;
class Imagen extends Molde{
protected int locx; //coordenada x respecto esquina superior
izqda.
protected int locy; // coordenada y respecto esquina superior
dcha
protected int anchura,altura; //dimensiones de la imagen
protected Image imagen; // la imagen
//CONSTRUCTORES
/*Construimos la imagen con coordenadas (0,0) en su esquina
superior izquierda*/
public Imagen(Image i, int anchura, int altura){
locx=0;
locy=0;
imagen=i;
if (imagen!=null){
this.anchura=anchura;//obtener anchura de la
imagen
this.altura=altura;// obtener altura de la
imagen
}
restablecer();
}
/*Construimos la imagen con coordenadas (x,y) en su esquina
superior izquierda */
public Imagen(int x, int y,Image i, int anchura, int altura){
locx=x;
locy=y;
imagen=i;
if (imagen!=null){
this.anchura=anchura;//obtener anchura de la
imagen
this.altura=altura;// obtener altura de la
imagen
}
restablecer();
}
public void actualizar(){}
public void pintar(Graphics g){
if (visible){
g.drawImage(imagen,locx,locy,anchura,altura,null);
}
}
}

Detengámonos con esta clase, porque es muy importante y de ella heredarán todos los
objetos (aviones y disparos) de los que hará gala el videojuego. Lograremos pintar la
imagen que deseemos, sea cual sea, en el applet que va a a ser soporte de nuestro
videojuego. Así, en el applet original, cargaremos las imágenes que consideremos
oportunas y a la hora de crear los objetos que hereden de Imagen se los pasaremos al

Página 10
Programar un videojuego en Java.

constructor.
Veamos ahora ya cómo construir la clase Avion. Notemos ante de ello que será
necesario implementarle la interfaz Colisionable, lo que posibilitará que un objeto de Avión
detecte colisiones con objetos en movimiento de diferente naturaraleza como otros
aviones, disparos, rectángulos....Percatarse de la importancia y el poder que ello
proporcionará al videojuego. Por supuesto, también hay que dotarle de la interfaz
Movimiento.
NOTA: He considerado oportuno poder dimensionar la imagen a la hora de dibujarla con
g.drawImage(...,anchura,altura,null). Si se observase cierta lentitud en el juego es posible que esa fuese una de las
causa. En ese caso intentad sustituir esa línea por g.drawImage(imagen,locx,locy,null) dotándole, pues, de su dimensión
real.

Construyendo la clase Avion.

import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.Image;
import java.awt.Graphics;
public class Avion extends Imagen implements Colisionable,Movimiento{
protected AudioClip audio;
//CONSTRUCTOR de Avion
public Avion(Image avion,AudioClip audio, int anchura, int
altura){
super(avion,anchura,altura); //llama al constructor de
Imagen
this.audio=audio; /* proporciona un sonido que
utilizaremos cuando deseemos.*/
suspender(); /*cuando creamos el objeto Avion, no está
activo.*/
}
// nuevaPosición es fundamental para ACTUALIZAR la posición.
public void nuevaPosicion(int x, int y){
locx=x;
locy=y;
}
/* si en algún momento deseamos INCREMENTAR la ACTUALIZACION y,
por tanto, incrementar la velocidad aparente de movimiento.*/
public void nuevaVelocidad(int vx, int vy){
locx+=vx;
locy+=vy;
}
/* devuelve cierto si un objeto delimitado por el rectángulo de
coordenadas (x1,y1),(x2,y2) interseca con nuestro Avion*/
public boolean intersecta(int x1, int y1, int x2, int y2){
return visible&&(x2>=locx)
&&(locx+anchura>=x1)&&(y2>=locy)
&&(locy+altura>=y1);
}
// Si nuestro Avion ha muerto, sonará un sonido y lo
desactivaremos.
public void colision(){
audio.play();
suspender();
}
}

Página 11
Programar un videojuego en Java.

Notemos la pecualiaridad de esta clase: le hemos dotado de sonido. El sonido


proporciona credibilidad y aumenta la interacción con el usuario. No deberían faltar este
tipo de cuestiones, así que nosotros no vamos a ser menos. Ahora bien, procuremos que
no ocupe mucho memoria el que elijamos. Podremos utilizar extensiones .wav, .au..etc.

Construyendo la clase Disparo.

import java.awt.Image;
public class Disparo extends Imagen implements Movimiento,Colisionable{
/* CONSTRUCTOR. */
public Disparo(Image disparo, int anchura, int altura){
super(disparo,anchura,altura);
suspender();/*Los disparos nacerán inactivos y no
visibles.
Estarán en la recámara de los aviones*/
}
public void nuevaPosicion(int x, int y){
locx=x;
locy=y;
}
public void nuevaVelocidad(int vx, int vy){
locx+=vx;
locy+=vy;
}
public boolean intersecta(int x1, int y1, int x2, int y2){
return visible&&(x2>=locx)
&&(locx+anchura>=x1)&&(y2>=locy)
&&(locy+altura>=y1);
}
public void colision (){
suspender();/*Si un disparo alcanza a un avión aquel
debe desaparecer.*/
}
}

Bien, llegados a este punto ya disponemos de las clases necesarias para simular a los
elementos del videojuego, como son las estrellas, los aviones y los disparos que efectúen
los aviones enemigos y el protagonista. Todos disponen de métodos para ACTUALIZAR
su posición y algunos métodos para detectar colisiones.

Fases por realizar


Ahora, el siguiente paso será construir las clases Controladoras que hagan nacer a
todos aquellos objetos en movimiento y determinen tanto las interacciones entre ellos
como sus actualizaciones.
Necesitaremos pues a:
1. Clase ControladorAviones

2. Clase ControladorDisparos

3. Clase ControladorEstrellas

4. Lo que nos falta por hacer.

Página 12
Programar un videojuego en Java.

Podremos añadir, posteriormente, para dar vistosidad al juego, una clase que emule
una corona circular y que represente el nivel de vida del protagonista.
Podríamos, también, incluir una presentación, y dotar al juego de un menu incluyendo el
applet en una frame (ventana), para Iniciar Juego, Finalizar Juego...e incluso, como meta
final, dotarle de la opción Guardar Partida, haciendo uso de una Base de Datos. Eso lo
decidiremos en el/los posteriores artículos.
Eso sí, más tarde, necesitaremos construir el applet principal mediante un hilo y dotarle
de métodos de eventos de teclado para que el usuario pueda interaccionar con el
videojuego. Queda mucho por hacer, pero si este artículo os han interesado seguro que
vuestra PASIÓN hará el resto. ;).

Recursos y referencias
[1] Programación de juegos en Java. (Black Art of Java in Game Programming), Joel Fan,Eric Ries, Callin
Tenitchi,

Acerca del autor


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

Copyright (c) 2002, Raúl Bonachía Castillo. Este documento puede ser distribuido solo bajo los
términos y condiciones de la licencia de Documentación de javaHispano v1.0 o posterior (la última
versión se encuentra en http://www.javahispano.org/licencias/).

Página 13

You might also like