Para hacer un juego interactivo con Java

Artículo | Escritorio | Java | Principiante | Programación con Java

En el artículo anterior ("Para hacer un juego con Java") vimos que la estructura básica de un videojuego es básicamente un ciclo infinito que ejecuta repetidamente los tres pasos siguientes:

  1. Lee los controles
  2. Ejecuta la lógica del juego
  3. Redibuja la pantalla

Para que el ejemplo fuera muy sencillo omitimos en ese artículo la parte de la interacción (el paso Lee los controles) y solamente hicimos un programa que mostraba una bola moviendose dentro de una ventana. Ahora vamos a ver cómo hacer que el jugador pueda controlar la bola con las flechas del teclado.

Un "juego" interactivo

Aquí está el fuente completo de un programa en Java que te permite emplear las flechas del teclado para mover una bola dentro de una ventana:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Demo2 extends JComponent {

    private final static int ANCHO = 512;

    private final static int ALTO = 384;

    private final static int DIAMETRO = 20;

    private float x, y;

    private float vx, vy;

    private boolean arriba, abajo, izquierda, derecha;

    public Demo2() {
        setPreferredSize(new Dimension(ANCHO, ALTO));
        x = 10;
        y = 20;
        addKeyListener(new KeyAdapter() {
                public void keyPressed(KeyEvent e) {
                    actualiza(e.getKeyCode(), true);
                }

                public void keyReleased(KeyEvent e) {
                    actualiza(e.getKeyCode(), false);
                }

                private void actualiza(int keyCode, boolean pressed) {
                    switch (keyCode) {
                        case KeyEvent.VK_UP:
                            arriba = pressed;
                            break;

                        case KeyEvent.VK_DOWN:
                            abajo = pressed;
                            break;

                        case KeyEvent.VK_LEFT:
                            izquierda = pressed;
                            break;

                        case KeyEvent.VK_RIGHT:
                            derecha = pressed;
                            break;
                    }
                }
            });
        setFocusable(true);
    }

    private float clamp(float valor, float min, float max) {
        if (valor > max)
            return max;
        if (valor < min)
            return min;
        return valor;
    }

    private void fisica(float dt) {
        vx = 0;
        vy = 0;
        if (arriba)
            vy = -300;
        if (abajo)
            vy = 300;
        if (izquierda)
            vx = -300;
        if (derecha)
            vx = 300;
        x = clamp(x + vx * dt, 0, ANCHO - DIAMETRO);
        y = clamp(y + vy * dt, 0, ALTO - DIAMETRO);
    }

    public void paint(Graphics g) {
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, ANCHO, ALTO);
        g.setColor(Color.RED);
        g.fillOval(Math.round(x), Math.round(y), DIAMETRO, DIAMETRO);
    }

    private void dibuja() throws Exception {
        SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    paintImmediately(0, 0, ANCHO, ALTO);
                }
            });
    }

    public void cicloPrincipalJuego() throws Exception {
        long tiempoViejo = System.nanoTime();
        while (true) {
            long tiempoNuevo = System.nanoTime();
            float dt = (tiempoNuevo - tiempoViejo) / 1000000000f;
            tiempoViejo = tiempoNuevo;
            fisica(dt);
            dibuja();
        }
    }

    public static void main(String[] args) throws Exception {
        JFrame jf = new JFrame("Demo2");
        jf.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
        jf.setResizable(false);
        Demo2 demo2 = new Demo2();
        jf.getContentPane().add(demo2);
        jf.pack();
        jf.setVisible(true);
        demo2.cicloPrincipalJuego();
    }
}

Para compilar y ejecutar este programa sigue los mismos pasos que para el programa del artículo anterior. La única diferencia es que ahora tienes que guardar el programa dentro de un archivo que se llame Demo2.java.

Cómo funciona el programa

Veamos ahora el programa parte por parte para entender cómo funciona. Este programa es muy similar al programa Demo1.java del artículo anterior, por lo tanto sólo vamos a explicar los cambios que le hicimos. En el artículo anterior ("Para hacer un juego con Java") puedes averiguar cómo funciona el resto del programa.

Cómo saber si está presionada una flecha del teclado

El primer cambio en el programa es que ahora tenemos cuatro nuevas variables de instancia:

private boolean arriba, abajo, izquierda, derecha;

