Tutorial programacion Megadrive - SGDK

1, 2, 3, 4, 57
Ok, ya he conseguido mostrar tiles trasteando un poco, pero tengo una duda... me ha pasado algo un poco extraño

Metí en la carpeta "res" el archivo "moon.bmp" y me decia algo así como "no such file", después de unos cuantos intentos, meto junto a el archivo el moon.h que viene en tu proyecto... y me lo compila sin problemas.

Ahí pensé que había que generar el .h de alguna forma, pero borro el moon.h en res y también borro la carpeta res que hay dentro de la carpeta out para copiar el mensaje de error y postearlo aqui... y me compila sin problemas xD no entiendo qué ha pasado.
Vaaaale, es la magia de la programación xDD En teoria con meterlo en la carpeta res te debe geenrar el moon.h automáticamente... por estas cosas no uso genres, yo recomiendo tirar de imagenesis la verdad y usar la salida como texto, me gusta ver los datos que genero y saber lo que estoy usando.

He encontrado mi vieja demo del street fighter 2, en el próximo tuto de sprites pondré el fuente (que no es nada del otro jueves) para que trasteeis ;)

Imagen
weirdzod escribió:Ok, ya he conseguido mostrar tiles trasteando un poco, pero tengo una duda... me ha pasado algo un poco extraño

Metí en la carpeta "res" el archivo "moon.bmp" y me decia algo así como "no such file", después de unos cuantos intentos, meto junto a el archivo el moon.h que viene en tu proyecto... y me lo compila sin problemas.

Ahí pensé que había que generar el .h de alguna forma, pero borro el moon.h en res y también borro la carpeta res que hay dentro de la carpeta out para copiar el mensaje de error y postearlo aqui... y me compila sin problemas xD no entiendo qué ha pasado.

Pues no sé, a mí me funciona. Al menos con el Genres creo que cuando cambias o modificas un archivo de imagen tienes que darle a rebuild project, o borrar la carpeta out, para que te cargue y compile de nuevo la imagen, si no te cargará la que tenías antes, y si ya no existe te dirá que dará error de que ya no existe el archivo.

Por cierto para cargar imágenes con el GenRes no hay que meter los archivos en la carpeta res.

Estaría de escándalo pocket_lucho, te lo agreceríamos un montón.
pocket_lucho escribió:He encontrado mi vieja demo del street fighter 2...

Imagen

Cómo te gusta hacer sangre ...


XD
Pues eso, añadido nuevo tuto aquí y al hilo principal, tb he añadido el gran tutorial de Manveru Ainu y os recuerdo que si queréis hacer algún tuto o compartir código o lo que sea no os cortéis, que será bien recibido ;)

TUTORIAL DE SGDK 04: SPRITES

Pues aquí andamos de nuevo con un nuevo tuto que en conjunción con el anterior, en el que tratamos los tiles, va a empezar a darle vidilla a las primeras demos que os animéis a hacer.

Eso sí, si aún no te ha quedado del todo claro el funcionamiento y uso de tiles en megadrive es MUY recomendable volver al tuto anterior y dedicarle el tiempo necesario. Tampoco hay por qué agobiarse, no tiene maś historia que:

1.Crear los tiles con cualquier método disponible
2.Mandarlos a VRAM en una determinada posición
3.Dibujarlos en pantalla usando la función pertinente


Pero claro, hay que conocer las funciones necesarias y conviene tener claro también como funciona en líneas generales la memoria de vídeo. Se reitera, no tiene gran misterio, sólo requiere un poquito de paciencia y tal vez una pizca de concentración para pillar la idea de primeras.

Y tras habernos ido por las ramas para no pasar por alto que este tuto parte de la base de haber asimilado debidamente el anterior, damas y caballeros, con todos
ustedes "Los Sprites".

(Insertar FX "Ovación Multitud" ZzzZZ )

"Esto ... ¿y si yo no sé que es un sprite?"
Si ese es el caso, vamos con unos ejemplos visuales la mar de efectivos y así nos ahorramos la definición técnica que para eso se tira de wikipedia y listo.

Primero recordaremos que megadrive dispone de dos planos de fondo por hardware: plano A, plano B. Para por ejemplo dibujar en el B un mapa de tiles que contengan las montañas en la lejanía y en el A usamos tiles para dibujar una cordillera cercana. Llegado el momento haremos que el plano B se desplace más despacio que el A, horizontalmente los dos (tómate tus segundos para visualizar la idea, no hay prisa).

Y entonces a lo mejor, luego de visualizar mentalmente el ejemplo, piensas: "Oye, ¿se supone que ibas a hablar sobre sprites?". Sí, pero me viene al pelo el ejemplo de los mapas de tiles. Hagámonos a la idea de que los "mapas de tiles" dibujados en los planos A y B nos servirán para dibujar fondos y escenarios de nuestros juegos. Los "sprites" suelen ser los objetos, personajes o elementos que aunque lleguen a interactuar con el escenario no forman parte de éste.

Ejemplo: Sonic, Green Hill Zone
- "Mapa de tiles" en el plano A: el escenario
plataformero en primer plano

- "Mapa de tiles" en el plano B: el mar, bosquecillos
cascadas, montañas, nubes y cielo en segundo plano
(que se muevan independientemente es algo de lo
tal vez hablaremos en otro tuto)

- SPRITES: Sonic, los monitores, enemigos, anillos ...

En un juego de naves los sprites serán las propias naves, los bichejos enemigos, las explosiones, disparos y demás elementos que sean independientes del escenario.
Los sprites se dibujan sobre el "plano de sprites". Con lo cual ya tenemos que la megadrive dispone de:

- 2 planos para fondo (A y B)
- 1 plano para sprites
- 1 ?? (trollface), "plano Window", que en realidad será una parte inmóvil del plano A que sirve normalmente para meter los marcadores, etc.

Y ya por último antes de meternos en faena, enumeraremos algunas características (o puñeterías) de los sprites en megadrive.

- El plano destinado a los sprites tiene un tamaño fijo y no permite scroll. Normalmente 512x512 píxels, correspondiendo la coordenada 128,128 al primer píxel visible en la esquina superior izquierda de la pantalla. Con SGDK usaremos 0,0 como coordenada que indique el píxel de la esquina superior izquierda del plano de sprites, pero la consola en realidad no los maneja así internamente.

