Programación #5: Enemigos plataformeros en BASIC.

Continuando con los artículos de programación BASIC, seguimos con los enemigos. Ya tenemos completamente solucionado el movimiento de nuestro héroe, así que ahora toca proveerle de antagonistas que haga que el juego tenga algún aliciente.

ist2_2077314_evil_teacher.jpg

Además, lo vamos a hacer bien. Lo más fácil a la hora de ponerse a hacer un juego (y más en BASIC Spectrum) es liarse a hardcodear como locos. Lo ideal, sin embargo, es construir los motores de juego lo más generales que sea posible, de forma que toda la forma del juego (pantallas, objetos, enemigos …) puedan leerse de ristras de datos que el motor interprete. Así podremos reaprovechar partes del motor (o todo él, esto es muy divertido), obteniendo nuevos juegos en muy poco tiempo símplemente cambiando los datos.

Por tanto, vamos a crear un sistema de manejo de enemigos totalmente parametrizable y ampliable, en el que nos sea muy sencillo añadir nuevos patrones de movimiento o tipos de enemigos. Pasen y vean, señores.

El sistema que vamos a diseñar se basa en la lectura y modificación de una ristraza de datos que almacenaremos en RAM y que marearemos con POKE y PEEK. Básicamente, ya que BASIC Spectrum no nos permite crear estructuras ni arrays de las mismas, y como nunca necesitaremos valores mayores de 255, simularemos tablas de estructuras en memoria “a pelo“. El código resultante es bastante ilegible (porque hay un montón de POKEs y PEEKs con direcciones y offsets), pero el resultado funcionará muy bien y muy rápido cuando compilemos nuestro programa con HiSoft BASIC. Si quieres ir probando lo que hacemos en el intérprete de BASIC, puedes poner el emu a funcionar a 4x o 6x de velocidad. Eso te dará una idea precisa de cómo se moverá el juego en un Spectrum real cuando el código esté compilado.

Vuelvo a recomendarte que te empapes (si no lo has hecho ya) mi artículo sobre BASIC Compilado que aparece en este número de la revista ZXSF. Todo lo que explico aquí sirve para el intérprete, pero tenemos que tener en mente que todo lo que consigamos no lucirá en absoluto (básicamente, será totalmente injugable) si no lo compilamos. En el intérprete, lo que es funcionar, funcionará… pero a la velocidad de una tortuga paralítica cuesta arriba en una pista encerada.

La idea es tener una ristra de datos para cada enemigo. En la “ristra” para cada enemigo se guardará su posición, el frame de animación, la dirección de movimiento, contadores, etcétera. La idea es, además, tener varios tipos de enemigos, con lo que la ristra debe ser lo suficientemente grande para contener los datos del tipo de enemigo que más valores necesite.

Para empezar, vamos a presentar varios tipos de enemigos sencillos describiendo qué datos necesita y cómo se programará su comportamiento. Una vez hecho esto, ya en próximos capítulos, veremos como manejar estas ristras de datos en memoria y empezaremos a plantear el esqueleto de nuestro “manejador de actores”. Al final de todo, lo programaremos en BASIC.

Enemigo Lineal Tontuelo

El Enemigo Lineal Tontuelo (o ELT) es aquél que describe siempre la misma trayectoria en linea recta (horizontal o vertical), se da la vuelta, y vuelve al punto de inicio, para volver a empezar. De resolución férrea y decisión inquebrantable, nada conseguirá desviar su trayectoria. Este es, por tanto, el enemigo más fácil de programar.

infinity5.gif

Los ELTs necesitan pocos valores. Como todos, necesitarán su par de coordenadas (x, y), su número de enemigo (para saber qué gráfico pintar) y su frame de animación. Además, necesitaremos una dirección de movimiento (que llamaremos d) que indicará si se mueve en horizontal o vertical, y un sentido de movimiento (que llamaremos s y que tomará los valores -1 o 1), que indicará si el enemigo va o viene. Por último necesitaremos dos “topes“, que indican los extremos del segmento imaginario sobre el que se mueve nuestro enemigo (que llamaremos t1 y t2).

Valos a decir que si d=0, el ELT se moverá en horizontal, y si d=1, se moverá en vertical. Poniendo por ejemplo que d=0, nuestro enemigo se moverá en x de t1 a t2 según la dirección de s, con y fijo. Si d=1, entonces lo hará en y de t1 a t2 según la dirección de s, con x fijo. Eso significa que seguirá este algoritmo:

si d = 0 entonces
    x = x + s
    si x = t1 o x = t2 entonces
        s = -s
    fsi
si no, entonces
    y = y + s
    si y = t1 o y = t2 entonces
        s = -s
    fsi
fsi

Si te fijas, es harto sencillo. Símplemente estamos haciendo que el enemigo se mueva en la dirección que indica s (que puede ser -1 o 1) y que cuando llegue a los extremos de la trayectoria (t1 y t2), s cambie de signo y por tanto el movimiento cambie de sentido.

Enemigo Lineal Lemming

El siguiente enemigo que vamos a describir (a partir de ahora, ELL) es una ampliación del anterior. Básicamente es un Enemigo Lineal Tontuelo horizontal pero sin idea fija. Nuestro ELL símplemente anda hacia delante hasta que se encuentre un obstáculo. Debido a su falta de carácter, cuando esto ocurre nuestro ELL se dará media vuelta y continuará en sentido contrario. Los ELLs, además, se ven afectados por la gravedad. Si no hay ninguna plataforma bajo ellos, caerán. Como es lógico, sólo podrán caminar si tienen suelo debajo.