Cada una de esas variables booleanas es verdadera cuando la tecla correspondiente del teclado está presionada. Claro que esto no ocurre automáticamente, tenemos que programar algún mecanismo para detectar cuando el usario presiona o suelta alguna de esas teclas y actualizar en ese momento la variable correspondiente.

Ese mecanismo está programado en el constructor de nuestra clase Demo2. Aquí esta el fuente del constructor, con los cambios respecto al ejemplo del artículo anterior en negritas para resaltar las diferencias:

public Demo2() {
    setPreferredSize(new Dimension(ANCHO, ALTO));
    x = 10;
    y = 20;
    addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                actualiza(e.getKeyCode(), true);
            }

            public void keyReleased(KeyEvent e) {
                actualiza(e.getKeyCode(), false);
            }

            private void actualiza(int keyCode, boolean pressed) {
                switch (keyCode) {
                    case KeyEvent.VK_UP:
                        arriba = pressed;
                        break;

                    case KeyEvent.VK_DOWN:
                        abajo = pressed;
                        break;

                    case KeyEvent.VK_LEFT:
                        izquierda = pressed;
                        break;

                    case KeyEvent.VK_RIGHT:
                        derecha = pressed;
                        break;
                }
            }
        });
    setFocusable(true);
}

Nota: otro cambio es que ya no estamos dandole un valor inicial al vector velocidad (variables vx y vy) dentro del constructor.

Los componentes de Swing permiten que se registren con ellos unos objetos listeners (escuchadores) a los que les avisan cuando ocurren ciertos eventos dentro del componente. Nuestra clase Demo2 extiende (hereda de) la clase JComponent y eso hace que sea un componente de Swing. Unos de los eventos que pueden ocurrir es que el usuario presione o suelte una tecla estando ese componente seleccionado (más adelante explicamos lo que quiere decir que un componente esté seleccionado). Para poder registarse con un componente de Swing y enterarse de los eventos relacionados con el teclado se necesita un listener que implemente la interfaz KeyListener. Esa interfaz define tres métodos, de los cuales hay dos que nos interesan: keyPressed() y keyReleased. Para no tener que implementar el tercer método, que no nos interesa para este programa, creamos una clase anómima que hereda de la clase KeyAdapter, la cual implementa la interfaz KeyListener con implementaciones "vacias" de sus métodos (que no hacen nada).

Cada vez que el jugador presiona una tecla, el componente llama el método keyPressed() de todos sus listeners de tipo KeyListener pasándoles como argumento un objeto KeyEvent. Cuando el jugador suelta la tecla, el componente llama el método keyReleased() de esos mismos listeners, una vez más pasándoles como argumento un objeto KeyEvent.

Los objetos KeyEvent tienen un método getKeyCode() que devuelve un entero indicando cual fue la tecla que se presionó o se soltó. La clase KeyEvent también define unas constantes que permiten identificar con un nombre simbólico el entero que corresponde a cada tecla. Las constantes para las flechas son: VK_UP, VK_DOWN, VK_LEFT y VK_RIGHT.

Nuestras implementaciones de keyPressed() y keyReleased() obtienen el key code de la tecla correspondiente y se lo pasan al método actualiza(): un método privado de nuestra clase anónima. También le pasan un valor booleano que es verdadero cuando se presiona una tecla y falso al soltarla. El método actualiza() simplemente usa un switch para ver si el key code de la tecla es el de alguna de las flechas y, en caso de que sea así, almacena el valor booleano en la variable correspondiente.

Una venta de Swing puede contener varios componentes. En un momento dado sólo uno de esos componentes es el componente activo. Es decir que únicamente uno de esos componentes es el que está interactuando con el usuario (imaginate una ventana con varios campos de texto, lo que escribes aparece solamente en uno de esos campos). Típicamente, el usuario selecciona el componente activo con un click del mouse.

En Swing, cuando un componente es el componente activo se dice que "está enfocado" (es el foco de antención). Para que un componente pueda estar enfocado necesitamos indicarle a Swing que es un componente enfocable (focusable). Eso es lo que hacemos con la última linea del constructor:

setFocusable(true);

Física interactiva

El segundo cambio del programa es que ahora la física tiene que tomar en cuenta si alguna de las teclas de las flechas está presionada. Este es el nuevo método para calcular la física:

