juego spectrum
inicio noticias artículos entrevistas enlaces especiales juegos colecciones podcast taller prensa
Taller Crea tu propio juego de Spectrum (capítulo 9)

viernes, 7 de febrero de 2014

Aquí tenéis por fin el nuevo y temido capítulo del Taller de la Churrera: Scripting básico. En este noveno capítulo veremos de forma amena, divertida y detallada el sistema de scripting que nos permitirá personalizar al máximo nuestro juego con funcionalidades de todo tipo. Se abre todo un mundo frente a vuestros teclados. Haced buen uso de "la fuerza". ¡Ah! Y recordad que un gran poder conlleva una gran responsabilidad.

Capítulo 9: scripting básico

¿Scripting básico?

Eso mismo pone. En este capítulo vamos a definir el gameplay de Dogmole Tuppowski y vamos a aprender algunas nociones básicas de scripting.

El sistema de scripting de la Churrera es muy sencillo y parece bastante limitado, pero te puedes empepinar bastante y conseguir cosas medianamente complejas con algo de maña. Además, en cada versión que sacamos de la churrera lo ampliamos y cada vez funciona mejor, por lo que si practicas puedes lograr en tu juegos diseños de gameplay bastante complejos. Las reglas de Dogmole son sencillas a propósito, para ilustrar un comportamiento sencillo y aprender. Luego veremos el script de diferentes juegos mojonos para que veáis cómo hemos conseguido hacer las cosas.

El sistema de scripting tiene muchos comandos y comprobaciones diferentes. Como no quiero convertir este curso en una referencia con una lista de cosas interminables, te remito al archivo motor_de_clausulas.txt que está en la carpeta /script de la churrera: ahí hay una lista de todo lo que msc es capaz de compilar. No está de más echarle un ojaldre.

Refresquemos un poco

Recordemos que el script está formado por secciones, y que cada sección incluye cláusulas. Cada cláusula no es más que una lista de comprobaciones y una lista de comandos: si todas las comprobaciones son ciertas, se ejecutarán los comandos.

Controlamos qué cláusulas se ejecutarán colocándolas en una u otra sección. Recordemos las secciones que existen y cuándo se ejecutan:

ENTERING GAME: Esta sección se ejecutará nada más empezar la partida, y nunca más.

ENTERING ANY: Esta sección se ejecutará al entrar en cada pantalla, y también al pisar un enemigo. Sí, no tiene lógica alguna, pero es así porque viene muy bien para determinadas cosas.

ENTERING SCREEN n: Esta sección se ejecutará al entrar en la pantalla N.

PRESS_FIRE AT ANY: Esta sección se ejecutará al pulsar acción, sin importar en qué pantalla estemos.

FRESS_FIRE AT SCREEN n: Esta sección se ejecutará al pusar acción, si estamos en la pantalla N, y también al pisar un enemigo. Tampoco tiene lógica, pero también viene bien.

ON_TIMER_OFF: Esta sección se ejecutará si tenemos un temporizador, este llega a 0, y hemos configurado en config.h que ocurra esto.

¡Vamos a ello!

Antes de empezar vamos a recapitular, porque es importante que sepamos qué estamos haciendo. Recordemos, pues, cuál era el diseño de gameplay de nuestro Dogmole Tuppowsky:

En primer lugar, la puerta de la universidad está cerrada, y para abrirla hay que matar a todos los monjes. Hay 20 monjes puestos por todo el mapa, en la parte de abajo (las dos filas inferiores) y hay que cargárselos a todos. Cuando estén todos muertos, habrá que quitar el piedro que colocamos en el mapa a la entrada de la universidad.

Luego hay que programar la lógica del pedestal, dentro de la universidad. Si tocamos el pedestal llevando un objeto, lo perdemos y se incrementará un flag contando el número de objetos que hemos depositado. Cuando este número llegue a 10, habremos ganado el juego.

El script de este juego va a ser muy sencillo. Lo primero que tenemos que mirar es qué vamos a necesitar almacenar para destinar algunas flags para ello. En nuestro caso, como el motor ya se encarga de contar los monjes que hemos matado, sólo necesitaremos ir contando las cajas que vamos depositando y además necesitaremos recordar si hemos quitado el piedro o no. Vamos a usar dos flags: la 1 y la 3. ¿Por qué estas dos y no otras? Pues porque sí. En realidad, da igual.
Recordemos que mencionamos en el anterior capítulo que era interesante apuntar qué hacía cada flag al principio de nuestro script:


# flags:
# 1 - cuenta general de objetos.
# 3 - 1 = puerta de la universidad abierta.


Contando monjes muertos

Vaya título ¿eh? Pero mola. Lo primero que vamos a ver es cómo contar los monjes muertos para quitar el piedro de la pantalla 2. Antes que nada, tenemos que ver qué es lo que vamos a quitar. La pantalla 2 es esta, y he marcado el piedro que tenemos que quitar por scripting:

Si contamos un poquito, nos damos cuenta de que el piedro ocupa las coordenadas (12, 7). Las apuntamos.
Hemos dicho que vamos a usar el flag 3 para almacenar si ya hemos matado a todos los monjes o no. Si el flag 3 vale 1, significará que hemos matado a todos los monjes, y en ese caso habría que modificar esa pantalla para borrar el piedro de la posición que tenemos anotada. ¿Por qué no empezar por ahí? Creemos, pues, una cláusula para cuando entremos en la pantalla 2:


# Entrada de la universidad
ENTERING SCREEN 2
# Control de la puerta de la universidad.
IF FLAG 3 = 1
THEN
SET TILE (12, 7) = 0
END
END



Poco hay de nuevo en esta primera cláusula de gameplay que hemos escrito: se trata de la comprobación del valor de un flag. En vez de el IF TRUE que habíamos usado hasta ahora, escribimos IF FLAG 3 = 1 que sólo evaluará a cierto si el valor de nuestro flag 3 es, precisamente, 1. En este caso, se ejecutará el cuerpo de la cláusula: SET TILE (12, 7) = 0 escribirá el tile vacío sobre el espacio que ocupa el piedro, eliminándolo. Por tanto, cuando entremos en esta pantalla con el flag 3 a 1, se borrará el piedro y no habrá obstáculo. ¿Se pilla el concepto?

Sigamos, entonces. Hemos dicho que el flag 3 a 1 significa que hemos matado a todos los enemigos, pero el flag 3 no se va a poner a 1 automáticamente. Necesitamos crear una regla que, efectivamente, lo ponga a 1.

Como en la pantalla donde aparece el piedro no hay monjes, nunca se dará la situación de que matemos al último monje en la pantalla del piedro. Esto es: siempre estaremos en otra pantalla cuando matemos al último monje. Por tanto, un buen sitio para comprobar que hemos matado a todos los monjes es al entrar en cualquier pantalla, o sea, en nuestra sección ENTERING ANY. Y mejor todavía, por la particularidad esa que mencionamos antes de que ENTERING ANY se ejecuta también cuando pisamos a un enemigo. Cada vez que entremos en una pantalla, comprobaremos que el número de enemigos eliminados vale 20 y, si se da el caso, pondremos el flag 3 a 1:


# Abrir la universidad
ENTERING ANY
IF ENEMIES_KILLED_EQUALS 20
IF FLAG 3 = 0
THEN
SET FLAG 3 = 1
SOUND 7
SOUND 8
SOUND 9
SOUND 7
SOUND 8
SOUND 9
END
END



Con esto conseguimos justo lo que queremos. Fíjate que hay una nueva comprobación: IF ENEMIES_KILLED_EQUALS 20 será cierta si el número de enemigos eliminados (o monjes) vale exactamente 20. Si eso es cierto, acto seguido comprobamos el valor del flag 3 para ver que vale 0. Con esto lo que hacemos es asegurarnos de que esta cláusula sólo se ejecutará una vez, o de lo contrario se ejecutaría al entrar en cada pantalla.

Si todo se ha cumplido, pondremos el flag 3 a 1 (que es lo que queríamos) además de soltar una serie de pitidos pochos. Sí, el comando SOUND n toca el sonido n. Se trata de los sonidos del engine. Puedes mirar a qué corresponde cada número en el archivo beeper.h, al final.

Con esto tendremos lista la primera parte de nuestro gameplay: si todos los enemigos están muertos, colocamos el flag 3 a 1. En la pantalla 2, si el flag 3 vale 1, quitamos el piedro.

Lógica de las cajas

Ahora sólo nos queda definir la segunda parte del gameplay. Si recordáis, tenemos configurado el motor con ONLY_ONE_OBJECT. Eso significa que el máximo de objetos que podemos recoger es uno, o sea, que sólo podemos llevar una caja.

El objetivo del juego es llevar 10 cajas al mostrador de la Universidad, por tanto tendremos que programar en el script la lógica que haga que, si llevamos un objeto y activamos el mostrador, se nos reste ese objeto y se incremente el contador de objetos entregados, que hemos dicho que será el flag 1.

El mostrador está en la pantalla 0, si recordáis: lo hemos pintado con SET TILE desde nuestro script en la sección ENTERING SCREEN 0. El pedestal ocupa las posiciones (3, 7) y (4, 7).

Vamos a escribir ahora un trozo de script que, si pulsamos la tecla de acción en la pantalla 0, comprueba que estamos tocando el pedestal y que llevamos un objeto, para eliminar ese objeto e incrementar en uno la cuenta.

Lo primero que tenemos que resolver es la detección de que estamos tocando el pedestal. Si el pedestal ocupase un sólo tile en (x, y), sería muy sencillo:


IF PLAYER_TOUCHES x, y


Si cualquier pixel del jugador toca el tile (x, y), esa condición evalúa a cierto. El problema es que nuestro pedestal ocupa dos tiles. Una solución sería escribir dos cláusulas idénticas, una con un PLAYER_TOUCHES 3, 7 y la otra con un PLAYER_TOUCHES 4, 7, pero eso no será necesario ya que tenemos otras herramientas.

Para comprobar que estamos dentro de un area tenemos dos comprobaciones especiales:


IF PLAYER_IN_X x1, x2
IF PLAYER_IN_Y y1, y2


La primera evaluará a cierto si la coordenada x, en píxels, de la esquina superior izquierda del cuadro del sprite de nuestro personaje está entre x1 y x2. La segunda lo hará si la coordenada y, en píxels, de la esquina superior izquierda del cuadro del sprite de nuestro personaje está entre y1 e y2.

Veámoslo con un dibujo. Aquí vemos un área delimitada por x1, x2 y por y1, y2. El jugador estará "dentro" de ese área si el píxel marcado en rojo (el de la esquina superior izquierda del sprite) está "dentro" de ese área.

Cuando queremos comprobar que nuestro personaje esté dentro del área rectangular que ocupa un conjunto de tiles, tendremos que seguir la siguiente fórmula para calcular los valores de x1, x2, y1 e y1. Si (tx1,ty1) son las coordenadas (en tiles) del tile superior izquierdo del rectángulo y (tx2, ty2) son las coordenadas (también en tiles) del tile inferior derecho, esto es:

Con el área definida aquí, los valores de x1, x2 e y1, y2 que tendremos que usar en el script son los que se obtienen con las siguientes fórmulas:


x1 = tx1 * 16 - 15
x2 = tx2 * 16 + 15

y1 = ty1 * 16 - 15
y2 = ty2 * 16 + 15


Para verlo, de nuevo, un dibujito. Fíjate que he superpuesto un sprite para que veáis que para que "toque" los tiles debe estar en el rectángulo definido por las coordenadas (x1, y1) y (x2, y2):

