Feudo
1Nov/100

Input

Como siempre, deben recordar que todo lo que escribo proviene de mi propia experiencia y de lo que he ido leyendo por la red y que no soy un profesional del tema.

El input
El input es parte fundamental de los juegos, pues consiste en conectamos todo el hardware que interactua con nuestro usuario y en convertir dichas señales en ordenes o información relevante para nuestra aplicación, actualmente los dos grandes hardware para PC son el teclado y el mouse, aunque de seguro iremos viendo cada vez más opciones, como pantallas de multitoque (Las pantalla de monotoque, aunque como hardware son diferentes, a nivel lógico su input es exactamente el mismo que el del mouse.), capacidad de reconocer ordenes vocales y de seguro que en algunos años más veremos sistema que reconocen los impulsos eléctricos del cuerpo para convertirlos en señales directas para nuestro PC.

Hay por lo menos 2 formas de manejar estos input, una consiste en crear un ciclo que se encuentre escaneando de forma permanente los valores de los hardware de entrada (Keyboard, mouse o gamepad) , la segunda consiste en agregar las ordenes a ciertos eventos que nos entrega nuestro lenguaje, como puede ser el caso de flash, donde en vez de tener un ciclo de input, lo que tenemos son eventos disparados por el usuario. Sobre cuál es mejor, creo que es mejor considerar que ambas son herramientas y que la elección debe responder a nuestro gusto y a nuestras necesidades (y a nuestro lenguaje, pues no todos disponen de ambas opciones).

En mi caso, voy a optar por la clásica estructura de tener un ciclo de input que lee el hardware, que le entrega la información al ciclo lógico y la salida será el ciclo de dibujo.

Ciclo

Lo primero, es contar con alguna herramienta que nos permita leer las entradas del teclado o del mouse (o del gamepad), por desgracia no podemos usar la entrada normal de windows, ya que ésta cuenta con un retardo que haría injugable nuestra aplicación.

Abran el Notepad o cualquier aplicación que les permita escribir, presionen y dejen presionada la tecla “A” y vean que ocurre. En el instante en que presionan la tecla, va a aparecer la letra “A”, si mantienen presionada la tecla, verán que luego de aproximadamente un segundo el notepad empieza a escribir toda una línea de letras “A”, el tiempo que transcurre entre que se preciosa por primera vez la tecla, hasta el momento en el cual se comienza a escribir la línea de letras es un retardo que aplica nuestro sistema operativo y no el notepad, si programamos un juego y usamos el input normal de windows para leer la entrada del teclado vamos a tener el mismo problema. Imagen jugar Mario bros de ésta forma, al presionar la tecla izquierda el personaje se movería un poco, para luego quedar quito durante un segundo, sería algo bastante desagradable.
Para solventar el problema podemos programar nuestra propia aplicación para que lea de forma directa el hardware o usar alguna librería que haga esto. Yo voy a usar la librería dx_Lib32. La cual incorpora toda una clase dedicada a la lectura del hardware de input.

¿Qué hacemos con el input?
Lo que yo recomiendo es separar el input en ordenes que le pasaremos a nuestro ciclo lógico y que sean lo más independientes posibles del hardware, supongamos que tenemos un juego de plataformas, donde tenemos a nuestro héroe de turno, lo primero es definir que ordenes puede ejecutar y al ser un juego de plataformas, nuestro héroe debería ser capaz de saltar, caminar a la izquierda y caminar a la derecha. A nivel lógico tenemos 3 eventos independientes del input, cada uno de estos métodos debe estar enlazado con el input, pues la decisión de saltar, caminar a la izquierda o la derecha no depende de nuestra aplicación, si no, que depende del jugador (Recuerden que la única forma de interactuar entre el jugador y nuestra aplicación es mediante el input). Al hacer ésta separación, es posible asignar cualquier entrada a cualquier acción dentro del ciclo lógico, en otras palabras, la acción es saltar, y luego enlazamos el input del keyboard, la tecla “W”, a la acción de saltar; la ventaja de ésta separación, es que si el día de mañana queremos agregar a nuestro juego la opción de usar un gamepad no tenemos que reprogramar la acción de saltar, simplemente agregamos un enlace.