private void fisica(float dt) {
    vx = 0;
    vy = 0;
    if (arriba)
        vy = -300;
    if (abajo)
        vy = 300;
    if (izquierda)
        vx = -300;
    if (derecha)
        vx = 300;
    x = clamp(x + vx * dt, 0, ANCHO - DIAMETRO);
    y = clamp(y + vy * dt, 0, ALTO - DIAMETRO);
}

Empezamos por asumir que la velocidad, tanto en su componente horizontal como en su componente vertical, es cero. Después checamos las variables booleanas que nos indican si se está presionada la tecla de alguna de las flechas y, cuando eso ocurre, modificamos el componente correspondiente del vector velocidad.

Ya que actualizamos los componentes horizontal y vertical del vector velocidad, de acuerdo a las teclas que están presionadas, los empleamos para calcular la nueva posición de la bola. Al igual que en el ejemplo anterior, multiplicamos la velocidad por el tiempo transcurrido y le sumamos el resultado a la posición actual empleando las expresiones x + vx * dt y y + vy * dt. Aquí también debemos tener cuidado de que que la bola no se salga de la ventana. Esta vez decidimos emplear un método llamado clamp() para asegurar que los valores de las variables x y y se mantengan dentro de los límites válidos. El método clamp() espera tres argumentos: el nuevo valor, el límite inferior y el limite superior. Cuando el nuevo valor está dentro de los límites, el método clamp() simplemente devuelve ese mismo valor. Pero, cuando se sale de esos límites, devuelve el límite inferior si el nuevo valor era menor que él o el límite superior si el nuevo valor era mayor que él. En inglés la palabra clamp significa abrazadera y también existe el verbo to clamp que significa asegurar: fijar sólidamente. Estamos fijando los valores dentro de un rango válido, en el caso horizontal el valor mínimo de x es cero (cuando la bola está en el extremo izquierdo de la ventana) y el valor máximo es ANCHO - DIAMETRO (cuando la bola está en el extremo derecho de la ventana).

Y lo único que falta es la implementación del método clamp(). Este método es tan sencillo que no requiere ninguna explicación:

private float clamp(float valor, float min, float max) {
    if (valor > max)
        return max;
    if (valor < min)
        return min;
    return valor;
}

En diagonal, la bola se mueve más rápido

Ejecuta el programa Demo2 y prueba lo que pasa cuando presionas simulatáneamente la fecha derecha y la flecha abajo. Al combinar el movimiento horizontal con el movimiento vertical, la bola se mueve en diagonal. Y no sólo eso, prueba mover la bola sólo horizontalmente o verticalmente y después vuelvela a mover en diagonal. ¿Viste lo que pasa? ¡La bola va más rápido cuando se mueve en diagonal! Esto se debe a que la velocidad en diagonal es la suma de sus componentes horizontal y vertical. Si la bola se mueve de 300 pixeles hacia la derecha y, al mismo tiempo, se mueve de 300 pixeles hacia abajo, entonces la distancia que recorrio fue de más de 300 pixeles. Pero no fue de 600 pixeles, porque los desplazamientos de 300 pixeles fueron en direcciones diferentes.

Para calcular cual es la velocidad de la bola cuando se mueve en diagonal, podemos emplear el Teorema de Pitágoras: en un triángulo rectángulo la suma de los cuadrados de los catetos es igual al cuadrado de la hipotenusa. En este caso, las velocidades horizontal y vertical forman los catetos del triángulo, mientras que la suma de esas dos velocidades (la diagonal) es la hipotenusa:

Empleando el Teorema de Pitágoras, calculamos que la velocidad en diagonal de la bola es de:


424.264 pixeles/segundo. Un 41% más rápido.

En algún otro artículo explicaremos cómo hacer para que la bola vaya siempre a la misma velocidad, independientemente de la dirección en la que se esté moviendo.

Double buffering

Algo que todavía no hemos mencionado es que cuando redibujamos el contenido de la ventana hay que evitar que este sea visible mientras que estamos en medio del proceso de redibujado. No queremos que el jugador vea una imagen que todavía no está completa. Imaginate que tenemos algún juego en el cual aparecen cien bolas en la pantalla, no quieres que se vea la imagen cuando apenas haz dibujado la mitad de las bolas en su nueva posición. Para lograr esto se emplea una técnica que se llama double buffering. Esta técnica consiste en hacer todo el redibujado sobre una imagen que tenemos en memoria y, al terminar de redibujar, mandar esa imagen (donde ya está todo dibujado) a la pantalla. De esta manera el jugador nunca ve una imagen que esta dibujada "a medias".