- Cualquier sprite fuera del área visible de pantalla no será visible. Puesto de otro modo, si sitúas un sprite de 16 píxels de ancho en la coordenada (-20, 128) dicho sprite no aparecerá en pantalla pero estar.. está.

- Si el valor dado a la coordenada X o Y del sprite excede el espacio del plano "vuelve" sobre el origen. Ejemplo: (300, 812) es lo mismo que (300, 300)

- Todos los sprites están identificados con un índice numérico y cuentan con un atributo que indica cuál es el sprite que le sigue a la hora de ser dibujado ("link"). El atributo link de nuestro último sprite ha de tomar el valor del índice que tenga el primer sprite que vayamos a dibujar. Si no lo hacemos así obtendremos el bonito número de cero sprites en pantalla. Podemos modificarlos más tarde para indicar prioridades entre los sprites... cual se dibuja encima de otros, imaginad los dragones del Space Harrier, cuyas partes cambian de prioridad según se acercan o alejan de la pantalla, para eso sirve.

- Máximo 80 sprites definidos simultáneamente.
- Máximo 20 sprites sobre una misma scanline ("en línea"), si te pasas... parpadean.

No es necesario aprendérselas de memoria, pero si tu demo o tu juego hace algo raro y no sabes por qué, dales un repaso a ver si algo de eso va a tener la culpa.

Y la idea básica y más importante:

- Los sprites están compuestos por tiles, podemos definir sprites desde 1x1 tile (8x8 píxels) hasta 4x4 tiles (32x32 píxels) usando cualquier valor intermedio, cosa que la todopoderosa snes no puede [poraki]

Por ejemplo (3x2 tiles = 24x16 píxels).

En el momento en que quieras usar sprites más grandes, ten en cuenta que megadrive cuenta con esos límites, por lo que tendrás que:

. definir varios sprites hasta completar el tamaño que necesites
. y tratar las coordenadas de esos sprites de manera adecuada para que en su conjunto formen la imagen que hayan de representar.

Vamos al lío ...


****************************************************/

// LIBRERIAS ////////////////////////////////////////
#include <genesis.h>

// DATOS GLOBALES ///////////////////////////////////


Cuando programando con SGDK definamos algún dato como const ("constante", el valor con que se inicialice ya no puede variar en todo el programa) dicho dato se amacenará en ROM en lugar de en la memoria RAM de 64Kb, así que los gráficos por ejemplo DEBEN declararse así.

Vamos a crear un array de cuatro tiles (2x2) que representarán la imagen de una bola. Éste será el gráfico de nuestro primer sprite. Pero aún queda mandanga después de definir el array. Paciencia que con esto simplemente tenemos la información gráfica, que ya es algo por otro lado.

const u32 spriteTiles[4*8]=
{
      0x00001111, // Tile izquierda arriba
      0x00001111,
      0x00111144,
      0x00111144,
      0x11112244,
      0x11112244,
      0x11112244,
      0x11112244,

      0x11112222, // Tile izquierda abajo
      0x11112222,
      0x11112222,
      0x11112222,
      0x00111122,
      0x00111122,
      0x00001111,
      0x00001111,

      0x11110000, // Tile derecha arriba
      0x11110000,
      0x44111100,
      0x44111100,
      0x44221111,
      0x44221111,
      0x44221111,
      0x44221111,

      0x22221111, // Tile derecha abajo
      0x22221111,
      0x22221111,
      0x22221111,
      0x22111100,
      0x22111100,
      0x11110000,
      0x11110000
};


Del mismo modo que en el tutorial anterior tuvimos que crear un struct "genresTiles" (sí, lo hicimos, si no te acuerdas, anda, búscalo y de le das el repasito) para manejar los tiles que nos creaba la herramienta "genres" provista por SGDK, en este caso haremos lo propio creando un struct que nos permitirá hacer buen uso de los sprites. Guarda gran similitud con "genresTiles" pero una importante diferencia a tener en cuenta es que los valores que usemos vendrán dados en píxels.

Le echamos un ojo:

struct genresSprites
{
      u16 *pal;       // Puntero a los datos de la paleta
      u32 **sprites;   // Puntero a los datos de los sprites
      u16 count;      // Numero de sprites
      u16 width;      // Ancho de cada sprite en pixels
      u16 height;      // Ancho de cada sprite en pixels
      u16 size;       // como usamos el ancho/alto en pixels, informacion importante en el tamaño del sprite
                  
};


Almacenamos los datos del exprite que nos haya generado "genres" sobre los atributos de un struct "genresSprites".

extern struct genresSprites sonic;


En el archivo "resource.rc" se habrá indicado el nombre de la variable de salida (sonic), la ruta del bitmap que contiene los frames de nuestro sprite y el tamaño en píxels en el que se han de dividir los distintos frames. En nuestro caso, de la siguiente manera:

SPRITE sonic "data/sonic.bmp" 24 32 0 7


Empecemos con el bucle principal, como en las otras ocasiones:

/////////////////////////////////////////////////////////////
// MAIN
/////////////////////////////////////////////////////////////
int main( ){

   // Dibujamos la cabecera austera de turno con VDP_drawText()
    VDP_drawText("Ejemplo de dibujo de SPRITES", 5, 1);
   VDP_drawText("----------------------------", 5, 2);


Igual que hicimos en el tuto anterior, hay que empezar por escribir los tiles que vayamos a requerir en la VRAM de la consola usando VDP_loadTileData(). La recordamos:

// VDP_loadTileData(const u32 *data, u16 index, u16 num, u8 use_dma):
   //  - data:    puntero a los datos de nuestro tile
   //            (o al primero de nuestra ristra tiles si es el caso)
   //  - index:   en qué posición de la memoria de vídeo (VRAM) vamos a
   //            almacernarlo (o a partir de qué dirección si son varios)
   //  - num:     cuántos tiles vamos a almacenar a partir de esa posición
   //  - use_dma: ¿usaremos o no "Acceso Directo a Memoria"?

        // "spriteTiles" es el nombre que le dimos al array con la información
   // gráfica de nuestro sprite-bola de 2x2 tiles.
        VDP_loadTileData( (const u32 *)spriteTiles, 1, 4, 1);


La llamada a esta función es opcional, pero es recomendable usarla para asegurarnos de que ningún sprite arranque con algún valor que no le hayamos dado nosotros y el consecuente desespero

VDP_resetSprites();


Digamos que por sistema, tras mandar a VRAM los tiles de un sprite, lo siguiente por hacer es cargar su paleta. Nuestro sprite-bola usará una de las predefinidas sin embargo.

Y ahora... Y AHORA ... Y AHOOOORA... lo definimos :)

