Una cosa que siempre me resultó molesta de los MSX era que si dibujabas un cuadrado o un circulo, en pantalla aparecía un rectángulo o una elipse achatados respectivamente. Había que aplicar un factor de 1,4 aproximadamente en el eje Y para que visualmente tuvieran el mismo ancho que alto. Además, por lo que sé, esa relación entre los ejes X e Y es diferente si el ordenador es NTCS en lugar del PAL europeo. No quiero que mi juego tenga ese aspecto achatado característico así que estoy diseñando los gráficos con la Y multiplicada por ese 1’4:
Eso complica un poco las cosas porque si bien es fácil crear una elipse o un rectángulo con las dimensiones correctas, hacer que todas esas rayitas oblicuas queden en su sitio y correctamente orientadas tiene su dificultad. Al final el resultado ha sido más que satisfactorio (para mí):
Con la imagen del HUD de momento finalizada me he puesto por fin a codificar: carga de imágenes en VRAM, composición de la pantalla por capas, doble buffer y movimiento del puntero. En la película el punto de mira se mueve por el interior del circulo central del HUD con un mando y la posición de la cabina con otro (según he podido deducir). Yo por simplificar estoy haciendo que cuando el puntero llega al borde del círculo empuja a la cabina en esa dirección:
En este punto me he encontrado con otro problema. Limitar el movimiento dentro del círculo es relativamente sencillo en un computador con un procesador de 8 bits a 4MHz: no hay más que comprobar que la distancia al cuadrado del puntero al centro es menor que el cuadrado del radio del circulo (uso el cuadrado para evitar hacer la raíz cuadrada). Sooooolo queeee en realidad no es un círculo sino una elipse porque como soy tan guay quería que mis círculos no estuvieran achatados. Recuerda que aunque la imagen se muestre como la captura del MSX2 real, internamente el dibujo es la elipse de la primera imagen de esta entrada. Comprobar que un punto está dentro de una elipse no es tan trivial en un procesador como el que hemos mencionado. En este punto he tenido que ser imaginativo y calcular los límites de la elipse de forma off-line en una hoja de cálculo.
Como cada uno de los cuatro sectores en los que podemos dividir una elipse son simétricos dos a dos en los ejes vertical y horizontal, en realidad solo he tenido que calcular los límites del sector superior derecho. Para cada X he calculado la Y máxima y las he guardado en un array.
static TINY y[50] = { 69,69,69,69,69,69,68,68,68,68, 68,67,67,67,66,66,65,65,64,64, 63,62,62,61,60,59,58,58,57,56, 55,53,52,51,50,48,47,45,44,42, 40,38,36,33,30,27,24,20,14,0 };
Para comprobar que el punto de mira está dentro de los limites de la elipse, suponiendo que el centro de la elipse es el origen de coordenadas:
- Compruebo que el valor absoluto de la X del punto de mira es menor que la longitud de ese array.
- Si se cumple lo anterior, compruebo que el valor de la Y del punto de mira es menor que el valor guardado en el array para esa X.
x = abs(x); y = abs(y); if (x<50 && y<y[x]) { /* Mover punto de mira */ } else { /* Mover cabina */ }
Funciona, como se puede ver en el vídeo.
Continuará…
¿Y si multiplicas la altura Y por 1,4 antes de calcular la distancia al centro?
Es decir, r^2 = (y*1.4)^2 + x^2
(o igual hay que dividir, no me he parado a pensarlo bien, la verdad)
El problema principal es operar con decimales en C o en ensamblador, aparte de que el Z80 no tiene instrucciones de multiplicación o división. Tener pre-calculados los límites reduce la comprobación a un par de comparaciones y algunos saltos. Tendría que rebuscar en el código que genera el compilador de C para ver cómo queda en ensamblador.