Isshokuta; 20160525

Ayer, en un ratico que tuve, apañé las partes de arriba y de abajo de los enemigos, con algún que otro dolor de cabeza y un poquillo de trabajo manual. Por suerte, este tedio está resuelto y además me sirvió para ver que había introducido un bug en la importación de sprites de mkts que ya he reparado.

Lo que sí me he dado cuenta es que voy a necesitar una versión especial de oam_meta_spr que permita pintar con un atributo “custom” los metasprites que se le pase. No es trivial, de todos modos, porque no es sólo “emplear el atributo X que sea” para cambiar el color, sino que también hay que respetar el flag de flipping horizontal que lleva la mitad de los metasprites.

Probablemente lo modifique para que haga un OR con un valor fijo en la ZP antes de mandar el dato a la copia de la OAM, pero no es algo que me vaya a quitar el sueño en algún tiempo.

Antes tengo que montar el sistema de la IA de los enemigos, que no va a ser moco de pavo. Pero creo que la tengo lo suficientemente madura como para ponerme a ello – incluso mejor, creo que podría ponerme a escribir el compilador de comportamientos (el COCO, ya tengo nombre) porque así seguro que me da que pensar un montón y termino de definir.

~~~

Un script parecido a esto:

	WALK
:0a
	IF CLOSER_THAN 1 GOTO :1
	GOTO :0a
:1
	JUMP
	WAITIDLE
	TURN
	WALK
:1a
	IF HIT_RANGE GOTO :2
	GOTO :1a
:2
	HIT
	WAITIDLE
	TURN
	WALK
	END

Viendo eso de ahí arriba me he dado cuenta de que el único estado que se puede interrumpir es “WALK”, y que el único estado que se puede modificar es “Jump” (añade “Jumpkick”).

Lo digo porque a lo mejor podría simplificar un poco el script teniendo esto en cuenta, sobre todo porque no puedo hacer nada en estados como “Subiendo”, “Bajando”, “Puñetazo” o “Golpe aéreo”. Es tontería, estos estados deberían parar el script y no requerir un “WAITIDLE”. Para el estado de salto sí que tiene sentido. Lo de arriba quedaría así:

	WALK
:0a
	IF CLOSER_THAN 1 GOTO :1
	GOTO :0a
:1
	JUMP
	WAITIDLE
	TURN
	WALK
:1a
	IF HIT_RANGE GOTO :2
	GOTO :1a
:2
	HIT
	TURN
	WALK
	END

Otra cosa que me he dado cuenta, con respecto al control de todo esto, es que un personaje puede “caer” tras andar o saltar. Debo recordar el estado que tenía antes de caer para volver a él o no:

  • Si estoy andando y hay agujero -> caer. Cuando termina de caer -> sigo andando.
  • Si estoy saltando y hay agujero -> caer. Cuando termina de caer -> IDLE.

¿Sería muy difícil establecer DO:LOOP? Luego generaría saltos y tal, pero… Necesitaría una pila o algo:

00 	JURUFRIKI
01 	POTIPOTI
02 DO 			-> '02' a la pila:   02
02 	CAQUICUQUI
03 	PIÑARANJA
04 DO 			-> '04' a la pila: 	 02 04
04  	ROBESPIERRE
05 	ANDRONIGO
06 LOOP 		-> Saco de la pila: '04'; genero "GOTO 04"
08 LOOP 		-> Saco de la pila: '02'; genero "GOTO 02"
...

Creo que así podría ir bien. De este modo el programa es más legible:

	WALK
	DO
		IF CLOSER_THAN 1 GOTO :1
	LOOP
:1
	JUMP
	WAITIDLE
	TURN
	WALK
	DO
		IF HIT_RANGE GOTO :2
	LOOP
:2
	HIT
	TURN
	WALK
	END

Faltaría una forma de poder salir de los loops y “seguir”, en plan “EXIT DO”, pero eso ya precisaría que el compilador pegase dos pasadas y creo que es un poco overkill para algo tan sencillo como esto. Creo que lo dejo así, empezará e escribir el compilador en base a este lenguaje.

~~~

Revisamos:

OPCODE		COMMAND 	QUE
00x		END 		FIN
01x		IDLE 		Parar
10x		WALK 		Avanzar
40x		TURN 		Darse la vuelta (inmediato)
41x		JUMP 		Saltar (state -> jump)
42		CHANGE 		Cambiar de nivel (state -> go_up o go_down)
50 		FIREUP 		Disparar proyectil por arriba (inmediato)
51 		FIREDOWN 	Disparar proyectil por abajo (inmediato)
52x		HIT 		Hostia (puede que saltando)

CEx		GOTO 		Goto {next byte}

CF		WASTE 		No hacer nada