Lo que viene a decir que le indicaremos a la megadrive que queremos crear un flamante sprite con las características que le indiquemos y ya que ella se encargue de rellanar los registros en una tabla contenida en la VRAM con los valores pertinentes.

Cada sprite que pensemos usar hemos de definirlo antes de poder hacer uso de él en el programa. Vamos a ver dos métodos de hacerlo y luego ya decides tú cuál te parece más conveniente (*cof*, el segundo, *cof*)

Primero veamos cómo definir un sprite usando la función básica que SGDK dispone para ello de modo, VDP_setSprite() :

// void VDP_setSprite(u16 index, u16 x, u16 y, u8 size, u16 tile_attr, u8 link)
   // - index:     índice numérico que identifica al sprite (desde 0 a 79)
    // - x:         coordenada x en pantalla en la que se situará
    // - y:         coordenada y en pantalla en la que se situará
    // - size:      tamaño en tiles (desde 1x1 a 4x4 tiles). Nos valdremos de la
   //              macro "SPRITE_SIZE()" para indicarlo
    // - tile_attr: atributos de los tile(s), (paleta, prioridad, vflip, hflip, pos_tile_VRAM)
    // - link:      índice del sprite que sucede al actual, cada sprite debe enlazar
   //              al siguiente, teniendo el último que enlazar con el primero
    VDP_setSprite(0, 40, 40, SPRITE_SIZE(2,2), TILE_ATTR_FULL(PAL0,1,0,0,1), 1);


Atendiendo a los valores que hemos pasado como parámetros podemos ver que nuestro primer sprite (sprite 0), tiene un tamaño de 2x2 tiles los cuales se tomarán a partir de la posición 1 de la VRAM. Ergo, nuestro primer sprite va a mostrar el gráfico de la bola que creamos al empezar el código. Una cosa a tener en cuenta, es que mientras que para dibujar tiles en uno de las capas A y B, la consola dibuja los tiles secuencialmente de izquierda a derecha y de arriba a abajo, para los sprites lo hace de arriba a abajo y de izquierda a derecha, hay que tenerlo en cuenta a la hora de meterlo en la vram, pero vamos, que de eso se encargará el conversor gráfico que usemos al especificar que es un sprite, ya sea genres, imagenesis, etc.

Veamos ahora otra manera distinta (¿más elegante?) para definir un sprite

   SpriteDef spriteBola2;


"SpriteDef" es un struct disponible en SGDK destinado a acoger los distintos datos que precisa un sprite. El primer paso de este método es proceder como en la línea de código anterior: simplemente creando un dato de tipo SpriteDef que nombraremos según nos plazca. La definición de SpriteDef en SGDK es la siguiente:

  // typedef struct
   // {
   //   s16 posx, posy;
   //   u16 tile_attr;
   //   u8 size, link;
   // } SpriteDef;
   // Los atributos se corresponden con cada uno de los parámetros requeridos por
   // VDP_setSprite() salvando la ausencia de uno para el índice del sprite


Creado el dato, inicializamos sus atributos.

   spriteBola2.posx = 0;
    spriteBola2.posy = 0;
    spriteBola2.size = SPRITE_SIZE(2,2);
    spriteBola2.tile_attr = TILE_ATTR_FULL(PAL0,1,0,0,1);
    spriteBola2.link  = 2;


Y llegado este momento usamos la función VDP_setSpriteP() para definir nuestro segundo sprite:

// void VDP_setSpriteP(u16 index, const SpriteDef *sprite)
   // - index:  índice numérico que identifica al sprite (desde 0 a 79)
   // - sprite: dirección de memoria donde se encuentra el struct
   //           con la información de nuestro sprite
   //           (nos valemos del operador & para ello)
    VDP_setSpriteP(1, &spriteBola2);


Está siendo un poco tocho pero es por pretender dejar clara la forma de proceder para crear sprites. Ahora que tenemos ya definidos dos sprites, un par de bolas que se desplazarán (o no) por pantalla, vamos a recapitular a modo de resumen los pasos para crear y mostrar sprites en pantalla:

1. Cargar los tiles necesarios en VRAM
2. Cargar la paleta (si no ha sido cargada previamente)
3. Definir el sprite
4. Definir más sprites
5. Solicitarle a la megadrive que nos los dibuje


Vamos a ver ya por último como definir us sprite creado desde genres y en unos minutos nos metemos POR FIN en cómo animarlos por pantalla, tanto en cuanto a desplazarlos por la pantalla como crear el efecto de animación intercambiando frames. Pero antes, lo dicho: definir sprites creados con genres.

La puñeta siguiente es porque nos va a interesar conocer el número de tiles de los sprites en el "spritesheet" (el bitmap con los frames de nuestro sprite) con que genres genera los sprites, y genres, de por sí no nos lo indica. Si no lo has visto antes, abre la carpeta data y échale un ojo a sonic.bmp, ése es el "spritesheet" que estamos usando en este tuto. ¡Ah! y recuerda que si vas a usar el tuyo propio: 16 colores y dimensiones múltiplo de ocho.

u16 nbTiles = (sonic.height>>3) * (sonic.width>>3);


Si la notación binaria aún no es lo tuyo, no pasa nada. Lo que hemos hecho es tomar el valor en binario del alto (height) del sprite y ventilarle los tres últimos dígitos, lo cual equivale a dividir por ocho de una manera más rápida que haciéndolo al uso. Hemos hecho lo propio con el ancho y luego multiplicado ambos valores. Esto es porque genres guarda tanto el ancho como el ato en píxels, no en tiles, y como ya sabemos, un tile tiene un tamaño de 8x8 píxels.