Sí, si no estáis acostumbrados a hacer números programando esto es un lío de cojones, pero en realidad no lo es tanto cuando memorizáis la fórmula, o, mejor, si la comprendéis. Se multiplica por 16 para pasar de coordenadas de tiles a coordenadas de pixels porque los tiles miden 16x16 pixels. La suma y resta de 15 es para hacer "colisión por caja" con el sprite.

Sé que podríamos haber diseñado el scripting para ocultar un poco estos tejemanejes, pero así, exigiendo que el programador haga un par de operaciones matemáticas por su cuenta, eliminamos mucha complejidad en el código ya que le estamos dando al motor los datos "mascaditos".

Para terminar de verlo, trasladémonos a nuestro caso y hagamos las operaciones necesarias utilizando los valores de nuestro juego. Aquí, el rectángulo está formado únicamente por dos tiles en las coordenadas (3, 7) y (4, 7). Los tiles de las esquinas son esos dos tiles, precisamente, por lo que tx1 valdra 3, ty1 valdrá 7, tx2 valdrá 4 y ty2 valdrá también 7. De ese modo, siguiendo las fórmulas:


x1 = 3 * 16 - 15 = 33
x2 = 4 * 16 + 15 = 79

y1 = 7 * 16 - 15 = 97
y2 = 7 * 16 + 15 = 127


O sea, que para tocar el mostrador, el sprite debe estar entre 33 y 79 en la coordenada X y entre 97 y 127 en la coordenada Y. Veámoslo gráficamente con un gráfico lioso: fíjate como para que el sprite esté tocando el mostrador, el píxel superior izquierdo del cuadrado de su sprite (marcado en rojo) debe estar dentro del área que hemos definido:

Además, tendremos que comprobar que llevemos una caja en el inventario. Sería algo así:


PRESS_FIRE AT SCREEN 0
# Detectar pedestal.
# Lo detectamos definiendo un rectángulo de píxels.
# Luego comprobamos si el jugador ha cogido un objeto.
# Si todo se cumple, decrementamos el número de objetos e incrementamos FLAG 1
IF PLAYER_IN_X 33, 79
IF PLAYER_IN_Y 97, 127
IF PLAYER_HAS_OBJECTS
THEN
INC FLAG 1, 1
DEC OBJECTS 1
SOUND 7
END
END



Ahí está todo lo que hemos visto: primeramente, comprobamos la posición de Dogmole con IF PLAYER_IN_X e IF_PLAYER_IN_Y. Si todo se cumple, comprobamos que tengamos un objeto recogido con IF PLAYER_HAS_OBJECTS. Si se cumple todo haremos tres cosas: primero, incrementaremos en 1 el flag 1 mediante INC FLAG 1, 1. Luego decrementaremos en 1 en número de objetos recogidos (con lo que volverá a ser 0, y podremos volver a recoger otra caja) con DEC OBJECTS 1. Finalmente, tocaremos el sonido número 7.

Hecho esto, sólo nos queda una cosa que hacer: comprobar que hemos llevado las 10 cajas. Un buen sitio para hacerlo es justo después de la anterior cláusula. Como todas las cláusulas de una sección se ejecutan en orden, justo después de contabilizar colocaremos la comprobación de que ya hemos puesto 10 para terminar el juego. Ampliamos, por tanto, la sección PRESS_FIRE AT SCREEN 0 con la nueva cláusula. Quedaría así:


PRESS_FIRE AT SCREEN 0
# Detectar pedestal.
# Lo detectamos definiendo un rectángulo de píxels.
# Luego comprobamos si el jugador ha cogido un objeto.
# Si todo se cumple, decrementamos el número de objetos e incrementamos FLAG 1
IF PLAYER_IN_X 33, 79
IF PLAYER_IN_Y 97, 127
IF PLAYER_HAS_OBJECTS
THEN
INC FLAG 1, 1
DEC OBJECTS 1
SOUND 7
END

# Fin del juego
# Si llevamos 10 cajas, ¡hemos ganado!
IF FLAG 1 = 10
THEN
WIN GAME
END IF
END



De nuevo, muy sencillo: si llevamos 10 cajas (o sea, si el flag1 vale 10), habremos ganado. El comando WIN GAME hace que el juego termine con éxito y se muestre la pantalla del final.

¿Ves que no ha sido tanto? Vale, lo de las coordenadas es un poco lío, pero tampoco es para echarse a llorar. O sí, si eres una persona sensible.

Mejora interesante

Tal y como hemos configurado nuestro güego, el jugador tiene que pulsar acción para activar el mostrador y depositar un objeto. No es un problema, pero molaría más que el jugador no tuviese que pulsar nada. Precisamente para eso introdujimos en el motor lo que hemos llamado "la zona de fuego", o fire zone. Esta zona de fuego no es más que un rectángulo en pantalla, especificado en píxels. Si el jugador entra en el rectángulo, el motor se comporta como si hubiese pulsado acción. La zona de fuego se desactiva automáticamente al cambiar de pantalla, por lo que si la definimos en un ENTERING SCREEN n, sólo estará activo mientras estemos en esa pantalla.

Esto viene divinamente para nuestros propósitos: si al entrar en la pantalla 0 definimos una zona de fuego alrededor del mostrador, en cuanto el jugador lo toque se ejecutará la lógica que hemos programado en el script para dejar el objeto que lleve e incrementar el contador.

La zona de fuego se define con el comando SET_FIRE_ZONE, que recibe las coordenadas x1, y1, x2, e y2 del rectángulo que queramos usar como zona de fuego. Si queremos hacer coincidir la zona de fuego con un rectángulo formado por tiles, como es nuestro caso, se aplican las mismas fórmulas que explicamos antes. O sea, que vamos a usar exactamente los mismos valores.