Un detalle interesante de Swing es que dentro de su operación normal de redibujado ya está incluido el double buffering y no es necesario programarlo explícitamente. Nuestro programa, tal como está, emplea double buffering para redibujar el contenido de la ventana.

WOW

Gran tutoria!! Aunque está muy simple explica muy bien los conceptos principales... de hecho, he construido algunos juegos "a como Dios me dió a entender" y aunque no estaba tan lejos de la lógica, indiscutiblemente me hay enseñado mucho sobre la verdadera naturaleza del swing. Increible en verdad! Sigan así!!

Excelente

muy buen tutorial, sencillo y concreto, facilisimo de entender... solo que una cosa, porque mencionas como vector a los flotantes de velocidad vx y vy?? es lo unico que no entendi, porque referirse a esas variables como vectores, siendo que son simples flotantes, ya que en java un vector es otra cosa

Vectores

En este artículo la palabra "vector" se refiere al concepto de vector en matemáticas y física. Las variables vx y vy son las componentes horizontal y vertical del vector velocidad. En Java existe la clase "Vector" que sirve para almacenar una lista de valores. Es clase también toma su nombre del concepto de vector en matemáticas, ya que se podría emplear para almacenar los componentes de un vector multidimensional. En retrospectiva esa no fue una buena elección de nombre para esa clase. De hecho a partir del JDK 1.2 aparecieron nuevas clases en donde en Vez de Vector se usa más bien el nombre "List" que es mucho más apropiado.

Pregunta

que java hay que tener instalado?

yo tengo el SE y el compilador me da error

Public void paint

como le puedo hacer para que en vez de una pelotita muestre una imagen?
le intento con en ImageIcon pero no me muestra nada porque no se como integrarlo al objeto g.
Y el Math.round() se puede usar en el ImageIcon?, no entendi esta parte

Misma velocidad en direccion diagonal

Viendo el interesante aporte de este post y que no he visto en otro post o comentario la solución al movimiento de la bola roja a la misma velocidad de forma horizontal y verticual contra la diagonal.

en el metodo de fisica() añadimos lo siguiente:

if (derecha)
if (arriba){
vx = 212.13204f;
vy = -212.13204f;}
if (derecha)
if (abajo){
vx = 212.13204f;
vy = 212.13204f;}
if (izquierda)
if (arriba){
vx = -212.13204f;
vy = -212.13204f;}
if (izquierda)
if (abajo){
vx = -212.13204f;
vy = 212.13204f;}

Saludos

principiante en java

hola llevo muy poco programando por favor estoy haciendo un video juego con unas bolas pero necesito el codigo para hacer que las bolas exploten
gracias

re:principiante en java

mas que codigo te tienes que poner a jugar con los graficos y usar varias imagenes una para cada etapa de la explocion. o simplemente(mas complicado) puedes dividir la pelota en cachitos y usar algo de matematias para hacer que giren las piesas y toda la cosa

te dare un codigo que gira un arreglo de puntos que tambien puede funcionar en simple j los parametros son estos (arreglo de puntos por ejemplo {{5,2},{1,4},{5,3}} , el punto x de rotacion , y el punto y de rotacion, la cantidad de grados que girara en radianes)

public double[][] rotate(double[][] points,double x,double y, double angle){
double newPoints[][]=new double[points.length][2];
for(int i = 0;i < points.length; i++){
double angles=Math.atan2( points[i][1]-y,points[i][0]-x)+angle ;
double dist=Math.sqrt(Math.pow(points[i][0]-x, 2)+Math.pow(points[i][1]-y, 2));
newPoints[i][0]=Math.cos(angles)*dist+x;
newPoints[i][1]=Math.sin(angles)*dist+y;
}
return newPoints;
}

has tus propios codigos para que lo puedas entender mejor
|-------------------------------------------|
| G3RW4Nll-77NAMREG-GERMAN77 |
|-------------------------------------------|

TETRIS