Si lo de "sonic" te extraña y no caes en qué momento hemos creado ese dato, fue antes de meternos con la función main. Así:

extern struct genresSprites sonic;


Importando a nuestro código los sprites creados con "genres". Justo antes creábamos el struct genresSprites. Vuelve a echarle un vistazo y repasar sus atributos, y si te sobra tiempo y estás de buenas repara en que estamos procediendo igual que en el tuto anterior cuando sólo requeríamos de genres tiles sin más. El atributo "sprites" va a entrar en acción en breve. Estate pendiente.

Puñeta anterior realizada, vamos a definir el nuevo sprite usando el método con el que definimos el anterior.

SpriteDef spriteErizo;


Esta vez no usaremos una paleta predefinidia sino que cargamos la paleta del spritesheet. Lo hacemos sobre PAL1. Fácil, ¿no?

VDP_setPalette(PAL1, sonic.pal);


Asignamos los que serán los valores iniciales que tome nuestro tercer sprite:

  spriteErizo.posx = 128;
    spriteErizo.posy = 128;
    spriteErizo.size = sonic.size>>8;
    spriteErizo.tile_attr = TILE_ATTR_FULL(PAL1,1,1,1,5);
    spriteErizo.link  = 0;  // Como éste va a ser el último sprite que definiremos
                     // lo hemos de enlazar ya con el primero cuya id es 0.
                     // Si se te olvida hacer esto no veremos sprite alguno.


Y tercer sprite definido:

VDP_setSpriteP(2, &spriteErizo);


Dijimos por ahí atrás que íbamos a animar un sprite frame a frame. Nuestra variable "frame" será la que indique cuál frame ha de ser mostrada.

  u8 frame = 0;


¡Ah!, ábrete la carpeta "data" y déjate a la vista el spritesheet. En el archivo "resource.rc" tenemos indicado que cada frame va a ser de 24x32 píxels con lo que cada imagen queda encuadrada debidamente en un área de ese tamaño. Y lo realmente importante es que genres nos lo deja a huevo para acceder a cada frame de forma muy cómoda: usando el atributo "sprites" como un array al que especificándole un determinado índice accedemos al frame que se encuentre en dicha posición (comenzando a contar de izquierda a derecha y de arriba a abajo). Por ejemplo, sonic.sprites[6] nos ofrecerá los datos del sexto sprite/frame: el Sonic rojo.


   // BUCLE PRINCIPAL ==================================================
    while(1){ // Bucle infinito al canto


Movemos el sprite "bola2" incrementando su posición en un píxel ambas coordenadas...

spriteBola2.posx++;
        spriteBola2.posy++;


Al usar de nuevo VDP_setSpriteP() pasándole unos valores modificados al sprite 1 (a la "bola2") lo que hacemos es actualizar sus propiedades:

        VDP_setSpriteP(1, &spriteBola2);


El sprite de Sonic lo moveremos por pantalla y a la vez que lo vamos a animar cambiando su frame continuamente ...

Escribimos en la posición 5 de la VRAM tantos tiles como correspondan a un frame (nbTiles, la puñeta de más atrás), tomándolos a partir del segundo sprite/frame del spritesheet (sonic.sprites[frame + 1]). Venga, que no es tan complicado. Reléelo unas cuantas veces teniendo a la vista el spritesheet si hace falta.

VDP_loadTileData(sonic.sprites[frame + 1], 5, nbTiles, 1);


Incrementamos el frame en cada iteración:

     frame++;


Y como los frames corresponidentes a la animación de correr, que son los que nos interesan, con la siguiente instrucción hacemos que cuando la variable frame vaya a tomar el valor 3 "se resetee" y vuelva a cero:

frame%=3;   // solo tenemos 3 frames, volvemos al primero


Movemos el sprite, modificando su coordenada x.

    spriteErizo.posx+=10;


Y registramos los cambios sobre el "sprite número 2" que no es otro que nuestro sonic presto a correr de una manera un tanto extraña.

VDP_setSpriteP(2, &spriteErizo);


VDP_updateSprites() hace que la consola tome en cuenta los nuevos valores que hayamos podido dar a los sprites. Vamos, que actualiza los sprites...

VDP_updateSprites();


Sincronizamos el dibujo con el retrazo horizontal de pantalla... unas cuantas veces, sí. Es un apaño para procurarnos un retardo conveniente y que nuestros sprites no vayan demasiado lanzados cuando se desplacen. Eres libre de comentar e invalidar tantos como te apetezca (conveniente también es dejar siempre uno al menos).

VDP_waitVSync();
        VDP_waitVSync();
        VDP_waitVSync();
        VDP_waitVSync();
        VDP_waitVSync();
        VDP_waitVSync();
        VDP_waitVSync();
        VDP_waitVSync();
        VDP_waitVSync();
    }

    return (0); // Return cero, y hasta aquí hemos llegado en esta ocasión.
}


Y con esto y un bizcocho ya sabemos dibujar tiles en las 2 capas y sprites.

Aquí os dejo el fuente del tutorial, recordad cambiar la ruta de vuestro makefile si no es como la mia.

https://dl.dropbox.com/u/33369593/tuto_ ... prites.rar

Imagen

Como deberes... cambiar los tiles de los sprites por algunos vuestros y hacer que se muevan con el pad estaría bien. También dejo el código de la demo que hice hace siglos del SF2, por si quereis cacharrear con ella, deberíais poder entender todo, lo único que no hemos visto es la función para dibujar mapas de tiles usada para dibujar el escenario de la que tratará un futuro tutorial.

Imagen

https://dl.dropbox.com/u/33369593/tuto_ ... ve/sf2.rar

De nuevo agradecer a Bruce las curradas que se mete comentando estos tutos, que sin él tendrian una periodicidad anual por lo menos xD