Input

Ordenes por nivel y por flanco.
En mis proyectos, yo suelo utilizar 3 eventos por cada botón o tecla que son el momento en el cual se presionan (flanco de subida), mientras se mantiene presionado (nivel 1) y cuando se suelta (flanco de bajada), si volvemos al ejemplo anterior, saltar es una orden que sólo se debe efectuar una vez, por lo cual obedece a una acción de flanco, es similar a prender una luz, porque al hacerlo sólo deben presionar el interruptor una única vez y no es necesario mantener el dedo en el interruptor para que la luz quede encendida (técnicamente existe una memoria mecánica, pero no viene al caso explicar ese concepto). En cambio, caminar a la derecha o la izquierda son ejemplo de ordenes por nivel y son parecidas al acelerador de un automóvil, para que el automóvil se mueva es necesario mantener presionado el acelerador, cuando lo sueltan, el auto comienza a detenerse. En nuestro juego queremos que pase el mismo fenómeno, queremos que se salte una única vez cuando se presione el input “W”, pero queremos que se camine a la izquierda mientras se tenga presionado el input “A”.

Flancos
Para evitar que se puede saltar en medio de otro salto es necesario usar algún flag que nos limite la acción de saltar, pero no viene al tema ahora.

Para poder reconocer un flanco es necesario almacenar el valor de nuestro input en el ciclo anterior, como ven en el dibujo, un flanco de subida es el momento en el cual el input tiene valor 1, pero que en el ciclo anterior tenía valor 0. Un flanco de bajada, al contrario, es aquel que actualmente tiene valor 0, pero que en el ciclo anterior tenía valor 1.

Pseudocódigo:
ValorW = ActualizarInput(“W”)
Si ValorAnteriorW = 0 y ValorW = 1 Entonces
#Flanco de subida
Heroe_Saltar
Fin del Si
Si ValorAnteriorW = 1 y ValorW = 0 Entonces
#Flanco de bajada
Fin del Si
ValorAnteriorW = ValorW

ValorA = ActualizarInput(“A”)
Si ValorA = 1 Entonces
#Nivel 1
Heroe_Izquierda
Fin del Si
ValorAnteriorA = ValorA
Es muy fácil crear los flancos, simplemente debemos almacenar en algún lugar el valor que tenía el input en el ciclo anterior.

Algo que puede ser confuso para los nuevos es el termino de los ciclos. Mi juego, al igual que muchos otros, tiene un ciclo principal que se repite n veces por segundo (30 en mi caso), ese es el ciclo principal del juego y dentro del cual yo llamo a los ciclos de input, de lógica y de dibujo, en mi caso he optado por tener todo sincronizado, con lo cual, todo mi hardware de entrada se actualiza también 30 veces por segundo, cada una de estás actualizaciones es un ciclo, ésta no es una única manera de hacerlo pero no me da ahora el tiempo para entrar en detalles sobre eso.
Mi ciclo principal parte leyendo el estado actual del keyboard, del mouse y del gamepad (si corresponde) y me entrega los valores en variables, luego yo reviso si en éste ciclo está presionada la tecla “W”, lo comparo con el valor que tenía en el ciclo anterior (previamente guardado en alguna variable como muestra el ejemplo) y con el if determino si corresponde ejecutar la acción de saltar o no y así ocurre en cada ciclo, manteniendo conectado al jugador con la lógica.

¿Te gustó este artículo?

¡Suscríbete a nuestro feed RSS!

Archivado en: Feudo Deja un comentario
Comentarios (0) Trackbacks (0)

Aún no hay comentarios.


Leave a comment

Aún no hay trackbacks.

FireStats icon Con la potencia de FireStats