Lo primer que tenemos que hacer es decirle al motor que vamos a usar zonas de fuego. Para ello, tenemos que activar la directiva correspondiente en nuestro config.h:


#define ENABLE_FIRE_ZONE // Allows to define a zone which auto-triggers "FIRE"


Hecho esto, sólo tendremos que modificar la sección ENTERING SCREEN 0 añadiendo el comando SET_FIRE_ZONE x1, y1, x2, y2 al final del todo:


# Vestíbulo de la universidad
ENTERING SCREEN 0
# Decoración y pedestal
IF TRUE
THEN
# Pedestal
SET TILE (3, 7) = 22
SET TILE (4, 7) = 23
# Decoración
SET TILE (1, 5) = 29
SET TILE (1, 6) = 20
SET TILE (1, 7) = 21
SET TILE (6, 6) = 20
SET TILE (6, 7) = 21
SET TILE (7, 7) = 28
SET TILE (1, 2) = 27
SET TILE (1, 3) = 28
SET TILE (2, 2) = 29
SET TILE (2, 3) = 27
SET TILE (3, 2) = 32
SET TILE (3, 3) = 33
SET TILE (9, 1) = 30
SET TILE (9, 2) = 30
SET TILE (9, 3) = 31
# Fire zone (x1, y1, x2, y2):
SET_FIRE_ZONE 33, 97, 79, 127
END
END



La pregunta que te harás es ¿por qué #@!! no lo habéis metido en el juego? Pues porque esta característica, que se incluyó originalmente en la rama 4.0 (en el juego de el Hobbit) se reintrodujo con la versión 3.99.1.

Tío, estoy un poco perdido

Me hago cargo. Hay que hacerse un poco el coco al funcionamiento del script. Creo que es ideal empezar por algo muy sencillo, incluso más sencillo que el Dogmole que hemos visto, e ir progresando.

Se me ocurre algo genial: íbamos a terminar aquí el capítulo de scripting básico, pero creo que nos vendría muy bien ver juntos los scripts de algunos de nuestros juegos. Voy a elegir unos cuantos juegos con un script sencillo, y lo iremos explicando paso por paso. Sería interesante que, mientras tanto, fueses jugando al juego para ver cómo afectan las diferentes cláusulas.

Cheril Perils

El güego con el que estrenamos el motor de scripting fue Cheril Perils. Entonces todo estaba en pañales y era muy sencillo. El script de Cheril Perils es el script más sencillo de todos nuestros güegos con Script: aquí sólo se hace una cosa: que hayamos matado a todos los enemigos, en cuyo caso quitaremos los pinchos de la primera pantalla. Estos pinchos:

En principio se parece mucho a parte de lo que hemos hecho en Dogmole: al entrar en la pantalla, comprobamos que hemos matado a todos los enemigos (hay 60 en total). Si se da el caso, imprimimos el tile vacío sobre los pinchos:


ENTERING SCREEN 20
IF ENEMIES_KILLED_EQUALS 60
THEN
SET TILE (2, 7) = 0
SET TILE (2, 8) = 0
END
END



Pero aquí ocurre algo que no nos pasaba en el Dogmole: hay enemigos en la pantalla donde hay que quitar los pinchos. No nos vale con detectar esto al entrar, ya que si matamos al último bicho en esta pantalla (puede suceder) necesitaríamos salir y volver a entrar en la pantalla para que el motor se coscase. Necesitamos más código que detecte que hemos matado al último bicho y que se ejecute cuando lo matemos. Recordemos que había una peculiaridad en el motor: cuando pisamos a un bicho se ejecuta la sección PRESS_FIRE AT SCREEN correspondiente a la pantalla actual. Esto nos viene genial: poniendo el mismo código en esta sección que en ENTERING SCREEN solucionamos el problema.

Ni cortos ni perezosos...


PRESS_FIRE AT SCREEN 20
IF ENEMIES_KILLED_EQUALS 60
THEN
SET TILE (2, 7) = 0
SET TILE (2, 8) = 0
END
END



Ahora vamos a detectar que "salimos". Si no hiciésemos nada, saliendo de la pantalla 20 por la izquierda nos encajamos en la pantalla 19... Que además está en la otra punta del mapa. En el juego original, esto estaba solucionado con un hack guarro, pero con la versión actual de la churrera puede hacerse bien.

Lo primero será definir una zona de fuego que cubra la parte izquierda de la pantalla, de forma que se ejecute la sección PRESS_FIRE AT SCREEN 20 cuando nos acerquemos a ella. Añadimos, pues, la definición de la zona de fuego en la sección ENTERING SCREEN 20 (no nos olvidemos, además, de activar la funcionalidad en config.h). Nos queda así:


ENTERING SCREEN 20
IF ENEMIES_KILLED_EQUALS 60
THEN
SET TILE (2, 7) = 0
SET TILE (2, 8) = 0
END

IF TRUE
THEN
SET_FIRE_ZONE 0, 0, 15, 159
END
END



¿Queda claro? Al entrar en la pantalla 20 pasan dos cosas: primero se comprueba si el número de enemigos vale 60, en cuyo caso se eliminan los tiles-pincho que bloquean la salida. Luego, en cualquier caso (IF TRUE) se define una zona de fuego que cubre todo una tira pegada a la izquierda de 15 pixels de ancho. En cuanto el jugador entre en esta zona (no podrá hacerlo si no se ha eliminado la barrera: simplemente no puede pasar), se ejecutará la sección PRESS_FIRE AT SCREEN 20. Ahora tendremos que añadir código en la sección PRESS_FIRE AT SCREEN 20 para detectar que el jugador está intentando salir por la izquierda y, en ese caso, terminar el juego con éxito. Quedaría así:


PRESS_FIRE AT SCREEN 20
IF ENEMIES_KILLED_EQUALS 60
THEN
SET TILE (2, 7) = 0
SET TILE (2, 8) = 0
END

IF PLAYER_IN_X 0, 15
THEN
WIN
END
END



Recapitulemos para que quede bien claro. Veamos lo que pasaría, paso por paso. Imaginemos que llegamos a la pantalla 20 después de haber matado a todos los malos. Esta es la secuencia de acontecimientos:

1. Al entrar en la pantalla 20, después de dibujarla y tal, se ejecuta la sección ENTERING SCREEN 20. En ella, se comprueba que llevamos 60 enemigos matados, cosa que es cierta, y se elimina la barrera. Además, se define una zona de fuego de 15 pixels de ancho en la parte izquierda del área de juego.

2. Se ejecuta el bucle principal del juego. El jugador juega y tal y cual, ve la barrera abierta, y se dirige a la izquierda.

3. Cuando el jugador entra en la zona de fuego, se ejecuta la sección PRESS_FIRE AT SCREEN 20. En ella, se comprueba que llevamos 60 enemigos matados y se elimina la barrera. Esto es redundante y podría evitarse con un flag, pero nos da igual... tampoco se nota. Lo importante es lo que ocurre luego: comprueba que la coordenada X del jugador, en pixels, esté entre 0 y 15, cosa que es cierta (ya que hemos entrado en esta sección por haber entrado en la zona de fuego, que está definida justo en ese area), por lo que ejecuta WIN y se nos muestra el final del güego.

¿Se pilla? ¿Vemos otro? ¿Que quieres ver lo del flag para eliminar la redundancia? Perfecto.

Tenemos todos los flags libres, así que pillaremos el 1. El método es sencillo: lo ponemos a 0 al entrar en la pantalla, a 1 cuando eliminemos la barrera, y sólo eliminaremos la barrera en PRESS_FIRE AT SCREEN 20 si está a 0. Lo pongo todo junto, ya deberías poder seguirlo solo:


ENTERING SCREEN 20
IF TRUE
THEN
SET_FIRE_ZONE 0, 0, 15, 159
SET FLAG 1 = 0
END

IF ENEMIES_KILLED_EQUALS 60
THEN
SET TILE (2, 7) = 0
SET TILE (2, 8) = 0
SET FLAG 1 = 1
END
END

PRESS_FIRE AT SCREEN 20
IF ENEMIES_KILLED_EQUALS 60
IF FLAG 1 = 0
THEN
SET FLAG 1 = 1
SET TILE (2, 7) = 0
SET TILE (2, 8) = 0
END

IF PLAYER_IN_X 0, 15
THEN
WIN
END
END



Ahora sí, vamos a ver otro.

Sgt. Helmet Training Day

Vamos a ver ahora un script un poco más largo, pero igualmente sencillo. En este juego la misión es recoger las cinco bombas, llevarlas a la pantalla del ordenador (pantalla 0) para depositarlas, y luego volver al principio (pantalla 24).
Hay muchas formas de hacer esto. La que usamos nosotros para montarlos es bastante sencilla:

Podemos contar el número de objetos que llevamos desde el script, por lo que las bombas serán objetos normales y corrientes del motor. Las colocamos con el colocador como hotspot de tipo 1.

Cuando lleguemos a la pantalla del ordenador, haremos una animación chula colocando las bombas alrededor. Usamos el colocador porque mola para saber las coordenadas de cada casilla (si pones el ratón sobre una casilla salen las coordenadas arriba del todo) y apuntamos en un papel donde las vamos a pintar.

Usaremos el flag 1 para comprobar que hemos colocado las bombas. Al principio del juego valdrá 0, y lo pondremos a 1 cuando coloquemos las bombas.

Cuando entremos en la pantalla 24, que es la pantalla principal, comprobaremos el valor del flag 1, y si vale 1, terminará el juego.

Además, iremos imprimiendo textos en la pantalla con lo que vamos haciendo. Recordemos que en config.h había tres directivas que mencionamos por encima hace algunos capítulos:


#define LINE_OF_TEXT 0 // If defined, scripts can show text @ Y = #
#define LINE_OF_TEXT_X 1 // X coordinate.
#define LINE_OF_TEXT_ATTR 71 // Attribute



Sirven para configurar donde sale una linea de texto que podremos escribir desde el script con el comando TEXT. Para ello dejamos sitio libre en el marco: fíjate como hay sitio en la fila de arriba, ya que hemos configurado la linea de texto en las coordenadas (x, y) = (1, 0).

Lo primero que hará nuestro script, por tanto, será definir un par de mensajes que aparecerán por defecto al entrar en cada pantalla, dependiendo de valor del flag 1. Esto lo hacemos en la sección ENTERING ANY. Esta sección, recordemos, se ejecuta al entrar en cada pantalla, justo antes de la sección ENTERING SCREEN n correspondiente. Atención a esto: nos permitirá definir un texto general que podamos sobrescribir fácilmente si hace falta para alguna pantalla en concreto, ya que si ponemos texto en ENTERING SCREEN n sobrescribirá el que pusomos en ENTERING ANY al ejecutarse después.

Para imprimir texto en la linea de texto definida, usamos el comando TEXT. El texto que le sigue va sin comillas. Usaremos el carácter de subrayado _ para representar los espacios. Es conveniente, además, rellenar con espacios para que, si hay que sobrescribir un texto largo con uno corto, se borre entero.

La longitud máxima de los textos dependerá de tu marco de juego y de cómo hayas definido su posición. En nuestro caso la hemos colocado en (x, y) = (1, 0) porque tenemos borde a la izquierda y a la derecha, con lo que la longitud máxima será de 30 caracteres.

Escribamos nuestra sección ENTERING ANY, pues. Hemos dicho que imprimiremos un texto u otro dependiendo del valor del flag 1:


ENTERING ANY
IF FLAG 1 = 0
THEN
TEXT BUSCA_5_BOMBAS_Y_EL_ORDENADOR!
END