El próximo tuto va a ser muy sencillo para desatascar un poco las neuronas después de tanto tile, capas y sprites... va a ser como dibujar texto de forma bonita, cambiando la fuente que trae por defecto las SGDK por una bitmap!!
Grande pocket_lucho, todo muy bien explicado. Gracias a este tutorial he entendido algunas cosas que antes sabía que funcionaban pero no muy bien cómo. Luego me pondré a trastear con el Street Fighter.
Ya que me han dicho que me pase por aqui, comento un poquito xD
En primer lugar menuda currada este ultimo post.
Voy a añadir algun que otro dato relevante (o no xD).

pocket_lucho escribió: - Máximo 80 sprites definidos simultáneamente.
- Máximo 20 sprites sobre una misma scanline ("en línea"), si te pasas... parpadean.

Hay alguna restriccion mas, la lista completa:
- 80 sprites en el modo 320 pixels.
- 64 sprites en el modo 256 pixels.
- 20 sprites en una scanline en el modo 320 pixels.
- 16 sprites en una scanline en el modo 256 pixels.
- 320 pixels de sprite dibujados en una misma scanline (10 de 32 por ejemplo).
- 256 pixels de sprite dibujados en una misma scanline (8 de 32 por ejemplo).
- El sprite dibujandose tiene el campo link a 0 (bueno esta es clara xD).

Respecto al tema de "parpadear" (bueno si se rebasan los limites lo que pasa es que en esa linea no se dibujan los sprites a partir del pixel en el que ha ocurrido) en el caso de la NES, como se daba muy a menudo, la mayoria de los juegos "modernos" lo que hacian es alternar la prioridad de los sprites de hardware para que no siempre se ocultara el mismo (basicamente los iban rotando por la VRAM por eso tambien se le llama OAM Cycling), aqui se podria hacer lo mismo modificando el orden de los "links", claro que si quieres respetar el orden de dibujado la cosa se complica... jeje

Y ya que hablamos de los sprites, introduciras el concepto de metasprite?

pocket_lucho escribió:El próximo tuto va a ser muy sencillo para desatascar un poco las neuronas después de tanto tile, capas y sprites... va a ser como dibujar texto de forma bonita, cambiando la fuente que trae por defecto las SGDK por una bitmap!!

Y variable-width fonts? es una de las cosas que siempre me ha gustado ver en megadrive (y otras) que que yo recuerde no esta en NES (o en muy pocos juegos), la posibilidad que una letra no ocupe siempre un tile (o un numero fijo igual para todas).
Claro que entonces no se podria utilizar la funcion del SGDK pero, eh, es lo que mola no? hacer cosas raras xD

Y hasta aqui mi aportacion :D (o tocada de... xDDDD)
xDD Es que si los tutos ya son densos empiezo a mentar los 2 modos gráficos puedo empezar a inducir suicidios colectivos, pero vamos, que lo dices es correcto. Pero vamos, ¿quien iba a querer usar ese modo de resolución inferior digna de snes? Ah, si, capcom para el sf2' xD

Por ciertoooo, ¿alguien sabria programar un programita para partir bmps? Es que necesito formatear unos gráficos en un formato concreto y a mano es un coñazo...

Lo de la rutina de fuentes... si alguién la necesita y no le importa compartirla bienvenida será pero vamos, a mi con letras de 8x8 me vale, para un rpg evidenteme no... pero no me gusta programar rpgs asi que XD

¿por metasprite que quieres decir? Pq seria algo que es como un sprite, que se comporta como un sprite... pero no es un sprite... vamos, tiles en una capa ¿no? ¿O te refieres a sprites grandes que se componen de sprites pequeños? La de mo del sf2 son varios sprites para hacer un personaje, pero vamos, no los considero como nada especial, solo varios sprites que he de mover/actualizar a la vez.

Por cierto, la limitación de 320 pixels de sprites por scanline... a mi me parpadea los últimos xD (me hará unos 300).
pocket_lucho escribió:xDD Es que si los tutos ya son densos empiezo a mentar los 2 modos gráficos puedo empezar a inducir suicidios colectivos, pero vamos, que lo dices es correcto. Pero vamos, ¿quien iba a querer usar ese modo de resolución inferior digna de snes? Ah, si, capcom para el sf2' xD

Por ciertoooo, ¿alguien sabria programar un programita para partir bmps? Es que necesito formatear unos gráficos en un formato concreto y a mano es un coñazo...

Lo de la rutina de fuentes... si alguién la necesita y no le importa compartirla bienvenida será pero vamos, a mi con letras de 8x8 me vale, para un rpg evidenteme no... pero no me gusta programar rpgs asi que XD

¿por metasprite que quieres decir? Pq seria algo que es como un sprite, que se comporta como un sprite... pero no es un sprite... vamos, tiles en una capa ¿no? ¿O te refieres a sprites grandes que se componen de sprites pequeños? La de mo del sf2 son varios sprites para hacer un personaje, pero vamos, no los considero como nada especial, solo varios sprites que he de mover/actualizar a la vez.

Por cierto, la limitación de 320 pixels de sprites por scanline... a mi me parpadea los últimos xD (me hará unos 300).

Jeje, si, lo de la resolucion solia ser por crappy ports (tortugas ninja, sunset riders...)

Tell me more de eso de partir bmps, igual puedo hacer algo.

Lo de las fuentes yo lo decia por la tecnica que es curiosa, quiza podria mirarmelo un poco, pero con calma xD Unas rutinillas pal SGDK.

Con lo de metasprite me refiero a un objeto hecho de varios sprites si, pero tratarlo como uno (en nes se hace para todo porque los sprites son de 8x8 u 8x16 xD), por si ampliaras el tutorial mas adelante, pregunto.
Puuuues lo de los bmps es basicamente...

Pongamos que tengo una bonita tira de sprites de un tamaño el que sea, en este caso de 32x32, por lo que hay 2 frames (64x32) pero podrian ser 32x24, 16x8 etc.:

Imagen

Y necesito un programita que me formatee esa imagen en una de 16 de alto por lo que toque de ancho ordenando los tiles de esta forma:

Imagen