hola que tal amigo.Primero, dejame felciitarte por el excelente post que has publicado, esta muy bueno.
Bueno te contare que tengo que hacer un tetris en java, y opte por la libreria swing(no se absoltuamente nada de la libreria solo tengo conocimientos de java en consola). Y pues, cogi tu codigo como base para hacer el juegos que estoy haciendo(como dije , un tetris), y hasta el momento he logrado que la bolita(ya lo converti en cuadraado XD) caiga desde el centro superior i que se detenga al llegar a la parte inferior(lo se lo se , practicamente no he hecho nada ).
AHora mi preugnta es, como lograr que una vez detenida el cuadrado en el fondo de la ventana, se cree otro, de diferente color...
Soy consciente de que estoy bien lejos de terminar ese proyecto(se presenta en 1.5 ssemanas) y que lo iddeal es que sean varios cuadraditos en un solo bloque(como todos concoemos asi es es el tetris), pero con eso estoy empezando...

GRACIAS DE ANTEMANO
mi correo es franco_lezcano_91@hotmail.com
te agradeceria mucho mas si me puedes dar una mano, como tutoriales que me puedan servir justo para este fin... entre otros

ta fasil

no a de ser muy complicado hacer un juego de tetris simplemente nesesitas un mapa de arrays en donde definas el color del bloque y si se forma una linea lo eliminas y para el bloque que va callendo es otro array de 4*4 de un cierto color en donde le asignas una forma especifica y luego checas la colicion solo si un bloque de color choco con otro de color del tablero.... horita estoy trabajando pero cuando me desocupe te hago una serie de videos para hacer ese juego-aunq no tendra sonido ni buenos graficos porque no los se utilisar.
|-------------------------------------------|
| G3RW4Nll-77NAMREG-GERMAN77 |
|-------------------------------------------|

TE agradesco demasiado por

TE agradesco demasiado por el simple hecho de haberme contestado.....
y entiendo que tengas otras cosas que hacer. Seguire intentando con el proyecto. Honestamente ya me habia arrepentido de hacer ese preoyecto, y estaba ya pensando en otro, pero justo hoy, empece a investigar mas sobre JFram y JPanel(Conceptos totalmente nuevos para mi). Te agradeceria si pudieras terminar esos videos lo mas antes posible...
de verdad muchas gracias , te lo agradesco mucho
nos vemos....

Siguiendo con mi

Siguiendo con mi comentario..... no importa para nada si es que no tiene buenos graficos, solo quiero que funcione lo basico, lo que realemnte es del juego.... las cosas adicionales como sonido o imagenes que hagan mas atractivo el juego no importan ... espero ansioso tus videos gracias de nuevo

ya tengo algunos videos

ya tengo algunos videos hasta haora solo tengo la presentacion del tablero y la creacion de nuevas figuras me atore en un problema pero lo dejare para despues y empesare con lo que es usar el teclado y darle vuelta a las figuras

subire los videos a mi cuenta de youtube.... tienen mala presentacion y muchos errores devido a que nunca hice un juego de este tipo por esa rason tambien subire el source code de cada video para que veas los cambios y funcione correctamente

link a mi pagina de youtube http://www.youtube.com/user/german77GL?feature=mhee
|-------------------------------------------|
| G3RW4Nll-77NAMREG-GERMAN77 |
|-------------------------------------------|

te lo agradesco demasiado...

te lo agradesco demasiado... estare viendo los videos
Dejame prsentarme(es lo minimo que puedo hacer). Mi nombre esta en mi nick y estudio ing sistemas, java es una pequeña parte de las cosas que estoy llevando en la universiad, y te te agradesco demasiado por la ayuda que me estas brindando....
esperare los demas videos tuyos...
PD: Como lo dije antes... ningun tema referente a la parte visual o algun sonido que meore la apariencia o usabilidad del juego importa, solo necesito lo basico... muchas graicas en este momento vere el video :D

hahaha no te mortifiques

No me lo agradescas yo lo ago por divercion

|-------------------------------------------|
| G3RW4Nll-77NAMREG-GERMAN77 |
|-------------------------------------------|

que tal.... estube viendo

que tal.... estube viendo los videos y descargue el codigo que pusiste.. lo estoy arreglando (tengo que ponerlo en varias clases, ojala salga biem)

estoy a la espera de tus nuevos videos(faltaba que las figuras bajen =)... ojala tengas tiempo ) nos vemos
gracias

de echo ya baja

ya bajan las figuras pero tienen unos grandes errores....
|-------------------------------------------|
| G3RW4Nll-77NAMREG-GERMAN77 |
|-------------------------------------------|

ya no puedo seguirle

Oye me encantaria seguir con lo de tetris pero esta semana tengo un curso y no es en donde yo vivo, te dejo en el source forge el codigo de lo que llevo.... ya funciona muy bien y tiene uno que otro error pero no son gran cosa.... faltan los puntos pero creo que ya puedes manejar eso

