Diseñando motor de Items para la Churrera
Publicado: Lun, 24 Feb 2014, 17:30
Queremos conseguir que pueda haber un pequeño inventario en pantalla y poder seleccionar un objeto de él, y además queremos que los objetos que compongan el inventario no sean fijos y que podamos saber, desde el script, qué objeto hay seleccionado.
Veamos, la idea es diseñar el sistema de items de forma que sea lo más funcional posible *pero* implique añadir el menor código posible. Siempre vamos de uñas con la memoria y esto es primordial. Hay veces que haciendo el sistema menos amigable para el usuario logramos que lo sea mucho más para la máquina, y tratando con un Spectrum está claro cual es el camino que hay que seguir.
He estado pensando un buen rato y se me ocurre un sistema que implica poquÃsimo código pero que puede llegar a ser muy potente, si lo combinamos con los flags y un poco de cerebro:
- En una sección inicial del script, vamos a definir "el itemset" (hay que ponerle nombres a las cosas, aunque sean nombres tan chungos como este): cuantos espacios tiene, dónde se colocan, y como se distribuyen los objetos. Algo asÃ:
$this->bbcode_second_pass_code('', 'ITEMSET
# Número de huecos:
SIZE 6
# Posición x, y
LOCATION 1, 21
# Horizonta/vertical, espaciado
DISPOSITION HORZ, 3
# Color y caracteres para pintar el selector
SELECTOR 66, 8, 9
# Flag que contiene qué hueco está seleccionado
FLAG 10
END')
- Un objeto se representa por su tile. Si tenemos una corona en el tile 10, el objeto corona será el 10. Si en un hueco del inventario está el 10, significa que en ese hueco está la corona. El valor 0 siempre representará un hueco vacÃo. Esto simplifica el código una barbaridad.
- En el script habrá cambios. ITEM n = t significa que en el hueco "n" está el objeto representado por el tile t. Definimos, pues, las siguientes condiciones:
$this->bbcode_second_pass_code('', 'IF ITEM n = t
IF ITEM n <> t')
Comprueban que en el espacio "n" está o no el objeto de tile "t".
$this->bbcode_second_pass_code('', 'IF SEL_ITEM = t')
Comprueba que en el espacio seleccionado por el selector está el objeto de tile "t"
Y los siguientes comandos:
$this->bbcode_second_pass_code('', 'SET ITEM n = t')
Establece en el hueco n el tile t. Obviamente, para quitar un objeto del hueco n, pondremos un 0.
Hay una limitación, por tanto, en el número de objetos que puede llevar el personaje a la vez. Con un poco de cabeza, como he dicho, se puede gestionar esto muy bien, y con un mÃnimo de código añadido al motor tenemos una herramienta bastante potente. Todo esto hay que combinarlo con los flags para tener funcionalidad completa. Con los ITEMs solo podemos saber si tenemos o no un ITEM en el inventario, pero no si se ha usado ya. Para eso necesitamos los flags.
¿Cómo se usa esto? Pongamos un ejemplo.
Imaginad que en la pantalla 6 tenemos un objeto "corona", representado por el tile 33, y lo tenemos en (7, 7). Además, el flag que indica su estado es el 3, que valdrá 0 cuando aún no lo hayamos cogido ni nada, para pintarlo en la pantalla.
$this->bbcode_second_pass_code('', 'ENTERING SCREEN 6
IF FLAG 3 = 0
THEN
SET TILE (7, 7) = 33
END
END')
Vamos a gestionar el hecho de cogerlo. Podemos hacerlo en modo básico o en modo virguero. Veamos el modo básico primero. En el modo básico asignamos "a mano" un hueco fijo para cada item. La corona la colocaremos en el hueco 2:
$this->bbcode_second_pass_code('', 'PRESS_FIRE AT SCREEN 6
IF PLAYER_TOUCHES (7, 7)
IF FLAG 3 = 0
THEN
SET FLAG 3 = 1
SET TILE (7, 7) = 0
SET ITEM 2 = 33
END
END')
El juego con el flag 3 es simplemente para que no vuelva a dibujarse. Cuando el flag 3 valga 1 no se volverá a pintar el objeto al volver a entrar en la pantalla, ni intentaremos cogerlo de nuevo. Por lo demás, lo que se hace es hacer que en el hueco 2 esté el objeto 33.
Imaginad que en la pantalla 12 tenemos que usarlo en la coordenada 5, 8. Pues habrá que comprobar que el item seleccionado es el 33:
$this->bbcode_second_pass_code('', 'PRESS_FIRE AT SCREEN 12
IF SEL_ITEM = 33
THEN
SET ITEM 2 = 0
# mas cosas
END
END')
Si el objeto seleccionado es el 33 (que sólo podrá ocurrir si antes lo colocamos en el hueco 2), lo quitamos del inventario (poniendo un 0 en el slot 2) y luego hacemos más cosas.
El modo virugero es que el objeto vaya al hueco seleccionado. Para eso usamos la indirección que permite el motor de scripting con el operador #. Recordad que estamos usando el flag 10 para representar el hueco seleccionado. Juguemos con eso. Además, habrá que comprobar que el hueco está libre!
$this->bbcode_second_pass_code('', 'PRESS_FIRE AT SCREEN 6
IF PLAYER_TOUCHES (7, 7)
IF FLAG 3 = 0
IF FLAG 10 <> 0
THEN
# Mal! el hueco no está libre!
SOUND 2
END
IF PLAYER_TOUCHES (7, 7)
IF FLAG 3 = 0
IF FLAG 10 = 0
THEN
SET FLAG 3 = 1
SET TILE (7, 7) = 0
SET ITEM #10 = 33
END
END')
¿Qué hacemos? Pues colocar el objeto de tile 33 (nuestra corona) en el espacio seleccionado, que no es más que el que está almacenado en el flag 10 (recordad que #10 significa "el valor del flag 10").
Para comprobar que lo tenemos, pues lo mismo.
¿Qué os parece? ¿Dudas? ¿Algo que comentar? Si mola, lo haré exactamente como he descrito.
Veamos, la idea es diseñar el sistema de items de forma que sea lo más funcional posible *pero* implique añadir el menor código posible. Siempre vamos de uñas con la memoria y esto es primordial. Hay veces que haciendo el sistema menos amigable para el usuario logramos que lo sea mucho más para la máquina, y tratando con un Spectrum está claro cual es el camino que hay que seguir.
He estado pensando un buen rato y se me ocurre un sistema que implica poquÃsimo código pero que puede llegar a ser muy potente, si lo combinamos con los flags y un poco de cerebro:
- En una sección inicial del script, vamos a definir "el itemset" (hay que ponerle nombres a las cosas, aunque sean nombres tan chungos como este): cuantos espacios tiene, dónde se colocan, y como se distribuyen los objetos. Algo asÃ:
$this->bbcode_second_pass_code('', 'ITEMSET
# Número de huecos:
SIZE 6
# Posición x, y
LOCATION 1, 21
# Horizonta/vertical, espaciado
DISPOSITION HORZ, 3
# Color y caracteres para pintar el selector
SELECTOR 66, 8, 9
# Flag que contiene qué hueco está seleccionado
FLAG 10
END')
- Un objeto se representa por su tile. Si tenemos una corona en el tile 10, el objeto corona será el 10. Si en un hueco del inventario está el 10, significa que en ese hueco está la corona. El valor 0 siempre representará un hueco vacÃo. Esto simplifica el código una barbaridad.
- En el script habrá cambios. ITEM n = t significa que en el hueco "n" está el objeto representado por el tile t. Definimos, pues, las siguientes condiciones:
$this->bbcode_second_pass_code('', 'IF ITEM n = t
IF ITEM n <> t')
Comprueban que en el espacio "n" está o no el objeto de tile "t".
$this->bbcode_second_pass_code('', 'IF SEL_ITEM = t')
Comprueba que en el espacio seleccionado por el selector está el objeto de tile "t"
Y los siguientes comandos:
$this->bbcode_second_pass_code('', 'SET ITEM n = t')
Establece en el hueco n el tile t. Obviamente, para quitar un objeto del hueco n, pondremos un 0.
Hay una limitación, por tanto, en el número de objetos que puede llevar el personaje a la vez. Con un poco de cabeza, como he dicho, se puede gestionar esto muy bien, y con un mÃnimo de código añadido al motor tenemos una herramienta bastante potente. Todo esto hay que combinarlo con los flags para tener funcionalidad completa. Con los ITEMs solo podemos saber si tenemos o no un ITEM en el inventario, pero no si se ha usado ya. Para eso necesitamos los flags.
¿Cómo se usa esto? Pongamos un ejemplo.
Imaginad que en la pantalla 6 tenemos un objeto "corona", representado por el tile 33, y lo tenemos en (7, 7). Además, el flag que indica su estado es el 3, que valdrá 0 cuando aún no lo hayamos cogido ni nada, para pintarlo en la pantalla.
$this->bbcode_second_pass_code('', 'ENTERING SCREEN 6
IF FLAG 3 = 0
THEN
SET TILE (7, 7) = 33
END
END')
Vamos a gestionar el hecho de cogerlo. Podemos hacerlo en modo básico o en modo virguero. Veamos el modo básico primero. En el modo básico asignamos "a mano" un hueco fijo para cada item. La corona la colocaremos en el hueco 2:
$this->bbcode_second_pass_code('', 'PRESS_FIRE AT SCREEN 6
IF PLAYER_TOUCHES (7, 7)
IF FLAG 3 = 0
THEN
SET FLAG 3 = 1
SET TILE (7, 7) = 0
SET ITEM 2 = 33
END
END')
El juego con el flag 3 es simplemente para que no vuelva a dibujarse. Cuando el flag 3 valga 1 no se volverá a pintar el objeto al volver a entrar en la pantalla, ni intentaremos cogerlo de nuevo. Por lo demás, lo que se hace es hacer que en el hueco 2 esté el objeto 33.
Imaginad que en la pantalla 12 tenemos que usarlo en la coordenada 5, 8. Pues habrá que comprobar que el item seleccionado es el 33:
$this->bbcode_second_pass_code('', 'PRESS_FIRE AT SCREEN 12
IF SEL_ITEM = 33
THEN
SET ITEM 2 = 0
# mas cosas
END
END')
Si el objeto seleccionado es el 33 (que sólo podrá ocurrir si antes lo colocamos en el hueco 2), lo quitamos del inventario (poniendo un 0 en el slot 2) y luego hacemos más cosas.
El modo virugero es que el objeto vaya al hueco seleccionado. Para eso usamos la indirección que permite el motor de scripting con el operador #. Recordad que estamos usando el flag 10 para representar el hueco seleccionado. Juguemos con eso. Además, habrá que comprobar que el hueco está libre!
$this->bbcode_second_pass_code('', 'PRESS_FIRE AT SCREEN 6
IF PLAYER_TOUCHES (7, 7)
IF FLAG 3 = 0
IF FLAG 10 <> 0
THEN
# Mal! el hueco no está libre!
SOUND 2
END
IF PLAYER_TOUCHES (7, 7)
IF FLAG 3 = 0
IF FLAG 10 = 0
THEN
SET FLAG 3 = 1
SET TILE (7, 7) = 0
SET ITEM #10 = 33
END
END')
¿Qué hacemos? Pues colocar el objeto de tile 33 (nuestra corona) en el espacio seleccionado, que no es más que el que está almacenado en el flag 10 (recordad que #10 significa "el valor del flag 10").
Para comprobar que lo tenemos, pues lo mismo.
¿Qué os parece? ¿Dudas? ¿Algo que comentar? Si mola, lo haré exactamente como he descrito.