Objetivo
Después de practicar con lo que te explicaremos, deberías ser capaz de crear un Sprite utilizando la herramienta que mejor te convenga e incorporarlo a FUSION-C para darle color y moverlo por la pantalla con los cursores.
En este ejemplo trabajaremos utilizando el software de edición de imágenes Gimp, así como lo que ya hemos presentado hasta ahora.
¿Qué es un Sprite?
Un sprite es, en los videojuegos, un elemento gráfico que puede moverse sobre la pantalla. En principio, un sprite es parcialmente transparente y puede ser animado (es decir, está formado por varios mapas de bits que se superponen).
Diseñando un Sprite
Para esta guía, hemos decidido crear el Sprite de un gato de tamaño 16 x 16 píxeles.
Este es el resultado de dibujar el gato con el programa Gimp. Para que el Sprite del gato tenga un mínimo de detalle en cuanto al color, hemos decidido crear un Sprite con dos capas. Una capa tendrá el color principal del gato y la otra los lunares del gato. Esto lo trasladaremos al MSX como dos Sprites que moveremos al mismo tiempo como si fuera uno solo.
A continuación, te comento una herramienta de Gimp que puede ser muy útil para dibujar Sprites y luego convertir la información a bits para que pueda ser gestionada desde el MSX.
Esta herramienta es una cuadrícula del tamaño de un píxel para que podamos crear nuestros diseños de Sprites cómodamente desde Gimp.
Primero, desde la opción de menú "Imagen > Configurar cuadrícula", seleccionamos el tamaño de la cuadrícula a 1x1.
La rejilla no aparecerá hasta que la activemos desde el menú "Ver > Mostrar cuadrícula".
Una vez activada la rejilla, se nos mostrará en la imagen de la siguiente manera:
Cada cuadro de la rejilla corresponderá a un píxel.
Para hacer el gato, hemos creado una imagen transparente de 16x16 píxeles. Utilizando la rejilla, podemos diseñar Sprites con mayor precisión que con otras herramientas.
Si deseamos, también podemos incorporar en Gimp la paleta de 16 colores del MSX1 que podemos encontrar, por ejemplo, en formato Gimp en el siguiente enlace [1].
Diseñando la animación
Ahora que hemos introducido el diseño de un primer Sprite, diseñaremos otro Sprite para poder animar al gato.
La idea detrás de animar un Sprite es la misma que la animación tradicional en papel, donde se dibujan varias posiciones estáticas y se pasan las hojas rápidamente para generar la sensación de animación.
En la figura de arriba podemos ver la animación de seis marcos o frames de un gato. Nosotros simplificaremos esto a dos marcos. Al utilizar Sprites, gran parte de la gestión la realizará el VDP, ya que estamos utilizando lo que se conoce como Sprites hardware.
Para generar la animación iremos alternando entre los dos Sprites en pantalla mientras vamos moviendo la coordenada X.
La figura de arriba es el segundo Sprite de la animación. Igual que en el primer caso, se trata de dos Sprites o un Sprite compuesto por dos capas.
Ahora que ya tenemos los dos Sprites del gato, que puedes ver abajo, podemos pasar a trasladar esta información para poder utilizarla dentro de FUSION-C y realizar la animación. La animación se logrará superponiendo los Sprites uno encima del otro mientras los vamos moviendo en la coordenada X.
Convirtiendo lo que hemos dibujado a un lenguaje que la computadora entienda
Nuestros Sprites son de 16 píxeles horizontales y 16 píxeles verticales, es decir, de 16x16. En FUSION-C hemos decidido trasladar la información utilizando patrones de texto de 8x8, dividiendo el Sprite en cuatro patrones de la siguiente manera:
Trasladaremos la información del dibujo a la computadora utilizando el sistema binario. Un 1 indicará la presencia de un píxel y un 0 indicará la ausencia de un píxel.
En el caso del primer marco de movimiento del gato, como hemos mencionado que está compuesto por dos capas o Sprites, necesitamos 8 patrones de 8x8 para generar este marco.
El resultado trasladado a FUSION-C de la primera capa del Sprite del primer marco serían los cuatro patrones que se muestran a continuación:
static const unsigned char body_idle_pattern_right_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00011000,
0b00100000
};
static const unsigned char body_idle_pattern_right_2[] = {
0b00100000,
0b00100011,
0b00011111,
0b00001111,
0b00000111,
0b00000110,
0b00000010,
0b00000000
};
static const unsigned char body_idle_pattern_right_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char body_idle_pattern_right_4[] = {
0b00010100,
0b10011010,
0b11110000,
0b11110000,
0b11110000,
0b00111000,
0b00100000,
0b00000000
};
Para definir el Sprite en FUSION-C, utilizaremos la función SetSpritePattern, a la cual le pasaremos tres parámetros: el número de patrón, el array del patrón y el número de líneas del patrón.
Para nuestro primer Sprite, que consiste en la primera capa del primer marco de la animación, quedaría de la siguiente manera:
SetSpritePattern( 0, body_idle_pattern_right_1,8 );
SetSpritePattern( 1, body_idle_pattern_right_2,8 );
SetSpritePattern( 2, body_idle_pattern_right_3,8 );
SetSpritePattern( 3, body_idle_pattern_right_4,8 );
Aún nos falta trasladar la información del color. Sin la información del color, nuestro Sprite se vería de la siguiente manera si lo cargáramos:
Definimos la paleta de colores que utilizaremos.
Primero, debemos pasar la paleta de colores a utilizar a FUSION-C, que en el caso del MSX será una paleta de 16 colores. Para hacerlo, definiremos un array en el que cargaremos cuádruplas de datos con el siguiente formato:
Número del color de la paleta de MSX
R componente rojo con decimales
G componente verde con decimales
B componente azul con decimales
Los valores de R, G y B pueden ir desde 0 hasta 7.
Para nuestro ejemplo, utilizaremos la paleta de colores de MSX1, que en FUSION-C definiremos dentro de un array que podemos ver más abajo.
char mypalette[] = {
0, 0,0,0, // transparent
1, 1,1,1, // black
2, 1.7,5,2, // medium green
3, 3.1,5.7,3.4, // light green
4, 2.4,2.3,6.1, // dark blue
5, 3.5,3.2,6.6, // light blue
6, 5,2.5,2.2, // dark red
7, 2.7,6,6.5, // cyan
8, 6,2.7,2.4, // medium red
9, 7,3.7,3.4, // light red
10, 5.6,5.3,2.5, // dark yellow
11, 6,5.7,3.7, // light yellow
12, 1.5,4.4,1.7, // dark green
13, 5,2.8,4.9, // magenta
14, 5.6,5.6,5.6, // gray
15, 7,7,7 // white
};
Coloreando los Sprites
Una vez definida la paleta, será necesario transferir la información de color a los Sprites. Para colorear los Sprites utilizaremos la función de FUSION-C SC5SpriteColors. Esta función toma como parámetros el número de Sprite a colorear y una matriz donde se define para cada línea del Sprite su color.
Los arrays con la información de color de las líneas del Sprite tienen el siguiente formato.
char LineColorsLayer4[16]= { 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 };
char LineColorsLayer14[16]= { 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14 };
Aquí hemos definido los colores de las dos capas o Sprites del primer marco de la animación. La primera capa toma el color azul oscuro (dark blue) y la segunda capa toma el color gris (gray) de la paleta definida anteriormente.
SC5SpriteColors(1,LineColorsLayer4);
SC5SpriteColors(2,LineColorsLayer14)
Aquí estamos cargando la información de color al primer y segundo sprite del primer marco de la animación, que corresponden a la primera y la segunda capas del sprite.
El bucle de juego
Para que el programa esté siempre atento a nuestras acciones, debe ejecutarse continuamente. Mientras se ejecuta, en nuestro caso particular, el programa verificará si se ha presionado ESC para salir, o si se han presionado las flechas o la barra espaciadora para mover o hacer saltar nuestro sprite. A medida que avanzamos, volveremos a comentar el concepto del bucle de juego.
Todo el código que vamos a explicar a continuación estará enmarcado dentro de este bucle del programa, que se ejecuta infinitamente hasta que se presione la tecla ESC, que corresponde al código de tecla 27.
// Game loop
while (Inkey()!=27)
{
…
Screen(0);
Exit(0);
}
Moviendo el Sprite del gato por la pantalla
Inicializamos la posición del sprite del gato utilizando la función PutSprite fuera del bucle del juego. La función toma como parámetros el número del sprite, el patrón de inicio, la posición x e y en la pantalla, y el color del sprite. En MSX2, los colores vendrán definidos como hemos explicado antes, y este valor no tendrá ningún efecto.
x=79;
y=50;
PutSprite (1,0,x,y,4);
PutSprite (2,4,x,y,14);
El resultado de haber posicionado el sprite del gato en la posición x=79 e y=50 sería el de la imagen de abajo.
Ahora que hemos posicionado al gato, debemos hacer que al presionar los cursores izquierda y derecha, el gato se mueva hacia la derecha o se gire hacia la izquierda. Esto se logra con el siguiente código.
// Game loop
while (Inkey()!=27)
{
stick = JoystickRead(0);
space = TriggerRead(0);
// Right
if(stick==3)
{
x=(x+1);
x=screen_limits_x(x);
if( x % 2 == 0)
{
PutSprite (1,0,x,y,4);
PutSprite (2,4,x,y,14);
}
if( x % 2 == 1)
{
PutSprite (1,8,x,y,4);
PutSprite (2,12,x,y,14);
}
FT_wait(10);
}
// Right
if(stick==7)
{
x=(x-1);
x=screen_limits_x(x);
if( x % 2 == 0)
{
PutSprite (1,16,x,y,4);
PutSprite (2,20,x,y,14);
}
if( x % 2 == 1)
{
PutSprite (1,24,x,y,4);
PutSprite (2,28,x,y,14);
}
FT_wait(10);
}
}
Screen(0);
Exit(0);
}
En el fragmento de código anterior, podemos ver el control del movimiento del gato hacia la izquierda y hacia la derecha.
En la función JoystickRead, si le pasamos el parámetro 0, leeremos el estado de los cursores presionadas. Guardaremos el resultado de la función en la variable "stick" para poder tomar decisiones según lo que hayamos presionado en el código a continuación.
Analizando el fragmento de código donde "stick=3", lo cual indica que se ha presionado el cursor izquierdo, podemos ver cómo cambiamos el conjunto de los dos sprites que componen un gato dependiendo de si la coordenada x es par o impar. Esto lo hacemos mediante la división entera de la coordenada x entre 2.
Los valores posibles que puede tomar "stick" son los siguientes.
0 | inactivo |
1 | arriba |
2 | arriba + derecha |
3 | derecha |
4 | derecha + abajo |
5 | abajo |
6 | abajo + izquierda |
7 | izquierda |
8 | izquierda + arriba |
Ahora te dejo la lista de código, así como un enlace de una imagen de disco para poder ejecutarlo directamente.
//
// Fusion-C
// Example : Moving Sam Garcia The Cat 16x16 Sprites
//
#include "fusion-c/header/vdp_graph2.h"
#include "fusion-c/header/msx_fusion.h"
#include "fusion-c/header/vdp_sprites.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
/* --------------------------------------------------------- */
/* SPRITEs of Sam Garcia The Cat */
/* ========================================================= */
static const unsigned char body_idle_pattern_right_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00011000,
0b00100000
};
static const unsigned char body_idle_pattern_right_2[] = {
0b00100000,
0b00100011,
0b00011111,
0b00001111,
0b00000111,
0b00000110,
0b00000010,
0b00000000
};
static const unsigned char body_idle_pattern_right_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char body_idle_pattern_right_4[] = {
0b00010100,
0b10011010,
0b11110000,
0b11110000,
0b11110000,
0b00111000,
0b00100000,
0b00000000
};
static const unsigned char detail_idle_pattern_right_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_idle_pattern_right_2[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000001,
0b00000000,
0b00000000
};
static const unsigned char detail_idle_pattern_right_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_idle_pattern_right_4[] = {
0b00000000,
0b00000100,
0b00001110,
0b00001110,
0b00001100,
0b10000100,
0b10011000,
0b00000000
};
static const unsigned char body_walk_pattern_right_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00110000
};
static const unsigned char body_walk_pattern_right_2[] = {
0b01000000,
0b01000001,
0b00100011,
0b00011111,
0b00001111,
0b00011100,
0b00110000,
0b00100000
};
static const unsigned char body_walk_pattern_right_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00010100
};
static const unsigned char body_walk_pattern_right_4[] = {
0b00011010,
0b00010000,
0b10110000,
0b11110000,
0b11111000,
0b11101100,
0b00000100,
0b00000000
};
static const unsigned char detail_walk_pattern_right_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_walk_pattern_right_2[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000010,
0b00001100,
0b00001000
};
static const unsigned char detail_walk_pattern_right_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_walk_pattern_right_4[] = {
0b00000100,
0b00001110,
0b00001110,
0b00001100,
0b00000100,
0b00000010,
0b00000010,
0b00000000
};
static const unsigned char body_idle_pattern_left_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char body_idle_pattern_left_2[] = {
0b00101000,
0b01011001,
0b00001111,
0b00001111,
0b00001111,
0b00011100,
0b00000100,
0b00000000
};
static const unsigned char body_idle_pattern_left_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00011000,
0b00000100
};
static const unsigned char body_idle_pattern_left_4[] = {
0b00000100,
0b11000100,
0b11111000,
0b11110000,
0b11100000,
0b01100000,
0b01000000,
0b00000000
};
static const unsigned char detail_idle_pattern_left_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_idle_pattern_left_2[] = {
0b00000000,
0b00100000,
0b01110000,
0b01110000,
0b00110000,
0b00100001,
0b00011001,
0b00000000
};
static const unsigned char detail_idle_pattern_left_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_idle_pattern_left_4[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b10000000,
0b00000000,
0b00000000
};
static const unsigned char body_walk_pattern_left_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00101000
};
static const unsigned char body_walk_pattern_left_2[] = {
0b01011000,
0b00001000,
0b00001101,
0b00001111,
0b00011111,
0b00110111,
0b00100000,
0b00000000
};
static const unsigned char body_walk_pattern_left_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00001100
};
static const unsigned char body_walk_pattern_left_4[] = {
0b00000010,
0b00000010,
0b11000100,
0b11111000,
0b11110000,
0b00111000,
0b00001100,
0b00000100
};
static const unsigned char detail_walk_pattern_left_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_walk_pattern_left_2[] = {
0b00100000,
0b01110000,
0b01110000,
0b00110000,
0b00100000,
0b01000000,
0b01000000,
0b00000000
};
static const unsigned char detail_walk_pattern_left_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_walk_pattern_left_4[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b01000000,
0b00110000,
0b00010000
};
static const unsigned char body_impuls_pattern_right_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00110000
};
static const unsigned char body_impuls_pattern_right_2[] = {
0b00100000,
0b00100000,
0b00100011,
0b00111111,
0b00011111,
0b00001111,
0b00001000,
0b00011000
};
static const unsigned char body_impuls_pattern_right_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00010100
};
static const unsigned char body_impuls_pattern_right_4[] = {
0b00011100,
0b00010100,
0b00100000,
0b11100000,
0b11100000,
0b11100000,
0b00100000,
0b00100000
};
static const unsigned char detail_impuls_pattern_right_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_impuls_pattern_right_2[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000110,
0b00000100
};
static const unsigned char detail_impuls_pattern_right_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_impuls_pattern_right_4[] = {
0b00000000,
0b00001000,
0b00011100,
0b00011100,
0b00011000,
0b00010000,
0b00011000,
0b00001000
};
static const unsigned char body_salt_pattern_right_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00100000
};
static const unsigned char body_salt_pattern_right_2[] = {
0b00100000,
0b00110000,
0b00110011,
0b00011111,
0b00001111,
0b00000110,
0b00001100,
0b00001000
};
static const unsigned char body_salt_pattern_right_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00101000,
0b00111000,
0b00110100
};
static const unsigned char body_salt_pattern_right_4[] = {
0b00100000,
0b01100000,
0b11100000,
0b11100000,
0b11100000,
0b00100000,
0b01100000,
0b00000000
};
static const unsigned char detail_salt_pattern_right_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_salt_pattern_right_2[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000001,
0b00000010,
0b00000110
};
static const unsigned char detail_salt_pattern_right_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00001000
};
static const unsigned char detail_salt_pattern_right_4[] = {
0b00011100,
0b00011100,
0b00011100,
0b00011100,
0b00011000,
0b00001000,
0b00001000,
0b00000000
};
static const unsigned char body_impuls_pattern_left_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00101000
};
static const unsigned char body_impuls_pattern_left_2[] = {
0b00111000,
0b00101000,
0b00000100,
0b00000111,
0b00000111,
0b00000111,
0b00000100,
0b00000100
};
static const unsigned char body_impuls_pattern_left_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00001100
};
static const unsigned char body_impuls_pattern_left_4[] = {
0b00000100,
0b00000100,
0b10000100,
0b11111100,
0b11111000,
0b11110000,
0b00010000,
0b00011000
};
static const unsigned char detail_impuls_pattern_left_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_impuls_pattern_left_2[] = {
0b00000000,
0b00010000,
0b00111000,
0b00111000,
0b00011000,
0b00001000,
0b00011000,
0b00010000
};
static const unsigned char detail_impuls_pattern_left_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_impuls_pattern_left_4[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b01100000,
0b00100000
};
static const unsigned char body_salt_pattern_left_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00101000,
0b00111000,
0b00101100
};
static const unsigned char body_salt_pattern_left_2[] = {
0b00000100,
0b00000110,
0b00000111,
0b00000111,
0b00000111,
0b00000100,
0b00000110,
0b00000000
};
static const unsigned char body_salt_pattern_left_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000100
};
static const unsigned char body_salt_pattern_left_4[] = {
0b00000100,
0b00001100,
0b11001100,
0b11111000,
0b11110000,
0b01100000,
0b00110000,
0b00010000
};
static const unsigned char detail_salt_pattern_left_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00010000
};
static const unsigned char detail_salt_pattern_left_2[] = {
0b00111000,
0b00111000,
0b00111000,
0b00111000,
0b00011000,
0b00010000,
0b00010000,
0b00000000
};
static const unsigned char detail_salt_pattern_left_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char detail_salt_pattern_left_4[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b10000000,
0b01000000,
0b01100000
};
/* --------------------------------------------------------- */
/* SPRITE energia Sam Garcia The Cat */
/* ========================================================= */
static const unsigned char energia_pattern_1[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char energia_pattern_2[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00100000,
0b11000000,
0b11000000
};
static const unsigned char energia_pattern_3[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
static const unsigned char energia_pattern_4[] = {
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000100,
0b00000011,
0b00000011
};
// Functions prototypes
char FT_wait(int);
int screen_limits_x(int);
int screen_limits_y(int);
/* --------------------------------------------------------- */
char FT_wait(int cicles)
{
int i;
for(i=0;i<cicles;i++)
{
EnableInterupt();
Halt();
}
return(0);
}
int screen_limits_x(int x)
{
if( x < 0)
{
x=0;
}
if(x > 200)
{
x=200;
}
return x;
}
int screen_limits_y(int y)
{
if( y < 0)
{
y=0;
}
if(y > 160)
{
y=160;
}
return y;
}
/* --------------------------------------------------------- */
void main( void ) {
int x;
int y;
char strx[6];
char stry[6];
char stick;
char space;
char mypalette[] = {
0, 0,0,0, // transparent
1, 1,1,1, // black
2, 1.7,5,2, // medium green
3, 3.1,5.7,3.4, // light green
4, 2.4,2.3,6.1, // dark blue
5, 3.5,3.2,6.6, // light blue
6, 5,2.5,2.2, // dark red
7, 2.7,6,6.5, // cyan
8, 6,2.7,2.4, // medium red
9, 7,3.7,3.4, // light red
10, 5.6,5.3,2.5, // dark yellow
11, 6,5.7,3.7, // light yellow
12, 1.5,4.4,1.7, // dark green
13, 5,2.8,4.9, // magenta
14, 5.6,5.6,5.6, // gray
15, 7,7,7 // white
};
char LineColorsLayer4[16]= { 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 };
char LineColorsLayer14[16]= { 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14 };
char LineColorsLayer12[16]= { 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12 };
char LineColorsLayer3[16]= { 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 };
char LineColorsLayer2[16]= { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 };
char LineColorsLayer1[16]= { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
x=79;
y=50;
if(ReadMSXtype()==3) // IF MSX is Turbo-R Switch CPU to Z80 Mode
{
ChangeCPU(0);
}
SetColors(15,1,1);
Screen(5);
SetSC5Palette((Palette *)mypalette);
SpriteReset();
SpriteDouble();
// The 16 x 16 pixels Sprite is made of 4 patterns
SetSpritePattern( 0, body_idle_pattern_right_1,8 );
SetSpritePattern( 1, body_idle_pattern_right_2,8 );
SetSpritePattern( 2, body_idle_pattern_right_3,8 );
SetSpritePattern( 3, body_idle_pattern_right_4,8 );
SetSpritePattern( 4, detail_idle_pattern_right_1,8 );
SetSpritePattern( 5, detail_idle_pattern_right_2,8 );
SetSpritePattern( 6, detail_idle_pattern_right_3,8 );
SetSpritePattern( 7, detail_idle_pattern_right_4,8 );
SetSpritePattern( 8, body_walk_pattern_right_1,8 );
SetSpritePattern( 9, body_walk_pattern_right_2,8 );
SetSpritePattern( 10, body_walk_pattern_right_3,8 );
SetSpritePattern( 11, body_walk_pattern_right_4,8 );
SetSpritePattern( 12, detail_walk_pattern_right_1,8 );
SetSpritePattern( 13, detail_walk_pattern_right_2,8 );
SetSpritePattern( 14, detail_walk_pattern_right_3,8 );
SetSpritePattern( 15, detail_walk_pattern_right_4,8 );
SetSpritePattern( 16, body_idle_pattern_left_1,8 );
SetSpritePattern( 17, body_idle_pattern_left_2,8 );
SetSpritePattern( 18, body_idle_pattern_left_3,8 );
SetSpritePattern( 19, body_idle_pattern_left_4,8 );
SetSpritePattern( 20, detail_idle_pattern_left_1,8 );
SetSpritePattern( 21, detail_idle_pattern_left_2,8 );
SetSpritePattern( 22, detail_idle_pattern_left_3,8 );
SetSpritePattern( 23, detail_idle_pattern_left_4,8 );
SetSpritePattern( 24, body_walk_pattern_left_1,8 );
SetSpritePattern( 25, body_walk_pattern_left_2,8 );
SetSpritePattern( 26, body_walk_pattern_left_3,8 );
SetSpritePattern( 27, body_walk_pattern_left_4,8 );
SetSpritePattern( 28, detail_walk_pattern_left_1,8 );
SetSpritePattern( 29, detail_walk_pattern_left_2,8 );
SetSpritePattern( 30, detail_walk_pattern_left_3,8 );
SetSpritePattern( 31, detail_walk_pattern_left_4,8 );
SetSpritePattern( 32, body_impuls_pattern_right_1,8 );
SetSpritePattern( 33, body_impuls_pattern_right_2,8 );
SetSpritePattern( 34, body_impuls_pattern_right_3,8 );
SetSpritePattern( 35, body_impuls_pattern_right_4,8 );
SetSpritePattern( 36, detail_impuls_pattern_right_1,8 );
SetSpritePattern( 37, detail_impuls_pattern_right_2,8 );
SetSpritePattern( 38, detail_impuls_pattern_right_3,8 );
SetSpritePattern( 39, detail_impuls_pattern_right_4,8 );
SetSpritePattern( 40, energia_pattern_1,8 );
SetSpritePattern( 41, energia_pattern_2,8 );
SetSpritePattern( 42, energia_pattern_3,8 );
SetSpritePattern( 43, energia_pattern_4,8 );
SetSpritePattern( 44, body_salt_pattern_right_1,8 );
SetSpritePattern( 45, body_salt_pattern_right_2,8 );
SetSpritePattern( 46, body_salt_pattern_right_3,8 );
SetSpritePattern( 47, body_salt_pattern_right_4,8 );
SetSpritePattern( 48, detail_salt_pattern_right_1,8 );
SetSpritePattern( 49, detail_salt_pattern_right_2,8 );
SetSpritePattern( 50, detail_salt_pattern_right_3,8 );
SetSpritePattern( 51, detail_salt_pattern_right_4,8 );
SetSpritePattern( 52, body_impuls_pattern_left_1,8 );
SetSpritePattern( 53, body_impuls_pattern_left_2,8 );
SetSpritePattern( 54, body_impuls_pattern_left_3,8 );
SetSpritePattern( 55, body_impuls_pattern_left_4,8 );
SetSpritePattern( 56, detail_impuls_pattern_left_1,8 );
SetSpritePattern( 57, detail_impuls_pattern_left_2,8 );
SetSpritePattern( 58, detail_impuls_pattern_left_3,8 );
SetSpritePattern( 59, detail_impuls_pattern_left_4,8 );
SetSpritePattern( 60, body_salt_pattern_left_1,8 );
SetSpritePattern( 61, body_salt_pattern_left_2,8 );
SetSpritePattern( 62, body_salt_pattern_left_3,8 );
SetSpritePattern( 63, body_salt_pattern_left_4,8 );
SetSpritePattern( 64, detail_salt_pattern_left_1,8 );
SetSpritePattern( 65, detail_salt_pattern_left_2,8 );
SetSpritePattern( 66, detail_salt_pattern_left_3,8 );
SetSpritePattern( 67, detail_salt_pattern_left_4,8 );
SC5SpriteColors(1,LineColorsLayer4);
SC5SpriteColors(2,LineColorsLayer14);
SC5SpriteColors(3,LineColorsLayer12);
Sprite16();
// Printing initial coordinates on the Screen
PutText(0,10,"SCREEN 5",0);
sprintf(strx, "%i", x);
sprintf(stry, "%i", y);
PutText(83,10,"(",0);
PutText(91,10,strx,0);
PutText(113,10,",",0);
PutText(122,10,stry,0);
PutText(144,10,")",0);
// Positioning Sam on the Screen
PutSprite (1,0,x,y,4);
PutSprite (2,4,x,y,14);
// Game loop
while (Inkey()!=27)
{
stick = JoystickRead(0);
space = TriggerRead(0);
// Idle
if(stick!=0) {
sprintf(strx, "%i", x);
sprintf(stry, "%i", y);
PutText(83,10,"(",0);
PutText(91,10,strx,0);
PutText(113,10,",",0);
PutText(122,10,stry,0);
PutText(144,10,")",0);
}
// Up
if(stick==1)
{
y=(y-1);
PutSprite (1,0,x,y,4);
PutSprite (2,4,x,y,14);
FT_wait(10);
}
// Right
if(stick==3)
{
x=(x+1);
x=screen_limits_x(x);
if( x % 2 == 0)
{
PutSprite (1,0,x,y,4);
PutSprite (2,4,x,y,14);
}
if( x % 2 == 1)
{
PutSprite (1,8,x,y,4);
PutSprite (2,12,x,y,14);
}
FT_wait(10);
}
// Down
if(stick==5)
{
y=(y+1);
PutSprite (1,0,x,y,4);
PutSprite (2,4,x,y,14);
FT_wait(10);
}
// Right
if(stick==7)
{
x=(x-1);
x=screen_limits_x(x);
if( x % 2 == 0)
{
PutSprite (1,16,x,y,4);
PutSprite (2,20,x,y,14);
}
if( x % 2 == 1)
{
PutSprite (1,24,x,y,4);
PutSprite (2,28,x,y,14);
}
FT_wait(10);
}
// Button A
if(space==255 && stick==3)
{
PutSprite (1,32,x,y,4);
PutSprite (2,36,x,y,14);
FT_wait(10);
// Impulse
SC5SpriteColors(3,LineColorsLayer12);
PutSprite (3,40,x,y,12);
FT_wait(10);
SC5SpriteColors(3,LineColorsLayer2);
PutSprite (3,40,x,y,2);
FT_wait(10);
SC5SpriteColors(3,LineColorsLayer3);
PutSprite (3,40,x,y,3);
FT_wait(10);
SC5SpriteColors(3,LineColorsLayer1);
PutSprite (3,40,x,y,1);
FT_wait(10);
// Jump
x=x+20;
y=y-20;
PutSprite (1,44,x,y,4);
PutSprite (2,48,x,y,14);
FT_wait(10);
// Back to the floor
y=y+20;
PutSprite (1,0,x,y,4);
PutSprite (2,4,x,y,14);
}
// Button A
if(space==255 && stick==7)
{
PutSprite (1,52,x,y,4);
PutSprite (2,56,x,y,14);
FT_wait(10);
// Impulse
SC5SpriteColors(3,LineColorsLayer12);
PutSprite (3,40,x,y,12);
FT_wait(10);
SC5SpriteColors(3,LineColorsLayer2);
PutSprite (3,40,x,y,2);
FT_wait(10);
SC5SpriteColors(3,LineColorsLayer3);
PutSprite (3,40,x,y,3);
FT_wait(10);
SC5SpriteColors(3,LineColorsLayer1);
PutSprite (3,40,x,y,1);
FT_wait(10);
// Jump
x=x-20;
y=y-20;
PutSprite (1,60,x,y,4);
PutSprite (2,64,x,y,14);
FT_wait(10);
// Back to the floor
y=y+20;
PutSprite (1,16,x,y,4);
PutSprite (2,20,x,y,14);
}
}
Screen(0);
Exit(0);
}
Clica aquí para ver el ejemplo en funcionamiento.
Hola!
felicidades por el artículo, estoy empezando con los sprites en Fusion-C y me ha venido muy bien.
Una pregunta: ¿Por qué hay que poner los FT_wait para esperar ciclos? ¿Es para que no vaya tan rápido, o tiene que ver con algo de las interrupciones o los refrescos del VDP?
Gracias, y saludos!