Esto es porque para comprimir los gráficos, uso un programita escrito por shiru creo que lo hace... pensando es sprites de 16x16 y ya, no hay ni fuente, ni opciones, ni naaaaa... En el Oh Mummy no he tenido problema poooorque... mis sprites son de 16x16, pero si sales de ahi, es un coñazo hacerlo a mano, pq luego cambias algo... y te toca partir la imagen de nuevo :(

Así que si algún alma caritativa se anima, ayudará mucho con la compresión de sprites xDD (se comprime con un ratio de cagarse, te ahorras de media más de un 80% de espacio y la rutina de descompresión es en ensamblador).

El tema de las fuentes más grandes... yo creo que sería fácil adaptar las actuales, solo que la fuente ocuparia el doble mínimo en vram... pero vamos, es como añadir acentos y tal, que se puede. Cuando se necesita algo que no está en las libs... pues se añade, como vereis en la demo del sf2 una rutina para dibujar mapas de tiles... pero es que todavía no ha habido un tuto de mapas de tiles que estará muy chulo pq tb veremos una rutina con mapas graaandes, de ejemplo vendrá la fase 1 del shinobi!! (por si alguno se anima a hacer el shinobi, seguro que sería bien recibido ;) ).

Pues este verano me estuve peleando precisamente con algo en ese plan, para hacer animaciones de sprites grandes rápidamente, pero entre el tema del compresor y que tuve problemas de gráficos corruptos... vi que era más rápido computacionalemte hacerlo de forma sencilla, pero vamos, que sería interesante verlo, me lo apunto ;)
La herramienta para partir bitmaps la empecé yo usando html5 y canvas, pero me atasqué, la dejé cogiendo polvo demasiado tiempo y ahora me supone poco menos que una labor titánica reemprenderla (vamos, que "vaguitis total").

Si alguien que controle por ese lado (html5+canvas) cree que puede echar una mano, aquí subí mi última versión en desarrollo:

http://beatemup1985.byethost7.com/splitter.htm

(copiaros el archivo html junto con la imagen de ejemplo si queréis y le echáis un ojo al código)

El interfaz viene a funcionar de modo que con el ratón se marca un área sobre la imagen, se le da al botón "new" y debería aparecer en el canvas central los tiles correspondientes debidamente ordenados y en el textarea inferior el array preparado para insertarse en el código del programa. En firefox se ve bien sin el antialiasing que le meten los demás navegadores al bitmap.

Si no, pues no me quedará otra que volver a pelearme con ello, porque el "troceo manual" que os ha explicado pocket_lucho es un coñaaaaazo del copón. Tener una herramienta así agilizaría muy mucho el trabajo.
Pero como con esto me hice la picha un lío y en principio me interesa tener la atención en otros frentes, si alguien echa un cable por ese lado ...
no se imagina el favor que le haría a la comunidad desarrolladora megadrivera
[tadoramo]

PD: si alguien se lo pregunta, desafortunadamente no, el nombre del subdominio no es indicador de absolutamente nada :p
Bueno aqui va la primera version del reorganizador de tiles, esta hecho en java (que es lo mio xD) asi que necesitareis tenerlo instalado, dentro viene un ejemplo de como usarlo.
A ver si os sirve y sino vamos retocandolo.

Adjuntos

Pues muchas gracias, funciona al pelo lo que he tenido tiempo de probar!! [amor]
Hola!

El programa me da un error:

Exception in thread "main" java.lang.UnsupportedClassVersionError: com/wave/gfx/
TileRelocator : Unsupported major.minor version 51.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: com.wave.gfx.TileRelocator. Program will exit.

Debo tener alguna versión de Java en concreto instalada?

Gracias y un saludo,
A mi con la última me va al pelo!
Cuando podáis a ver si podéis explicar un poco como va el tema de comprimir y usar bitmaps comprimidos, y si puede ser para cualquier tamaño mejor porque los míos son 24x24 y supongo que no se podrá reordenar a 16x16.
Si, si, no hay problema de usar 24x24 con el programita en java que ha hecho wave ;)
¿De que va lo que estas haciendo Manveru?
TriggerHappy escribió:Hola!

El programa me da un error:

Exception in thread "main" java.lang.UnsupportedClassVersionError: com/wave/gfx/
TileRelocator : Unsupported major.minor version 51.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: com.wave.gfx.TileRelocator. Program will exit.

Debo tener alguna versión de Java en concreto instalada?

Gracias y un saludo,

Pues lo he hecho con la version 7 aunque quiza podria hacer una compatible hasta la 5, le echare un vistazo.

EDIT:
Prueba con esta version que adjunto si tienes java >= 5, asi compruebo tambien si funciona porque yo solo tengo la 7.

Adjuntos

pocket_lucho escribió:Si, si, no hay problema de usar 24x24 con el programita en java que ha hecho wave ;)
¿De que va lo que estas haciendo Manveru?

Bueno he estado unos días sin tocar ésto y ahora seguiré intentando terminar a sonic y luego algún nivel para practicar. Como el sprite de sonic es 40x40 más o menos, me he visto obligado a dividirlo en 4 trozos de 24x24, y por ejemplo en cuanto ha echado a correr he tenido que activar el DMA porque se desincronizaban los sprites al dibujarlos. Digo como empiece a meter más cosas igual tengo problemas y necesitaré bitmaps comprimidos.
wave escribió:Pues lo he hecho con la version 7 aunque quiza podria hacer una compatible hasta la 5, le echare un vistazo.

EDIT:
Prueba con esta version que adjunto si tienes java >= 5, asi compruebo tambien si funciona porque yo solo tengo la 7.


Efectivamente con esta me va perfecto!

Gran trabajo, gracias!!!

Una solución rápida y elegante.

Si te apetece mejorarla aún más, podrías poner la opción de elegir fichero de entrada y de salida?

Un saludo y gracias de nuevo,
TriggerHappy escribió:
wave escribió:Pues lo he hecho con la version 7 aunque quiza podria hacer una compatible hasta la 5, le echare un vistazo.

EDIT:
Prueba con esta version que adjunto si tienes java >= 5, asi compruebo tambien si funciona porque yo solo tengo la 7.


Efectivamente con esta me va perfecto!

Gran trabajo, gracias!!!

Una solución rápida y elegante.

Si te apetece mejorarla aún más, podrías poner la opción de elegir fichero de entrada y de salida?

Un saludo y gracias de nuevo,