DXx		P_CLOSER_THAN 	Jugador a menos de X*32 (acercándose) 
				[(efacing && px < ex) || (!efacing && px > ex)]
EXx		P_FURTHER_THAN 	Jugador a más de X*32 (alejándose) 
				[(efacing && px > ex) || (!efacing && px < ex)]

F0x		P_SAME_LEVEL 	Jugador en mi nivel
F2x		P_FRONT	 	Jugador frente a mí
F4x		P_HIT_RANGE 	Jugador cerca para hostial
F5x		P_CROUCHED 	Jugador agachado
F6x		P_JUMPING 	Jugador saltando
F7x		P_HITTING 	Jugador golpeando
FFx		IDLE 		Yo estoy idle

cosa: Los IF siempre implican GOTO, así que el formato será BYTE DESTINO, al igual que GOTO.

Los WAITIDLE los codificaré como un arreglo de DO/LOOP con un IF IDLE para salir. Los script serán más largos pero el parser menos complejo, y es a lo que debo estar siempre apuntando.

WAITIDLE debe generar código para:

DO
	IF IDLE GOTO :next
LOOP
:next

Soy tontángano, estoy viendo que voy a tener que hacer dos pasadas sí o sí, así que permitiré un EXIT LOOP, pero lo dejaré para el final.

En una primera pasada, el byte que se escribe después de los GOTO debe ser el índice de un array de etiquetas. Cuando se encuentren las etiquetas, se irá poblando el array con direcciones. En una segunda pasada, se sustituyen los bytes de después de los GOTO por los de verdad.

~~~~

Hostias, he escrito todo el compilador de un tirón. Como funcione es para darme premios.

~~

Había un par de mierdas de sintaxis y tonterías… Pero la compilación va perfecta. O eso parece con el script de prueba que he hecho. ¡Esto marcha! Ahora tengo que empezar, por tanto, a pensar en el módulo de enemigos. Qué variables necesito, cómo voy a gestionarlos dinámicamente, y más mierdas. Tiempo de pensar y pensar un montón.

~

Bueno, a ver si saco algo en claro. Me doy 20 minutos. Si no saco nada, le pego a otro, no sé, Lala, Pong Pong, o lo que sea. Obviamente tengo que encontrar la forma de “lanzarlos” y meterlos en una tira de enemigos, pero voy a intentar hacer el motor antes aunque los lance yo a mano al llegar a tal sitio de cam_pos (por poner).

Además, voy a implementar eso de “la pila de slots libres” para gestionar de forma más rápida la búsqueda de un sitio en el que crear un enemigo.

~~

Crear un nuevo enemigo: debo saber posición x inicial, posición y inicial (más bien, un valor para encurfloory, que puede ser 127 o 207), tops_id y legs_id. Puedo leer todo esto de variables globales generales (que habré sacado decodificando la tira, claro está).

rdxx, rdy (127/207), rdb y rdc.

~~

Llevo un montón de rato atrancado porque no sé por qué narices no me funciona una cosa (obviamente, ni siquiera puedo pensar). Lo he hecho mil veces, no sé qué falla. Supuestamente debe pintarse al malo si su coordenada X entra entre cam_pos y cam_pos + 232, pero nunca se me cumple! y eso que lo estoy mirando con el visor hexadecimal de RAM y debería cumplirse, los valores están bien.

A lo mejor es que me he ofuscao. Espero que sea eso y que a la próxima lo vea y tal, porque es rarer rarer.

~

Vale, espera, que hay algo sobrescribiéndome parte del array “enon”. A revisar tocan!

Ya está. Era una chorrez.

JODER. He perdido miles de minutos. Ahora churum on… y yo off :-/

Bueno, al menos ya creo el enemigo y éste parece que está bien creado y en su sitio, y que el render funciona. Ahora queda lo más difícil… el enems_do!

Hasta mañana.

~~~~~

Voy a medir el porcentaje de frame y a asustarme. Pues nada que asustarse, la cosa va bastante bien. Sólo el personaje principal oscila entre los 20-32 rasters, y cuando aparece el enemigo hay algunos más. Tengo que ir optimizando ya, por cierto, que el movimiento del prota está medio apañao.

Quizá sea buen momento de hacerlo ahora, mientras sigo macerando el sistema de la IA.

Cada cuadro podría procesar a un enemigo de los activos, en dos etapas: interpretar su script y ejecutar su estado. De ese modo, todos los estados conducen a IDLE en su compleción y es el script quien hace las otras transiciones. Al ejecutarse sólo un paso de script cada vez, todo llevará cierto retardo que (espero) parezca que sea que los malos “se lo piensan un poco” (lo cual, además, coincidiría con la realidad).

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 )

Google photo

Estás comentando usando tu cuenta de Google. 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 )

Conectando a %s