lokosoft-phantomas-luna.png

Este tipo de enemigos necesita menos valores aún. Nos vale simplemente con sus coordenadas (x, y) y el sentido del movimiento s. La coordenada x se verá afectada por s, y la coordenada y se verá afectada por la gravedad. Este tipo de enemigos, como es lógico, tenderán a terminar todos en la parte inferior de la pantalla, por lo que no es mala idea programar algún método para que puedan desaparecer y volver a aparecer por arriba.

Con todo esto, nuestro pseudocódigo es el siguiente:

si hay plataforma bajo el sprite entonces
    si s < 0 entonces
        si hay obstáculo a la izquierda entonces
            s = -s
        si no, entonces
            x = x + s
        fsi
    si no, entonces
        si hay obstáculo a la derecha entonces
            s = -s
        si no, entonces
            x = x + s
        fsi
    fsi
si no, entonces
    y = y + 1
fsi

si y = borde_inferior entonces
    y = borde_superior
fsi

Ya se complica un poco, ¿eh? Aquí lo único nuevo son las condiciones de cambio de sentido o caída. Eso de detectar plataformas y obstáculos lo haremos exactamente de la misma forma que en el movimiento del protagonista: usando ATTR para detectar el color de las casillas de carácter situadas en la dirección hacia la que queremos movernos.

Enemigo Helicóptero Pseudoautista

Los geniales EHPs contienen uno de los algoritmos de Inteligencia Artificial más sencillos que existen. Es tan sencillo que debería llamarse “Estupidez Artificial“, pero produce enemigos áltamente porculeros en entornos con muchos obstáculos. Los EHPs sólo dependen del contexto en el mismo sentido que los ELLs, o sea, sólo se ven afectados por los obstáculos a la hora de cambiar de dirección.

pkgms206.png

Este tipo de enemigo tiene dos estados: moviéndose y parado. Mira tú qué casualidad: a lo mejor te vas de aquí sabiendo un poco sobre máquinas de estados finitos, pues un EHPs no es más que una máquina de estados muy sencilla. En el estado moviéndose, nuestro EHP se moverá de forma fija en la dirección que lleve hasta que “decida pararse” o encuentre un obstáculo. En este momento pasará al estado parado. En el estado parado, el EHP elegirá una nueva dirección al azar y el número de espacios que se moverá en esa dirección hasta que “decida pararse“, para pasar acto seguido al estado moviéndose. Todo esto se ve mucho más claro mirando al diagrama de estados:

diagrama.png

Por tanto, necesitaremos las coordenadas (x, y), emplearemos la variable d para almacenar un número de 1 a 4 (que significarán arriba, abajo, izquierda y derecha), y reaprovecharemos la variable s como contador del número de espacios que andaremos en la dirección que indique d antes de pararnos de nuevo. Para saber en qué estado estamos, usaremos también s. Si s=0 significará que estamos parados, y si s>0 significará que estamos moviéndonos.

si s = 0 entonces
    d = aleatorio entre 1 y 4
    s = aleatorio entre 1 y 8 (por ejemplo)
si no, entonces
    s = s - 1
    si d = 1 (arriba) entonces
        si hay obstáculo arriba entonces
            s = 0
        si no
            y = y - 1
        fsi
    si, en cambio, d = 2 (abajo) entonces
        si hay obstáculo abajo entonces
            s = 0
        si no
            y = y + 1
        fsi
    si, en cambio, d = 3 (izquierda) entonces
        si hay obstáculo a la izquierda entonces
            s = 0
        si no
            x = x - 1
        fsi
    si, en cambio, d = 4 (derecha) entonces
        si hay obstáculo a la derecha entonces
            s = 0
        si no
            x = x + 1
        fsi
    fsi
fsi

¡Toma ya! Esto se va complicando más y más por momentos… ¡Y todavía no hemos llegado a los más complicados de los enemigos simples! Eso lo veremos en la próxima entrega del tutorial, que me acaba de entrar un marronazo por el correo electrónico que me tendrá ocupado el resto de la jornada.

Lo dicho, en el próximo artículo os explico un par de enemigos más y os cuento cómo meter toda la información de los mismos en memoria (¡y de forma persistente de pantalla a pantalla!).

6 Responses to Programación #5: Enemigos plataformeros en BASIC.

  1. anjuel dice:

    Jajajaja!
    Enemigo Lineal Tontuelo… jajajajaja!

  2. Juno dice:

    «debido a su falta de carácter»

    Pobres lemmings, si es que los parieron así.😀
    Como siempre, interesante.

  3. ATO dice:

    Ey, a ver cuándo le dedicas un artículo a aquellas revistas que nutrieron la parte gráfica de Lokosoft… Me refiero a Micro Hobby, Micro Mania, Hobby Consolas, Super Juegos, OK Computer…

  4. na_th_an dice:

    Tengo que hacer un artículo sobre LOKOsoft, la revista😛

    O, mejor, varios artículos… ¡que 23 números y 10 especiales dan para mucho!

  5. ATO dice:

    Di que sí, Johnny! ^_^

  6. Si dice:

    Hi people,

    How about ENGLISH version or something?
    Even an offline .PDF would nicely do😉

    Cheers

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: