=======
3.99.3c
=======

Motor de Items
--------------

Se puede usar items y se puede hacer que el usuario los pueda seleccionar con la tecla "Z".
Para activarlos sólo hay que tener activado el scripting y definir una sección ITEMSET
al principio del script parecida a esta:

	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
		SLOT_FLAG 20
		
		# Flag que contiene qué objeto está en el hueco seleccionado
		ITEM_FLAG 21
	END

Luego tendremos comprobaciones y comandos destinadas a manejar los items:

* IF PLAYER_HAS_ITEM t      
    Descripción: Evaluará a CIERTO si el jugador tiene el item de tile T en su inventario.
    Opcode: 01 x
    
* IF PLAYER_HASN'T_ITEM x
    Descripción: Evaluará a CIERTO si el jugador NO tiene el item de tile T en su inventario.
    Opcode: 02 x
    
¡OJO! Las dos anteriores meten bastante código de intérprete. Es mejor no usarlas si
se puede evitar. Hay formas mejores de gestionar el inventario:

* IF SEL_ITEM = t
	Descripción: CIERTO si el item seleccionado es T
	Opcode: 10 ITEM_FLAG t
	El código generado equivale a IF FLAG ITEM_FLAG = t
	
* IF SEL_ITEM <> t
	Descripción: CIERTO si el item seleccionado no es T
	Opcode: 13 ITEM_FLAG t
	El código generado equivale a IF FLAG ITEM_FLAG <> t
	
* IF ITEM n = t
	Descripción: CIERTO si en el slot N está T
	Opcode: 04 n t
	
* IF ITEM n <> t
	Descripción: CIERTO si en el slot N está T
	Opcode: 05 n t
	
* SET ITEM n = t
    Descripción: Asigna el item t al slot n
    Opcode: 00 x n
    
* REDRAW_ITEMS
	Descripción: fuerza un redibujado de los items
	Opcode: E7

Para más info, visita este hilo del foro:

http://www.mojontwins.com/mojoniaplus/viewtopic.php?f=9&t=1581

Disparo / pisar enemigos deshabilitable
---------------------------------------

Se añade la posibilidad de habilitar el disparo / pisar enemigos según el valor
de una flag (para poder usarlo, disparo / pisar enemigos deben estar activados
en el motor, of course):

#define PLAYER_CAN_KILL_FLAG   1
#define PLAYER_CAN_FIRE_FLAG   1

Por ejemplo, imaginemos que decides que el flag que controle este comportamiento 
es el flag 5. Primero definiríamos esto en config.h:

	#define PLAYER_CAN_KILL_FLAG   5      

Luego, en el script, nos aseguraríamos de que ese flag vale 0 al principio del juego
(o 1, si queremos que se pueda matar a los enemigos desde el principio):

	ENTERING GAME
	    IF TRUE
	    THEN
	        SET FLAG 5 = 0
	    END
	END

Imagina que queremos que el jugador pueda empezar a pisar a los enemigos cuando 
coja un objeto representado por el tile 24 y situado en la pantalla 6, posición 
(7, 5). Podríamos hacer algo parecido a esto:

	ENTERING SCREEN 6
	    # Si no hemos cogido el objeto lo dibujamos
	    IF FLAG 5 = 0
	    THEN
	        SET TILE (7, 5) = 24
	    END
	END
	
	PRESS_FIRE AT SCREEN 6
	    # Si pulsamos ACCION sobre el objeto...
	    IF FLAG 5 = 0
	    IF PLAYER_TOUCHES 7, 5
	    THEN
	        # Lo borramos de la pantalla
	        SET TILE (7, 5) = 0
	        # Activamos la habilidad de matar enemigos
	        SET FLAG 5 = 1
	    END
	END

=======
3.99.3b
=======

Mínima revisión. Se arregla lo necesario para poder tener juegos de 128K con un
sólo nivel (es decir, usar MODE_128K sin COMPRESSED_LEVELS).

Ahora mismo hay dos ejemplos que te pueden ayudar si quieres hacer un juego de 128K:

- Goku Mal: 128K con niveles comprimidos. Ver este doc y los fuentes del juego.
- Las nuevas aventuras de Dogmole Tuppowsky: 128K con un sólo nivel, más info en
el foro de mojonia.

