PongPong; 20160207

Más rápido de lo que pensaba, he hecho la transición. Aunque he metido varias optimizaciones y he añadido precálculos por todos lados está claro que el proceso será bastante más lento. Aún no he medido el tiempo de frame que me queda ahora mismo porque pienso que todavía podría precalcular u optimizar alguna cosa más. Le daré más pensadas ahora que no puedo ponerme a ello, he visto que macerando las cosas offline a veces se me ocurren geniales ideas (como la de precalcular los 16 posibles inicios de metatile en # de patrón para no tener que calcular nada una vez extraído el nibble del byte correcto del tile del mapa que quiero pintar).

Si todo va bien, meteré más tipos de enemigos. Otra cosa que tengo que hacer es buscar una forma mejor de extraer los dígitos decimales de la puntuación para añadirlos al display. Estoy empeñado en ejecutar esta actualización justo antes de esperar al split, pero ahora mismo no me da tiempo. Lo intentaré un par de veces más y si veo que sigue saltando, lo muevo después del split y busco otra cosa que colocar antes.

¡ENHORABUENA! ¡¡HE TERMINADO REESCRIBIÉNDOLO TODO!!

~~

He estado leyendo y es lo que yo me temía: como el 6502 de la NES está capado y no tiene BCD, no hay otra que hacer el BCD tú mismo almacenando cada dígito en una posición de RAM e implementando tu función de suma pseudo-BCD si quieres evitar las divisiones.

Mira, hace tiempo que tenía que haber hecho esto, así que voy al lío. Tengo código en asm para hacerlo, pero voy a probar a dejarlo en C para no complicar porque creo que me dará tiempo.

~~

Sencillo, aunque tengo que optimizar un par de cosas tontas. Pero es genial: ahora me cabe en el poquísimo tiempo que hay desde que acaba la rutina del NMI y aún no ha ocurrido el “sprite 0 hit” que controla el split.

Ahora tengo que hacer estas tareas de limpieza tonta:

  • Quitar la variable “pscore” y usar una bandera normal 0/1 para indicar que ha cambiado y que hay que volver a pintarlo.
  • Quitar la función p_5d que pinta un valor de 16 bits en decimal (con las consiguientes divisiones y módulos) por algo que pinte directamente el valor del buffer bcd (directo a VRAM, se llama siempre con la PPU apagada).
  • Otra cosa que se me había ocurrido para ahorrar algunos ciclos pero que ahora no puedo recordar. Ya me vendrá.

Tengo que ir metiendo ya la música, aunque sea la de Chase o algo tonto que haga, para que no me de una sorpresa nada agradable en el futuro.

Voy a hacer una lista de sonidos que necesito y a rapiñarlos del pool murciano, veamos:

- Salto                         "Jump 3" (tocado, -1o)
- Enemy hit                     "Kill"
- Chof (agua)                   "Door"
- Coger mosca                   "Item" (tocado, -1o)
- Caer con el culo              "Fiuuu" (tocado, -1o)
- Botar con el culo             "Assplossion" (recortado) + "Jump 3"
- Disparo (tentativo)           "Laser 2"
- Pedo (movimiento choco)       "Wrong"
- Start                         "Select"
- ???? 1                        "Invisibility"

Voy a meter los sonidos y la música de Chase y ver qué tiempo de frame queda, de media.

~~~

Mierda, me da la impresión de que al sonar más de un sonido a la vez pierdo ya el frame en NTSC. Porca miseria. Tendría que haber empezado desde el principio con la música.

A ver de dónde saco castaña.

~~

He cambiado el sitio donde llamo al split. Se ve que, en NTSC, cuando hay un loop de la canción el tiempo que tarda el NMI en terminar es bastante mayor, así que se junta todo y no da tiempo.

Bueno, así se pierde más tiempo en los frames, pero bueno, a ver si así va todo guay. No debería afectarme mucho si quiero añadir complejidad al juego, porque lo que incrementa es el tiempo de NMI y no el tiempo antes de esperar a que este ocurra…

En teoría seguimos yendo bien.

~~

Chrum se está despertando, pero yo debería ir pensando en ver qué añadir:

  • Más movimientos de enemigos. Sierras, podrían funcionar bien, pero tengo que trabajar en un código más sencillo. Fantys, de los más sencillos – a lo mejor no quedan bien del todo porque estarían limitados a la pantalla donde están creados -> si los pongo de los que llevan estados esto se notará menos. Si el jugador sale de la pantalla para ellos dejaría de existir y se les vería volviendo a su sitio. Saltadores: saltan al azar a izquierda o a derecha, siempre que no se vayan a salir de la pantalla. El problema de esto es que precisaría una rutina equivalente (o casi) a la que mueve al jugador. [**].
  • Motor jetpac y motor choco, para ir cambiando.
  • El set de sprites normal en el que no se le vea el totete a la prota.

[**] Tengo que crear un sistema de coordenadas de punto fijo y de colisiones con el escenario unificada. Vendrá bien.

Pensaré en todo, churum está despertándose.

~

Quizá pueda codificar de alguna manera qué cosas necesito (generales) en el valor de 3 bits que indica el tipo de movimiento, en plan:

111
|||
||+- Alt
|+-- Colisión
+--- Fixed Point

Así, por ejemplo, en el bucle que controla los enemigos, si el bit 2 está a 1 haré automáticamente la conversión de fixed point -> integer al final del bucle. Si el bit 1 está a 1, habrá colisión. Pero quizá…. No sé.

Lo de las sierras, he pensado que puedo liarla parda porque las sierras originales de MK1 necesitan el truco del sprite que oculta (o sea, poner un sprite de mayor prioridad (antes en la OAM) pero con el bit de “baja prioridad” levantado, de forma que se pinte antes de los importantes, pero detrás del escenario, efectivamente ocultando parte de los sprites importantes – el truco de SMB3) y ya es mucha tela marinera. Lo que haré será esta variación muy sencilla:

  ···
  ·X·
  ··o

Donde X es el tile, o el enemigo, y · la trayectoria, en el sentido de las agujas del reloj o el contrario.

Simplificando, dos modos, cuatro estados.

Modo clockwise: L U R D.

  • Si state & 1 = 0: Horizontal.
  • Si state & 1 = 1: Vertical.
  • Si state >> 1 = 0: Decrementando
  • Si state >> 1 = 1: Incrementando

Modo counter-clockwise: L D R U.

  • Si state & 1 = 0: Horizontal.
  • Si state & 1 = 1: Vertical.
  • Si state == 0 || state == 3: Decrementando
  • Si state == 1 || state == 2: Incrementando;

o lo que es lo mismo:

  • Si ((state + 1) & 3) >> 1 == 0: Decrementando
  • Si ((state + 1) & 3) >> 1 == 1: Incrementando

Todo esto se simplifica en este pseudocódigo:

rda = cw ? (state >> 1) : (((state + 1) & 3) >> 1);
d = rda ? V : -V;
if (state & 1) y += d; else x += d;

A lo que habría que añadir el cambio de estados. Siempre se avanza 32 pixels desde la posición inicial, así que podríamos llevar la cuenta:

ct = (ct + V) & 31; if (!ct) state = (state + 1) & 3;

Creo que es la forma más compacta de programar algo así, y daría de la leche de juego. Será lo próximo a lo que le de fran. Además, no necesita ni punto fijo ni colisión, lo que me lleva al problema de la falta de bits. O sea, 000 no puede ser porque eso es “vacío”, 001 ya está pillado, x1x no, porque no necesita FP, y 1xx tampoco, porque no necesita colisión.

Por otro lado, no tiene sentido hacerlo con cualquier tipo de sprite, así que a lo mejor lo puedo fijar de otra manera, combinando con el número de sprite.

EN plan, si tipo = 000, y sprite != 0000, entonces -> este tipo de casos especiales. O yo qué sé.

Tengo que pensar otra cosa. O eso, o usar el bit que reservo para “dispara o no”. Juer, me crecen los enanows. Otra de pensar.

PENSAWR!!!

También podría pensar qué quiero y qué es posible, y luego pensar en cómo codificarlo todo. Quizá así me fuese mejor.

Pero ahora voy a fregal.

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