Bueno en el fichero .bat los ultimos 2 parametros son fichero de entrada y salida, si lo editas lo verás
wave escribió:Bueno en el fichero .bat los ultimos 2 parametros son fichero de entrada y salida, si lo editas lo verás


Sí, lo he visto. Pero creo que me resulta más cómodo renombrar el fichero, que entrar dentro del .bat a editarlo.

Ya que estamos, ¿puedo hacer otra petición de programa bastante parecido? :-)

Uno que uniera dos bmp, uno a continuación (a la derecha) del otro.

Así podríamos crear fácilmente un gráfico "master" e ir añadiendo los que creáramos nuevos a continuación...

O quizá conocéis alguno que te lo haga en 2 clicks? (que es lo que interesa, no ir cortando y pegando...)

Saludos!!
TriggerHappy escribió:
wave escribió:Bueno en el fichero .bat los ultimos 2 parametros son fichero de entrada y salida, si lo editas lo verás


Sí, lo he visto. Pero creo que me resulta más cómodo renombrar el fichero, que entrar dentro del .bat a editarlo.

Ya que estamos, ¿puedo hacer otra petición de programa bastante parecido? :-)

Uno que uniera dos bmp, uno a continuación (a la derecha) del otro.

Así podríamos crear fácilmente un gráfico "master" e ir añadiendo los que creáramos nuevos a continuación...

O quizá conocéis alguno que te lo haga en 2 clicks? (que es lo que interesa, no ir cortando y pegando...)

Saludos!!

A ver si te sirve este, el ultimo argumento es el fichero de salida, el resto de graficos son los que junta.

Adjuntos

Wave, he encontrado una cosilla, al convertir una imagen con tiles impares como 88x24, no convierte el último tile, genera una imagen de 128x16, cuando deberia ser 136x16 dejando el último tile como vacio, ¿eso se puede hacer?

Y garcias de nuevo por el programa ;)
pocket_lucho escribió:Wave, he encontrado una cosilla, al convertir una imagen con tiles impares como 88x24, no convierte el último tile, genera una imagen de 128x16, cuando deberia ser 136x16 dejando el último tile como vacio, ¿eso se puede hacer?

Y garcias de nuevo por el programa ;)

Sabia yo que alguna dimension daria problemas xD
Por cierto el programa no hace ningun tipo de comprobacion de tamaños ni si los archivos existen ni nada, a cualquier cosa de esas o petara o a saber que pasa xD

A ver si con esta version te funciona correctamente.

Adjuntos

Hombreeee, como cualquier programa bien hecho, sin comprobaciones ni na de na xD

Mañana lo compruebo y te digo ;)
Mientras espero pacientemente el siguiente tutorial, por aquí sigo toqueteando código y ahora he llegado a un punto donde me vendría bastante bien poder usar la librería stdarg.h para manejar funciones con un número de argumentos variables, pero veo que esta versión del gcc no la trae, ¿se puede añadir de alguna manera o no es posible o aconsejable?
Manveru Ainu escribió:Mientras espero pacientemente el siguiente tutorial, por aquí sigo toqueteando código y ahora he llegado a un punto donde me vendría bastante bien poder usar la librería stdarg.h para manejar funciones con un número de argumentos variables, pero veo que esta versión del gcc no la trae, ¿se puede añadir de alguna manera o no es posible o aconsejable?


El tema de usar gcc modernos ya fue discutido. Parece que las últimas versiones generan ejecutables poco eficientes para los Motorola por lo cual fueron desechadas. Ni idea de como añadir esa librería.
Ya sí por eso lo preguntaba. Si no se sabe, en caso de duda mejor no meterlo por si acaso, aunque sería una pena.
Siempre puedes escribir tu propio stdarg... yo he tenido que hacerlo que string.h [+risas]
Pues no tengo ni idea de cómo hacerlo, no sé haré una función por cada número de parámetros y va que chuta jejeje.

Una duda: ¿en qué momento captura SGDK las pulsaciones del mando? ¿Lo hace con el VDP_waitVSync()? Quería controlar una cosa pero me daba resultados aleatorios. Ahora he puesto el código justo antes del VDP_waitVSync() y funciona, pero no me vale con ponerlo a voleo hasta que vaya bien, me gustaría saber cómo funciona.
Buenas foreros,
Os comento, la cosa es que he visto estos tutoriales, que menudo currazo os habéis pegado cracks, y me ha entrado el gusanillo de volver a picarme con c, pero a penas he hecho nada gráfico y en java como que nunca he usado tiles en la carrera, ahora mismo empiezo 4 de teleco, así que os quería comentar, ¿algún consejo sobre en que debería de centrarme más aparte de los tiles y los mapas de sprites?
Un saludo y gracias de "antebrazo"
Buenas AkrosRockBell.
Nada con lo que ha puesto pocket_lucho tienes todo lo que necesitas sobre gráficos. Yo vengo también de java y c++(aunque nivel medio) y me estoy adaptando a c. Cuesta un poco si vienes de POO pero bueno es parte de la gracia de esto supongo.


Unas dudas para cuando podáis:

- ¿cómo hago para que cuando compile el proyecto se actualicen los archivos? A veces se pone tonto y tengo que estar borrando la carpeta "out" antes de darle a F9.

- Cuando un bitmap tiene transparencias, ¿si lo dibujo encima de otro, las trasparencias muestran la imagen inferior o el fondo negro de la pantalla? Me ha pasado lo segundo y no sé si he hecho algo mal.

- Sigo aprendiendo a programar siguiendo el tutorial de inicio con Sonic. Ahora he metido un fondo, en este caso intento copiar el de Green Hill de Sonic 1. Está compuesto por media pantalla de color cielo y otra azul agua (en ambos casos un tile usando VDP_fillTileMapRect), luego un bitmap con las montañas (bitmap 320x72) y por último otro con el acantilado con las cascadas (320x40) -aún no he hecho los cientos de tiles del reflejo en el agua-. Los 3 primeros los cargo una vez y quedan fijos, el del acantilado se actualiza cada 5 iteraciones del while para hacer la animación de la cascada. Además está el sprite de Sonic con sus animaciones y movimientos. Pues bien sólo con ésto al mover a Sonic ya me va a saltos, aunque los FPS siguen marcando 60.
Tengo activado el DMA, supongo que será cosa de comprimir los bitmaps, a ver si me sabéis decir por qué pasa ésto. Voy a hacer que sólo se actualicen las cascadas para aligerar, pero vamos por practicar porque aún faltan mil cosas y ya va todo justo...
Pues no se tio, pon el fuente el algun lado y le doy un vistazo a ver que has hecho xD

El tema el pad se comprueba en el vblank... asi que... si, se comprueba en el VDP_waitVSync().
Bueno voy a seguir que se van ocurriendo cosas para mejorar ésto, ya te cuento.
Lo del mando gracias, a ver si vuelvo a donde lo dejé porque me estaba rayando que a veces funcionase y a veces no.
Lo de las transparecias después he caído que es normal que la transparencia sea otro plano o el "fondo" de la consola, si no la Mega tendría 500 planos jejejeje. No sé si es correcto pero he pensado usar el plano B para los bitmaps fijos y el A para las animaciones del decorado.

Sí me interesaría arreglar lo de tener que borrar la carpeta "out" porque no compila bien (F9: "buid and run"), más que nada porque es un trabajo tonto y se pierde mucho tiempo. Me he dado cuenta que si los cambios se hacen en el archivo "main.c" sí se sobreescribe la salida al compilar, pero si modifico otro archivo tengo que borrar la careta "out" y luego F9 para que se cree la salida de nuevo con los cambios en el código. No sé si tiene algo que ver, pero me da otro error cuando le doy a "clean" o "rebuild workspace": "Error cleaning "Sonic - default"". El tutorial de instalación está hecho bien tal cual...por cierto me recomiendas mejor CodeBlocks o Eclipse.
Yo uso el codeblakcs y me hace el clean bien...
He desinstalado todo y vuelto a poner y a rehacer el tutorial de instalación y ahora va bien lo de clean o rebuild [+risas] , lo único que sigue sin actualizarse cuando le doy a F9, supongo que sólo compila el archivo no todo el proyecto. Si no se te ocurre algo simplemente me acostumbraré a darle a Ctrl-F11 (rebuild) en vez de a F9.

EDITO: vale, edito el mensaje porque lo que me decía con F9 era por haber puesto el compilador de la Mega por defecto.
Chavales a ver si algún alma caritativa que tenga tiempo hace algún tutorial para todo el tema de dibujar el mundo, la cámara, la carga de sprites según estén en zona visible o no, etc. He estado leyendo un poco y estoy bastante confuso con el tema de las coordenadas del nivel, las de la pantalla, de los personajes... Si no se agradecería un enlace a algún wiki o tuto para poder aprender cómo se hace ésto en la Megadrive.
Manveru Ainu escribió:Chavales a ver si algún alma caritativa que tenga tiempo hace algún tutorial para todo el tema de dibujar el mundo, la cámara, la carga de sprites según estén en zona visible o no, etc. He estado leyendo un poco y estoy bastante confuso con el tema de las coordenadas del nivel, las de la pantalla, de los personajes... Si no se agradecería un enlace a algún wiki o tuto para poder aprender cómo se hace ésto en la Megadrive.

Pues yo diria que es lo mas complicado del asunto, el tema de tener un mundo grande, ir cargandolo a trozos (algunos elementos tienen estado, si un puente se ha caido, una plataforma que se mueve...), las fisicas, interacciones entre objetos...
No creo que haya ningun tuto para la megadrive especificamente, pero lo primero que habria que pensar es un formato "standard" para la carga de mundos.
Vistos los tiles y sprites, el siguiente paso logico es ver mapas y deteccion de colisiones. Y ahi es donde empieza la programacion jejejeje
Ya ya jejeje, es que con otras librerías todo este tema de cámaras y tal se hacían ejecutando 2 funciones y todo automático, y aquí parte de la magia es hacerlo todo en manual, aunque claro a mí me pilla en bragas [+risas]
Manveru Ainu escribió:Ya ya jejeje, es que con otras librerías todo este tema de cámaras y tal se hacían ejecutando 2 funciones y todo automático, y aquí parte de la magia es hacerlo todo en manual, aunque claro a mí me pilla en bragas [+risas]

Siempre se pueden crear aqui esas librerias y que sirvan a otros :D
Pues sí que estaría bien, aunque yo prefiero aprender y hacerlo por mí mismo, pero ahora mismo estoy atrancado y parado y espero no desanimarme, pero es que no sé por dónde empezar.
Yo siento no poder oner el siguiente pero es que no tengo tiempo material para nada [buuuaaaa]

El proximo tuto iba/va a ser compresion de tiles en rom y como poner una fuente bonita, asi aprovechamos para juntar las dos cosas.
Tranquilo pocket_lucho, sé que estás muy liado con el Oh Mummy, tú acaba con eso y cuando puedas sigues con los tutos. Yo estoy aprovechando de mientras para ir mejorando en C y viendo cómo se hacen juegos en otros formatos para hacerme una idea. Además tiene su encanto comerte el coco para hacer algo que no sabes [fumando] .
esto... ¿Cómo he de meter una cizalla para que GenRes sólo me coga un solo sprite de ese color y no me llene la memoria con sus 1200 sprites del mismo color, o cómo puedo manejar la memoria resultante del out de GenRes?
Si no me equivoco, GenRes sólo convierte los archivos de bitmaps en sprites, luego eres tú el que tienes que cargar en memoria (uno a uno) los que necesites usando el array sprites de la estructura genresSprites donde Genres carga cada sprite de un archivo.
Serialare-ostiapoder usar el TileStudiopara diseñar el TileSet y los mapas importando ese TileSet. Como para GBA por ejemplo,solo necesitamos crear el Script de salida para que genere el codigo C, ASM, Binario, etc
Estoy pensando en hacerme una herramienta yo mismo... alguien sabe los valores RGB de los 512 colores de Megadrive?

http://en.wikipedia.org/wiki/List_of_mo ... #9-bit_RGB

Supongo que puedo fiarme de esto...

¿Alguien se anima a trabajar en el proyecto? D:
343 respuestas
1, 2, 3, 4, 57