Además, en spare he añadido el archivo extern-textos.h cuyo contenido podéis usar
en extern.h si queréis una forma sencilla de mostrar textos en pantalla mediante el
comando EXTERN n del script.

======
3.99.3
======

Tiles animados
--------------

Si se define:

#define ENABLE_TILANIMS			32		// If defined, animated tiles are enabled.
										// the value especifies firt animated tile pair.

En config.h, los tiles >= que el índice especificado se consideran animados.
En el tileset, vienen por parejas. Si se define, por ejemplo, "46", entonces
la única pareja de tiles 46 y 47 estará animada. El motor los detectará y cada
frame hará que uno de los tiles 46 cambie de estado.

Puede haber un máximo de 64 tiles animados en la misma pantalla. Si pones más,
petará.

Modo 128K
---------

Tienes que hacer mucho trabajo manual con esto. Lo siento, pero es así. En primer
lugar habrá que crear un make.bat que construya todo lo que necesitas. Para ello
puedes basarte en el archivo spare/make128.bat y adecuarlo a tu proyecto.

El modo 128K es igual que el 48K pero usar WYZ Player y además soporta varios niveles.
No podrás tener niveles más largos, pero sí podrás tener varios niveles. 

Para usarlo, necesitas activar tres cosas en config.h:

#define MODE_128K						// Experimental!
#define COMPRESSED_LEVELS				// use levels.h instead of mapa.h and enems.h (!)
#define MAX_LEVELS			4			// # of compressed levels

En MAX_LEVELS tienes que especificar el número de niveles que vas a usar.

En churromain.c hay que cambiar la posición de la pila y colocarla por debajo
del binario principal:

#pragma output STACKPTR=24299

Luego hay que modificar levels128.h, que es donde se define la estructura de niveles
y que se incluye en modo 128K. Ahí verás un array levels, con información sobre los
niveles. En principio se incluye muy poca información:

// Level struct
LEVEL levels [MAX_LEVELS] = {
	{3,2},
	{4,3},
	{5,4},
	{6,5}	
};

El primer valor es el número de recurso (ver más adelante) que contiene el nivel. 
El segundo valor es el número de la canción en WYZ PLAYER que debe sonar mientras
se juega al nivel.

Para preparar un nivel tienes que usar la nueva utilidad buildlevel.exe que hay
en /utils. Esta utilidad toma los siguientes parámetros:

$ buildlevel mapa.map map_w map_h lock font.png work.png spriteset.png 
extrasprites.bin enems.ene scr_ini x_ini y_ini max_objs enems_life behs.txt level.bin

   * mapa.map Es el mapa de mappy
   * map_w, map_h Son las dimensiones del mapa en pantallas.
   * lock 15 para autodetectar cerrojos, 99 si no hay cerrojos
   * font.png es un archivo de 256x16 con 64 caracteres ascii 32-95
   * work.png es un archivo de 256x48 con el tileset
   * spriteset.png es un archivo de 256x32 con el spriteset
   * extrasprites.bin lo encuentras en /levels
   * enems.ene el archivo con los enemigos/hotspots de colocador.exe
   * scr_ini, scr_x, scr_y, max_objs, enems_life valores del nivel
   * behs.txt un archivo con los tipos de tiles, separados por comas
   * level.bin es el nombre de archivo de salida.
   
Cuando tengamos todos los niveles construidos, hay que comprimirlos con apack:

$ /utils/apacke.exe level1.bin level1c.bin
...

Cuando tengamos todos los niveles comprimidos, habrá que crear las imagenes
binarias que se cargarán en las páginas de RAM extra. Para eso usamos la utilidad
librarian que hay en la carpeta /bin. De hecho, es buena idea trabajar en la
carpeta /bin para esto.

La utilidad librarian utiliza una lista list.txt con los binarios comprimidos
que debe ir metiendo en las imagenes binarias que irán en las páginas extra de 
RAM. Lo primero que tendremos que meter serán los archivos title.bin, marco.bin
y ending.bin, en ese orden. Si no tienes marco.bin debes usar un archivo de
longitud 0, pero debes especificarlo. Luego añadiremos nuestros niveles. Por
ejemplo:

title.bin
marco.bin
ending.bin
level1c.bin
level2c.bin
level3c.bin
level4c.bin

Ahí hemos añadido cuatro niveles comprimidos.

Al ejecutar librarian, irá rellenando imagenes de 16K destinadas para ir en la
RAM extra. Primero creará ram3.bin, luego ram4.bin y finalmente ram6.bin, según
vaya necesitando más espacio.

También generará el archivo librarian.h, que tendremos que copiar en /dev. Aquí
podremos ver el número de recurso asociado a cada binario:

RESOURCE resources [] = {
   {3, 49152},   // 0: title.bin
   {3, 50680},   // 1: marco.bin
   {3, 50680},   // 2: ending.bin
   {3, 52449},   // 3: level1c.bin
   {3, 55469},   // 4: level2c.bin
   {3, 58148},   // 5: level3c.bin
   {3, 60842}   // 6: level4c.bin
};

Estos números de recurso son los que tendremos que especificar en el array
levels que mencionamos más arriba. En concreto, los recursos 3, 4, 5 y 6 son
los que contienen los cuatro niveles.

Con todo esto hecho y preparado, habrá que montar la cinta. Para ello hay 
que crear un loader.bas adecuado (puedes ver un ejemplo en /spare/loader.bas)
y construir un .tap con cada bloque de RAM (de nuevo, el ejemplo en 
/spare/make.bat construye la cinta con binarios en RAM3 y RAM4).

También necesitarás RAM1.BIN para construir RAM1.TAP, conteniendo el player
de WYZ con las canciones. Para ello tendrás que modificar /mus/WYZproPlay47aZX.ASM
en /mus para que incluya tus canciones. Tienes un ejemplo en /spare.

Como ves, es un poco tedioso. Te recomiendo que construyas mini-proyectos en
48K según vas haciendo los niveles, y que al final montes una versión 128K con
todo.

Además, puedes usar el espacio extra para meter más pantallas comprimidas, o
incluso código para usar passwords para saltar directamente a los niveles.
Puedes ver ejemplos de todo esto en Goku Mal 128.

Hotspots tipo 3
===============

Hemos hecho esta modificación, propuesta en el foro, fija a golpe de directiva.
Si defines

#define USE_HOTSPOTS_TYPE_3				// Alternate logic for recharges.

Las recargas aparecerán única y exclusivamente donde tú las coloques, usando
el hotspot de tipo 3.

Pausa / Abortar
===============

Si se define

#define PAUSE_ABORT						// Add h=PAUSE, y=ABORT

Se añade código para habilitar la tecla "h" para pausar el juego y la tecla
"y" para interrumpir la partida. Si quieres cambiar la asignación tendrás que
tocar el código en mainloop.h

Mensaje al coger objetos
========================

Se se define

#define GET_X_MORE						// Shows "get X more" 

Aparecerá un mensaje con los objetos que te quedan cada vez que coges uno.

-------------------------------------------------------------------------------

=========
3.99.2mod
=========

Esta fue una versión especial con una cosa que nos pidió Radastan, los...

Tiles animados
==============

Todo se basa en tilanim.h. Este archivo se incluye si se define en config.h la 
directiva ENABLE_TILANIMS. Además, el valor de esta directiva es el que define 
el número de tile menor que se considera animado.

En tilanim.h hay, además de la definición de datos, dos funciones:

void add_tilanim (unsigned char x, unsigned char y, unsigned char t) 
se llama desde la función que pinta la pantalla actual si detecta que el tile 
que va a pintar es >= ENABLE_TILANIMS. Añade un tile animado a la lista de 
tiles.

void do_tilanims (void) se llama desde el bucle principal. Básicamente 
selecciona un tile animado al azar entre todos los almacenados, le cambia el 
frame (de 0 a 1, de 1 a 0) y lo dibuja.

Para usarlo sólo tienes que definir en config.h la directiva ENABLE_TILANIMS 
con el tile animado menor. Por ejemplo, si tus cuatro últimas parejas de 
tiles (8 en total) son los animados, pon el valor 40. Luego, en el mapa, se 
tiene que poner el tile menor de la pareja, o sea, el tile 40 para 40-41, el 
42 para 42-43... Si no lo haces así pasarán cosas divertidas. El código es 
(tiene que ser) minimal, no se comprueba nada, así que cuidao.

Por cierto, esto no se ha probado. Si lo pones en tu güego y se peta, danos
un toque.

-------------------------------------------------------------------------------

======
3.99.2
======