IF FLAG 1 = 1
THEN
TEXT MISION_CUMPLIDA!_VUELVE_A_BASE
END
END



No tiene misterio ¿verdad? Si el flag 1 vale 0, o sea, la situación del principio del juego (todos los flags de ponen a 0 al empezar), al entrar en cada pantalla aparecerá el texto "BUSCA 5 BOMBAS Y EL ORDENADOR" en la zona del marco definida para la linea de texto. Si el flag 1 vale 1, cosa que ocurrirá cuando coloquemos las bombas en el ordenador, el texto por defecto que aparecerá al entrar en las pantallas será "MISION CUMPLIDA! VUELVE A BASE".

Vamos a hacernos un croquis mierder de la pantalla para ver donde va el ordenador y las bombas:

Vamos ahora con la chicha. Lo primero que haremos será escribir las condiciones para la pantalla del ordenador, que es la pantalla 0. En esta pantalla tenemos que hacer varias cosas. Tengámoslas claras antes de empezar:

Siempre que entremos tendremos que pintar el ordenador, que está compuesto por los tiles 32 a 38 del tileset. Lo haremos como hemos visto, con SET TILE.

Además, tendremos que definir un area de fuego alrededor del ordenador para que el juego detecte automáticamente cuando nos acercamos a él.

Si volvemos a entrar en la pantalla después de haber colocado las bombas (puede pasar), tendremos que coscarnos de ello y pintar también las bombas.

Si entramos por primera vez (no hemos puesto las bombas) escribiremos un mensajito de ayuda que diga "PON LAS CINCO BOMBAS Y CORRE"

Si nos acercamos al ordenador, habrá que hacer la animación chula de poner las bombas, y además colocar el flag 1 a 1.

Ahora que tenemos algo de experiencia, nos daremos cuenta que las cuatro primeras cosas se hacen al entrar en la pantalla, y la última al pulsar acción (o entrar en la zona de fuego). Vayamos una por una. Empecemos por las cosas que hay que hacer al entrar en esta pantalla. Me gusta empezar por las cosas que hay que hacer siempre: pintar el ordenador y definir la zona de fuego:


ENTERING SCREEN 0

# Siempre: pintar el ordenador.
IF TRUE
THEN
SET TILE (6, 3) = 32
SET TILE (7, 3) = 33
SET TILE (8, 3) = 34
SET TILE (6, 4) = 36
SET TILE (7, 4) = 37
SET TILE (8, 4) = 38
SET_FIRE_ZONE 80, 32, 159, 95
END



Si te fijas, hemos usado las fórmulas que explicamos antes para definir un área amplia alrededor del ordenador. En concreto, el área equivale al rectángulo formado desde el tile (x, y) = (5, 2) hasta el (9, 5). O sea, un reborde de un tile alrededor de los seis tiles que ocupa el ordenador. Coge un papel de cuadritos y te lías menos.
Seguimos: si entramos luego de haber colocado las bombas (algo que puede pasar) tendremos que coscarnos y pintar las bombas. Nada más sencillo:


# Si ya hemos puesto las bombas: pintarlas.
IF FLAG 1 = 1
THEN
SET TILE (4, 4) = 17
SET TILE (4, 2) = 17
SET TILE (7, 1) = 17
SET TILE (10, 2) = 17
SET TILE (10, 4) = 17
END



Nos hemos fijado en el croquis, por supuesto, para saber las posiciones de las bombas. La bomba está en el tile 17, que es el tile que se usa para pintar los objetos, si recordáis.

Ahora solo queda poner un texto de ayuda si no hemos colocado aún las bombas. Fíjate que ocurre lo que dijimos: como esta sección se ejecuta después de ENTERING ANY, el texto que imprimamos aquí sobrescribirá el que ya hubiese. Es por eso, además, que usamos espacios en blanco alrededor: centrarán el texto y eliminarán los caracteres del texto anterior, que es más largo:


# Si no, mensajito.
IF FLAG 1 = 0
THEN
TEXT _PON_LAS_CINCO_BOMBAS_Y_CORRE_
END
END



Listo. Ahora sólo queda reaccionar a la zona de fuego, en la sección PRESS_FIRE AT SCREEN 0. Haremos algunas comprobaciones y luego haremos la animación:


PRESS_FIRE AT SCREEN 0
IF PLAYER_IN_X 80, 159
IF PLAYER_IN_Y 32, 95
IF OBJECT_COUNT = 5
IF FLAG 1 = 0
THEN
SET FLAG 1 = 1
SET TILE (4, 4) = 17
SHOW
SOUND 0
SET TILE (4, 2) = 17
SHOW
SOUND 0
SET TILE (7, 1) = 17
SHOW
SOUND 0
SET TILE (10, 2) = 17
SHOW
SOUND 0
SET TILE (10, 4) = 17
SHOW
SOUND 0
TEXT ____AHORA_VUELVE_A_LA_BASE____
END
END



Veámoslo poco a poco, porque hay cosas nuevas:

Lo primero es comprobar que estamos donde tenemos que estar (el jugador siempre puede pulsar la tecla acción en vez de entrar en la zona de fuego, y no mola ejecutarlo si el jugador está en cualquier sitio). Eso lo hacemos como ya hemos visto: con PLAYER_IN_X y PLAYER_IN_Y y las mismas coordenadas de la zona de fuego.

Lo siguiente es comprobar que tenemos las cinco bombas, o lo que es lo mismo, que tenemos cinco objetos. Esto se hace con OBJECT_COUNT, que representa el número de objetos que el jugador lleva recogidos.