edit: ya funcionan lo de los puntos incluso puedes obtener puntos extra por ejemplo si haces una linea te da 18 pts pero si combinas 4 lineas al mismo tiempo te da 108 pts ....tiene un error en donde se pueden sobreponer unas figuras sobre otras y tambien tiene otro donde al girar la ficha en una orilla se sale de la pantalla pero no produsen ningun error grave... como ya lo havia dicho me voy a un curso.... creo que con lo que hice te sirve mas que nada ya que es un tetris en si, lo demas son agregados...tal ves cuando termine mi curso aga de nuevo el codigo en limpio y lo gravare todo
|-------------------------------------------|
| G3RW4Nll-77NAMREG-GERMAN77 |
|-------------------------------------------|

Hermano...simplmente me

Hermano...simplmente me quede sorprendido con el juego...
habia avanzado con respecto al primero codigo que colgaste, logre que las figuras caigan,que se puedan manejar con el teclado, epare el codigo en varias clases(asi kiere el profesor XD)....
pero simplmente estaba kedand muy lejos de lo que tu hiciste.Veo que me queda trabajo por hacer, lograr que las filas que se llenan completamente desaparezcan, ojala me salga, aunque creo que asi sera puesto que he parendido mucho de tus codigos

Y mas que una ayuda para presentar un trabajo en la unviersidad....
me acabas de dar esas ganas de hacer proyectos con java, y lo mas importante... como lo dije antes, he aprendido demasiado de tus codigos..
muchas gracias en verdad!!
muechos exitos.. y te deseo lo mejor en ese nuevo curso que llevaras

muchos exitos

de ahi sale la experiencia

de ahi uno gana la experiencia tomando lo mejor de cada cosa, de echo la mayoria de mis juegos estan echos o basados con lo que hice en juego anterior. pero hay aveses en las que las cosas no salen de una forma, ni de otra, ni de otra y haci. eso es lo que no me gusta de programar. me tarde 2 dias para hacer girar esas inches figuras. primero intente con matematicas.... no sirvio. luego intente con for... de nuevo no sirvio. luego con logica basica...no sirvio y me enoje porque era mucho codigo... borre lo que hice y lo hice de nuevo pero con otro metodo si te fijas el array de las figuras es muy diferente porque ya no es de [4][4][3] si no, es de [4][2] por esa rason tuve que modificar la forma de imprimir las figuras y todo lo relacionado con la figura. los tipos de colicion tambien los borre ni se me occurrio volverlos a ver de nuevo porque no servian ni poquito. ya despues de reconstrur los metodos de colicion...hice lo de las figuras giraran con puros if pero como era de esperar producia muchos errores. ya que se salia la figura de la pantalla etc... ya despues de tratar de muchas formas una forma de comprovar si es posible poner un cuadrado ahi sirvio una. despues de eso vi el juego y me di cuenta que se movia muy rapido a la derecha y a la izquierda entonses reduci la velocidad a .5 pero hice que no se quedara en .5 para que no produsca ningun error. me puse a jugar y no me gustaron los graficos haci que le puse bordes y le di el efecto de rastro luego le agrege el sistema de puntos(creo que no esta en el sorce forge) y ahora le estoy agregando un cronometro.....

me di cuenta que separas el codigo en varias clases porque es un requisito pero ami me choca hacer varias clases por varias rasones (suena chistoso)entre ellas la comunicacion entre los valores de las clases ya que uso muchos valores para los graficos, aparte yo aprendi a programar con simplej y en el no se usan las clases porque nadamas tienes un main al que le importas codigo pero nunca tienes mas de una clase

solo ten encuenta una cosa se puede hacer una cosa de muchas maneras te recomiendo que utilises la mas eficiente(rapida) ya que consumira menos CPU o la mas dinamica... no vallas a hacer lo que yo hice para girar las piesas ya que no es eficiente ni dinamico simplemente lo hice haci porque me tenia hasta ...

hahaha se nota que no tengo nada que hacer... la verdad esq horita estoy bien aburrido y cansado y tengo muchas ganas de escrivir... y me da mas flojera estudiar para mi curso ya que llevo toda una semana en eso y te puedo asegurar que no e estudidiado ni el 30%

|-------------------------------------------|
| G3RW4Nll-77NAMREG-GERMAN77 |
|-------------------------------------------|