Venga, las churreras van saliendo como churros. Estamos que lo rompemos, y
se nos ocurren cosas nuevas todos los días. Las iremos metiendo a medida que
se nos ocurran güegos que las lleven.

Estas son las cosas nuevas que hay en esta versión de la churrera:

Temporizadores
==============

Se añade a la churrera un temporizador que podemos usar de forma automática
o desde el script. El temporizador toma un valor inicial, va contando hacia
abajo, puede recargarse, se puede configurar cada cuántos frames se decrementa
o decidir qué hacer cuando se agota.

#define TIMER_ENABLE

Con TIMER_ENABLE se incluye el código necesario para manejar el temporizador.
Este código necesitará algunas otras directivas que especifican la forma de
funcionar:

#define TIMER_INITIAL		99	
#define TIMER_REFILL		25
#define TIMER_LAPSE 		32

TIMER_INITIAL especifica el valor inicial del temporizador. Las recargas de
tiempo, que se ponen con el colocador como hotspots de tipo 5, recargarán el
valor especificado en TIMER_REFILL. El valor máximo del timer, tanto para el
inicial como al recargar, es de 99. Para controlar el intervalo de tiempo que
transcurre entre cada decremento del temporizador, especificamos en TIMER_LAPSE
el número de frames que debe transcurrir.

#define TIMER_START

Si se define TIMER_START, el temporizador estará activo desde el principio.

Tenemos, además, algunas directivas que definen qué pasará cuando el temporiza-
dor llegue a cero. Hay que descomentar las que apliquen:

#define TIMER_SCRIPT_0	

Definiendo esta, cuando llegue a cero el temporizador se ejecutará una sección
especial del script, ON_TIMER_OFF. Es ideal para llevar todo el control del
temporizador por scripting, como ocurre en Cadàveriön.

//#define TIMER_GAMEOVER_0

Definiendo esta, el juego terminará cuando el temporizador llegue a cero.

//#define TIMER_KILL_0
//#define TIMER_WARP_TO 0
//#define TIMER_WARP_TO_X 	1
//#define TIMER_WARP_TO_Y 	1

Si se define TIMER_KILL_0, se restará una vida cuando el temporizador llegue a
cero. Si, además, se define TIMER_WARP_TO, además se cambiará a la pantalla
espeficiada, apareciendo el jugador en las coordenadas TIMER_WARP_TO_X y 
TIMER_WARP_TO_Y.

//#define TIMER_AUTO_RESET

Si se define esta opción, el temporizador volverá al máximo tras llegar a
cero de forma automática. Si vas a realizar el control por scripting, mejor
deja esta comentada.

#define SHOW_TIMER_OVER	

Si se define esta, en el caso de que hayamos definido o bien TIMER_SCRIPT_0 o
bien TIMER_KILL_0, se mostrará un cartel de "TIME'S UP!" cuando el temporizador
llegue a cero.

Scripting:
----------

Como hemos dicho, el temporizador puede administrarse desde el script. Es
interesante que, si decidimos hacer esto, activemos TIMER_SCRIPT_0 para que
cuando el temporizador llegue a cero se ejecute la sección ON_TIMER_OFF de
nuestro script y que el control sea total. 

Además, se definen estas comprobaciones y comandos:

Comprobaciones:
---------------

IF TIMER >= x
IF TIMER <= x

Que se cumplirán si el valor del temporizador es mayor o igual o menor o igual
que el valor especificado, respectivamente.

Comandos:
---------

SET_TIMER a, b

Sirve para establecer los valores TIMER_INITIAL y TIMER_LAPSE desde el script.

TIMER_START

Sirve para iniciar el temporizador.

TIMER_STOP

Sirve para parar el temporizador.

---

Control de bloques empujables
=============================

Hemos mejorado el motor para que se pueda hacer más cosas con el tile 14 de
tipo 10 (tile empujable) que simplemente empujarlo o que detenga la trayectoria
de los enemigos. Ahora podemos decirle al motor que lance la sección PRESS_FIRE
de la pantalla actual justo después de empujar un bloque empujable. Además, el
número del tile que se "pisa" y las coordenadas finales se almacenan en tres
flags que podemos configurar, para poderlas usar desde el script para hacer 
comprobaciones.

Este es el sistema que se emplea en el script de Cadàveriön para controlar que
coloquemos las estatuas sobre los pedestales, por poner un ejemplo.