Por último, muy importante, hay que comprobar que aún no hemos dejado las bombas, o cosas divertidas podrían pasar.
Si se cumplen todas estas condiciones, pondremos el flag 1 a 1 (ya hemos puesto las bombas) y hacemos la animación, que consiste en ir pintando una a una las bombas y tocando un sonido. Ves ahí el comando SHOW, necesario porque los cambios que hagamos en la pantalla no serán visibles hasta que se actualice, cosa que pasa normalmente al volver al bucle principal, pero no en medio de la ejecución de una cláusula. Como queremos que se vea cada bomba justo después de pintarla, llamamos a SHOW. Cada sonido, además, parará la ejecución durante unos instantes (estamos en modo 48K), lo que nos viene genial. Por último, imprimiremos un texto de ayuda, de nuevo con espacios a los lados para completar los 30 caracteres máximos y borrar lo que hubiese del texto anterior.

Y con esto hemos terminado todo lo que había que hacer en la pantalla 0.

Si seguimos con nuestro guión, lo próximo que había que hacer era volver a la pantalla inicial, que es la 24. Lo que queda por hacer es bastante sencillo: consiste en comprobar, al entrar en la pantalla 24, que el flag 1 vale 1. Esto sólo pasará si anteriormente hemos colocado las bombas, por lo que no necesitamos más... Simplemente comprobamos eso y, si se cumple, terminamos el juego con éxito... Nada más sencillo que hacer esto:


ENTERING SCREEN 23
IF FLAG 1 = 1
THEN
WIN
END
END



¡Ea! Ya tenemos el juego programado. En el script de Sgt. Helmet hay un detalle más: nuestro habitual "vendo moto seminueva". Pero eso lo dejo ya, no tiene nada de especial: imprimir tiles, definir zona de fuego, detectar posición, y escribir un texto. Todo eso lo sabes hacer ya.

Arf, arf.

Podría seguir, pero mejor lo dejamos por ahora. En el próximo capítulo seguiremos viendo ejemplos paso por paso, pero ya con scripts más complejos como, por ejemplo, el de Cadàveriön. Luego ya seguiremos viendo cosas interesantes, como juegos de 128K, cambiar la música y los efectos, fases comprimidas... Uf, no vamos a terminar nunca.

Entretanto te recuerdo que en el archivo motor_de_clausulas.txt que está en /script puedes ver una lista de los comandos y las comprobaciones disponibles, por si te pica la curiosidad.

¡Hasta otra!

27 comentarios Mojon Twins


Hay actualmente 27 comentarios


na_th_an 07/02/2014 a las 18:46:08

¡Cuidado!, se ha vuelto a perder la indentación de las cajas de código. Así es bastante difícil de seguir.

A favor A favor En contra En contra
0(0 votos)
alejandro 07/02/2014 a las 19:58:26

¡Corregido! Gracias @na_th_an por el aviso.

A favor A favor En contra En contra
0(0 votos)
josepzin 07/02/2014 a las 19:59:51

Que jrandes sois!!

A favor A favor En contra En contra
0(0 votos)
lacucaracha8bits 07/02/2014 a las 20:06:18

Ui mae mia..Ya en esta fase del tuto ahi que tener la E.G.B terminada,jajaja..z forever...

A favor A favor En contra En contra
0(0 votos)
UsuarioEliminado 07/02/2014 a las 20:48:21

...mensaje eliminado por expreso deseo de su autor...

A favor A favor En contra En contra
0(0 votos)
Fabio 07/02/2014 a las 21:06:54

Una sola palabra.... VAAAAMMMMMOOOOSSSSS SSSSSS!!!!

A favor A favor En contra En contra
0(0 votos)
alxinho 08/02/2014 a las 00:48:42

Joder qué capitulazo!

A favor A favor En contra En contra
0(0 votos)
Lord Raptor 08/02/2014 a las 04:20:27

Kohonudo !! Ya avanzamos !! Bieeenn!! Yuhuuuuu..!!
..Est ajém! .. ajém! [no debo pensar en alto].. errrr...
Pueee bien, bien... llegamos a lo interesante... manos a la boraa... digooo... la barra... [eso luego].. la obra

Un saludo y gracias moztruos !!

A favor A favor En contra En contra
1(1 votos)
Fabio 10/02/2014 a las 02:26:06

Muy bien. La primera parte de quitar la piedra que nos obstaculiza el camino me funciono. Vamos a ver como me fue con eso de llevar las cajas.

A favor A favor En contra En contra
0(0 votos)
Pi 10/02/2014 a las 14:01:18

Hola spectruneros,..
se que hay un usuario que cuelga los cursos todos fusionados en un pdf y no me acuerdo quien es "el sujeto". Agradecería que añadiese este capítulo también ya que va de coña para repasar en el bus, metro y demás...gracias

A favor A favor En contra En contra
0(0 votos)
Fabio 10/02/2014 a las 19:08:55

Muy bien. Ya esta la logica de las cajas instrumentado.

A favor A favor En contra En contra
0(0 votos)
Fabio 10/02/2014 a las 19:11:56

El usuario Jarlaxe en el final de los comentarios del capitulo 8 ha publicado los pdf que pides. Aqui esta el link... http://sdrv. ms/1epsKGR

A favor A favor En contra En contra
0(0 votos)
Pi 11/02/2014 a las 12:06:27

Fabio 1.000.000 de Gracias.

A favor A favor En contra En contra
1(1 votos)
anjuel 11/02/2014 a las 12:22:50

Hola!

cuando esté terminado, colgaremos nosotros el curso maquetado en PDF con alguna corrección si la hubiera :-)

A favor A favor En contra En contra
2(2 votos)
Fabio 25/03/2014 a las 21:33:10

Alguien entre los presentes que ya este usando la version 3.99.3? Por lo que se ya viene implementada la carga de energia donde uno quiere y no al azar. Puede ser?

A favor A favor En contra En contra
0(0 votos)
elfoscuro 28/05/2014 a las 15:12:00

