¿Cómo debo tener la entrada de tecla / mouse en un juego avanzado de Java?

9

Soy un programador autodidacta, por lo que no sé las formas adecuadas de hacer las cosas. He creado juegos simples como asteroides y serpientes, pero en esos juegos, puedes modificar fácilmente las variables dentro de las funciones de keyevent. Así es como lo hice en mi sencillo juego de Asteroides:

/*
* key listener events
*/
public void keyReleased(KeyEvent k){
    int keyCode = k.getKeyCode();

    switch(keyCode){

        case KeyEvent.VK_LEFT:
            turnLeft = false;
            break;

        case KeyEvent.VK_RIGHT:
            turnRight = false;
            break;

        case KeyEvent.VK_UP:
            accel = false;
            break;

        case KeyEvent.VK_1:
            cls = true;
            break;
        case KeyEvent.VK_ENTER:
            break;
        case KeyEvent.VK_SPACE:
            fire = false;
    }
}
public void keyTyped(KeyEvent K){}
public void keyPressed(KeyEvent k){
    int keyCode = k.getKeyCode();

    switch(keyCode){

        case KeyEvent.VK_LEFT:
            turnLeft = true;
            break;

        case KeyEvent.VK_RIGHT:
            turnRight = true;
            break;

        case KeyEvent.VK_UP:
            accel = true;
            break;

        case KeyEvent.VK_1:
            cls = false;
            break;
        case KeyEvent.VK_ENTER:
            clearAllBullets();
            break;
        case KeyEvent.VK_SPACE:
            fire = true;
    }
}

Si tuviera que hacer un juego más avanzado (con un menú principal, opciones, juego principal, etc.), ¿cómo debería hacer la entrada de la tecla / mouse?

Además, si tuviera que entrar en un solo jugador, ¿debería poner todo el código de juego en una clase? ¿Hay alguna manera de poner el código de un jugador en una clase separada y de alguna manera hacer que la entrada clave modifique las variables y demás?

Steven Rogers
fuente
+1 Tu respuesta me permitió aprender algo nuevo de la respuesta de bearcdp. ¡Gracias por preguntar! =)
Will Marcouiller

Respuestas:

3

No soy un experto y, sin embargo, sugiero separar tanto los controles como la lógica de negocios / juego / menú (nómbrelo).

Ya he respondido una pregunta similar con respecto a dar instrucciones a una serpiente en un juego diseñado con clases. Java es un lenguaje orientado a objetos, supongo que puedes escribir clases y cosas adecuadas. Luego, cuando haya escrito su clase de objeto, si es así que su objeto necesita reaccionar a algunas teclas y clics del mouse, iría con una clase de controlador que sabe lo que se muestra actualmente en la pantalla, luego le diría a este objeto lo que debería hacer dependiendo de la tecla que se ha presionado o la región en la que se ha hecho clic.

Aquí está el enlace a la pregunta que le dije sobre la que respondí sobre la separación de los controles de la lógica del objeto. También incluye una muestra de código que ilustra mi pensamiento.

Moviendo mi sprite en XNA usando clases

( Desafortunadamente, ninguna de las respuestas fue aceptada por el OP, por lo que no sabemos con certeza si resolvió sus preocupaciones. Además, siempre estoy diseñando de esta manera y no encontré ningún problema al hacerlo hasta ahora ) .

Ahora lo sé, está etiquetado XNA. La idea o diseño es un nivel de arquitectura más alto que la tecnología utilizada, por lo que este diseño podría simplemente adaptarse a la sintaxis de Java. La idea general sigue siendo la misma. =)

¡Espero que esto ayude! Estaré encantado de ayudarlo más cuando pueda, ¡solo pregunte! =)

Will Marcouiller
fuente
5

La respuesta de Will muestra lo que probablemente sea el más flexible y directo, y lo recomendaría si lo que necesita es un sondeo de entrada directo.

Pero, si necesita una manera fácil de verificar diferentes combinaciones de pulsaciones de botones mientras evita grandes cantidades de cambio y si las declaraciones, puede usar enumeraciones de bandera de bits.

No sé lo que sabes sobre los vectores de bits, así que aquí hay una descripción general: Básicamente, tienes una clase enum que representa todas las claves posibles. Cada enumeración debe tener un valor que corresponda a un bit en un entero. (es decir: 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0011, 0x0012, 0x0014, etc.). ( Enlace para hacer esto en Java).

Ahora, dado que puede pasar información sobre hasta 32 (o 64 si usa teclas largas), puede tener una tabla hash que asocie vectores de bits (int o long) con objetos que caen en algún tipo de interfaz KeyComboCallback, que solo contiene un llamada de método único, Do (), que se llama cuando se presiona la combinación de teclas asociada.

Ahora, cuando crea una instancia / inicializa su objeto de jugador o su objeto de menú, puede hacer una llamada a algún tipo de administrador de entrada y pasarle todos los vectores de bits de combinación de teclas que desee y asociarlos con clases internas anónimas.

// ... in your init code for Player

InputManager.map(
    KeyMap.A.val() | KeyMap.B.val() | KeyMap.C.val(), 
    new KeyComboCallback(KeyMap keys) {
        public void Do() {
           this.DoCrazyAwesomeComboAttack();
        }
    });

// ...  continue init

Esto es realmente rápido y conveniente en C ++ y C #, pero las enumeraciones de Java son especiales, por lo que puede ser más conveniente crear una clase KeyCombination o algo que almacene toda esta información sin preocuparse por las enumeraciones. Pero la idea sigue siendo la misma. Estoy usando esto en un juego XNA, y me gusta mucho la instalación. También puede usarlo para separar las regiones de entrada, lo que es útil para comparar diferentes partes del teclado o gamepad de forma independiente (podría ser útil para dos jugadores en un teclado).

michael.bartnett
fuente
Me gusta tu publicación, especialmente el "this.DoCrazyAwesomeComboAttack ();" XD. Tu camino parece ser la mejor manera para cosas complicadas, así que me quedaré con cosas más fáciles. ¡Gracias por tu ayuda!
Steven Rogers
+1 ¡Respuesta muy interesante! Aprendí de esta respuesta y la echaré un vistazo cuando tenga más tiempo para dedicarme al desarrollo de mi juego de hobby. Y gracias por decir que mi respuesta es buena, aunque es para cosas más simples, lo cual no discutiría, ya que soy un principiante en GD. =) Gracias!
Will Marcouiller