Recordemos lo que teníamos hasta ahora:

#define PLAYER_PUSH_BOXES 				
#define FIRE_TO_PUSH					

La primera es necesaria para activar los tiles empujables. La segunda obliga al
jugador a pulsar FIRE para empujar y, por tanto, no es obligatoria. Veamos 
ahora las nuevas directivas:

#define ENABLE_PUSHED_SCRIPTING
#define MOVED_TILE_FLAG 		1
#define MOVED_X_FLAG 			2
#define MOVED_Y_FLAG 			3

Activando ENABLE_PUSHED_SCRIPTING, el tile que se pisa y sus coordenadas se 
almacenarán en los flags especificados por las directivas MOVED_TILE_FLAG,
MOVED_X_FLAG y MOVED_Y_FLAG. En el código que se muestra, el tile pisado se
almacenará en el flag 1, y sus coordenadas en los flags 2 y 3.

#define PUSHING_ACTION

Si definimos esta, además, se ejecutarán los scripts PRESS_FIRE AT ANY y
PRESS_FIRE de la pantalla actual.

Recomendamos estudiar el script de Cadàveriön, el cual, además de ser un buen
ejemplo del uso del temporizador y del control del bloque empujable, resulta
ser un script bastante complejo que emplea un montón de técnicas avanzadas.

---

Comprobar si nos salimos del mapa
=================================

Es aconsejable poner límites en tu mapa para que el jugador no se pueda
salir, pero si tu mapa es estrecho puede que quieras aprovechar toda la 
pantalla. En ese caso, puedes activar:

#define PLAYER_CHECK_MAP_BOUNDARIES

Que añadirá comprobaciones y no dejará que el jugador se salga del mapa.
¡Ojo! Si puedes evitar usarlo, mejor: ahorrarás espacio.

---

Tipo de enemigo "custom" de regalo
==================================

Hasta ahora habíamos dejado sin código los enemigos de tipo 6, pero 
hemos pensado que no nos cuesta poner uno, de ejemplo. Se comporta como
los murciélagos de Cheril the Goddess. Para usarlos, ponlos en el colo-
cador de enemigos como tipo 6 y usa estas directivas:

#define ENABLE_CUSTOM_TYPE_6			
#define TYPE_6_FIXED_SPRITE 	2		
#define SIGHT_DISTANCE			96

La primera los activa, la segunda define qué sprite va a usar (menos 1,
si quieres el sprite del enemigo 3, pon un 2. Sorry por la guarrada,
pero ahorro bytes). La tercera dice cuántos píxels ve de lejos el bicho.
Si te ve, te persigue. Si no, vuelve a su sitio (donde lo hayas puesto
con el colocador).

Esta implementación, además, utiliza dos directivas de los enemigos de
tipo 5 para funcionar:

#define FANTY_MAX_V             256	
#define FANTY_A                 12	

Define ahí la aceleración y la velocidad máxima de tus tipo 6. Si vas a 
usar también tipo 5 y quieres otros valores, sé un hombre y modifica el
motor.

---

Configuración de teclado / joystick para dos botones
====================================================

Hay güegos de vista lateral que se juegan mejor con dos botones. Si activas
esta directiva:

#define USE_TWO_BUTTONS

El teclado será el siguiente, en vez del habitual:

A izquierda
D derecha
W arriba
S abajo
N salto
M disparo

Si se elige joystick, FIRE y M disparan, y N salta.

---

Disparos hacia arriba y en diagonal para vista lateral
======================================================

Ahora podrás permitir que el jugador dispare hacia arriba o en diagonal.
Para ello define esto:

#define CAN_FIRE_UP	

Esta configuración funciona mejor con USE_TWO_BUTTONS, ya que así separamos
"arriba" del botón de salto.

Si no pulsas "arriba", el personaje disparará hacia donde esté mirando. Si
pulsas "arriba" mientras disparas, el personaje disparará hacia arriba. Si,
además, estás pulsando una dirección, el personaje disparará en la diagonal
indicada.

---

Balas enmascaradas
==================

Por velocidad, las balas no llevan máscaras. Esto funciona bien si el fondo
sobre el que se mueven es oscuro (pocos pixels INK activos). Sin embargo, 
hay situaciones en las que esto no ocurre y se ve mal. En ese caso, podemos
activar máscaras para las balas:

#define MASKED_BULLETS