¿Se ha terminado el curso o está en pausa? Porque estoy esperando a saber si se pueden hacer cosas en 128k, sonido, y demás, y no se si se va a tratar... Hace cuatro meses del último artículo :-(

A favor A favor En contra En contra
0(0 votos)
Wuan Ho 28/05/2014 a las 15:59:22

Si es cierto,yo hace bastante que también espero la nueva entrega,pero no olvides que han estado muu liaos con Ninjajar. Pienso que en cuanto descansen un poco lo tentremos ;-)

A favor A favor En contra En contra
0(0 votos)
Fabio 29/05/2014 a las 15:47:31

Es verdad, pero vale la pena la espera. El tema es no olvidar lo que ya se vio previamente.
Y aque esta un chivito con el ultimo que hice. Lo comente pero no se si se enteraron. https://drive.g oogle.com/folderview ?id=0B55Yc0v2KfXpWkJ Cd0d2aElGalk&usp=sha

A favor A favor En contra En contra
0(0 votos)
Wuan Ho 29/05/2014 a las 22:51:02

Vaya, no está nada mal! , te falto poner el source,jejeje
Mojo Twins me encantaría este próximo verano currarme algún juego, pero necesitamos el curso completo, alguna pista de cuando vais a poner el próximo capítulo y cuantos quedan aun??, un saludo :-)

A favor A favor En contra En contra
0(0 votos)
Fabio 31/07/2014 a las 05:12:25

Hola chicos. Podrian decirme si el curso ha finalizado? Tenia entendido que todavia faltaba la parte del sonido y como hacer que el juego sea para 128K.

A favor A favor En contra En contra
1(1 votos)
Wuan Ho 02/08/2014 a las 19:16:47

Hola Fabio, yo estoy igual que tú. Esperemos tener noticias pronto. Saludos :-)

A favor A favor En contra En contra
2(2 votos)
Megauno 13/10/2014 a las 16:55:49

Ya hace uno ocho meses de la última lección.
¿El curso sigue o ha sido cancelado?
Gracias.

A favor A favor En contra En contra
1(1 votos)
Megauno 13/10/2014 a las 17:05:47

El foro necesita un botón editar y yo un teclado nuevo.
Lo que quería decir es que ya hace unos ocho meses de la última lección.

A favor A favor En contra En contra
0(0 votos)
Fabio 23/11/2014 a las 00:24:46

Bien, no hay que impacientar. Pero si reconozco que una respuesta por si o por no seria lo ideal.

A favor A favor En contra En contra
1(1 votos)
Toni 30/04/2015 a las 19:10:36

Buenas!

Una duda:
Es posible hacer el mapa y los gráficos de un juego para La Churrera con el TommyGun de AGD?

Si es así,hay algún tutorial?

Gracia

A favor A favor En contra En contra
0(0 votos)
droman 22/10/2015 a las 23:13:14

Lo damos por perdido ya???

Con lo bien que rulaba.....

A favor A favor En contra En contra
1(1 votos)
Blackhero 13/04/2017 a las 11:57:23

Esto como que quedó en el aire, ¿sabe alguien si existe continuacion de este curso por otros cauces?.

A favor A favor En contra En contra
0(0 votos)


Escribe tu comentario:


Si ya tienes usuario loguéate desde aquí


Nick:

E-mail (opcional):


Si el comentario es largo te recomendamos que lo escribas primero en otro sitio no vaya a ser que seas medio robot y falles con el captcha.
Tu Comentario:


Tenemos que comprobar que eres humano:

· El número de verificación es obligatorio y tiene como objetivo evitar spam.
· El Mundo del Spectrum se reserva el derecho a eliminar el comentario.
· Se borrarán automáticamente los enlaces de spam.




Posicionamiento Zaragoza
Posicionamiento SEO Zaragoza
Hostal zaragoza
Hostal barato Zaragoza
Flores Zaragoza
Compra flores baratas Zaragoza
te interesa




Introduce aquí lo que quieres buscar:
Colecciones de Spectrum   Colecciones de Spectrum

Échale un vistazo a las colecciones de Spectrum de nuestros lectores. ¿Todavía no has publicado la tuya? Créate un usuario y enseña tu colección.

Ver colecciones



Podcast Retro Spectrum

Colección aleatoria

La colección de Julián Urbano

La colección de Julián Urbano



El Mundo del Spectrum
 
 
Últimos comentarios
Mijhelob

"Ico" sería una auténtica gozada, en isometría, con unas bu...

El_iniciado

Cada edición se superan. También recomiendo la revista New Súper Jue...

Modosita68

Jorrrr, otro más para la colección. Se agradece que aparezca Michael ...

DavidGL

Ahora por fin tendre perricas y me lo podre comprar. Tambien recupera...

JoGonBa

Otro que cae seguro sí o sí. Solo espero que esta vez correos se port...

 



Iniciar sesión
acceder
Recordar contraseña




¿Eres nuevo en
El Mundo del Spectrum?
Regístrate




  Hacen El Mundo del Spectrum posible
 
El Mundo del Spectrum es una web dedicada al Sinclair ZX Spectrum. Nació como homenaje a Microhobby en 1996 en formato revista mensual evolucionando hasta esta tercera época que incluye su programa de Podcast llamado El Mundo del Spectrum Podcast.

Si quieres saber quién la hace posible haz clic en cada uno de sus miembros a la derecha de este texto.
Jesús Martínez del Vas Javier Ortiz Juan Fº Torres Alejandro Ibáñez  

© 1996 - 2017 El Mundo del Spectrum es un producto de Consultis

3ª época - www.elmundodelspectrum.com - Contacta

Los contenidos son opinión de su autor, EMS no tiene porqué compartir esa opinión.
Colaboran:
Curro, Kidsaguf, Deckard, Manu Sevilla, Antonio Ortiz
Han colaborado:
Falsworth, Hoz3, Slobulus