Tutorial programacion Megadrive - SGDK

13, 4, 5, 6, 7
he hecho todo lo que me comentasteis y por desgracia esto sigue sin compilar [mamaaaaa]

me sale un mensaje extraño al iniciar codeblocks

Imagen

hay un detalle que no he mencionado sobre la maquina virtual de windows xp que uso, no le he instalado los drivers, lo veo una estupidez pero ¿podria tener algo que ver? aunque lo dudo mucho [carcajad]

gracias por vuestra ayuda compañeros [oki]
Ese error de inicio se debe a que no debes tener instalado el compilador por defecto (Mingw) pero para la Megadrive no lo necesitas. Pon una pantalla con los mensajes de error y como tienes configurado el proyecto.
En Settings->Compile te aparece una lista desplegable, ahi debes tener el compilador que has clonado para la MegaDrive.

Pulsa el botón Set Defaullt para que por defecto use ese
He probado a ponerlo, las SGDK 1.11 y el Code Blocks 13.12 y me compila los ejemplos que traen. He seguido el tuto de Lucho y sólo he tenido que hacer unos cambios:

- En las variables de entorno, en lugar de poner c:\sgdk y c:/sgdk, he puesto donde tengo la carpeta con las sgdk, en mi caso: c:\megadrive\sgdk111 y c:/megadrive/sgdk111.
- En el compilador pon donde tengas las sgdk, y en las toolchain en lugar de bintoc.exe tienes que cargar bintos.exe, y en debugger elegir defaut.
- En las propiedades del proyecto, en lugar de c:\sgdk\makefile.gen he puesto donde lo tengo yo, en mi caso como dije antes: c:\megadrive\sgdk111\makefile.gen.
- En project build options, en lugar de aparecer default aparece debug y release. Haz los cambios en ambas (básicamente es borrar el $target si no me falla la memoria).

Con esto ya me ha funcionado, comenta cualquier problema ;)
mmmm lo siento amigos, por lo visto no quiere funcionar :(

el compañero nolddor muy amablemente se ha puesto en contacto con migo y vamos a ver si por via telegram podemos solucionar esto [carcajad]
Si nadie dice lo contrario ayer por telegram quedó solucionado.
Buenas el código fuente de BugHunt está por fin disponible en github por si alguien le sirve o le ayuda pegarle un vistazo.

BugHunt for Sega Mega Drive / Genesis on Github
Saludos.
Que era lo que fallaba
???
Como no se muy bien que habia hecho bien o mal simplemente desinstalo todo y lo fue instalando paso a paso segun le iba diciendo por telegram en algun punto se habría confundido supongo
Buenas:

Me ha sorprendido mucho este tutorial del primer post.

En estos momentos aprendiendo este otro tutorial con BASIC, muy buen tutorial también, me encuentro con este gracias a que hice esta pregunta ya que no entiendo muy bien como trabajar con Photoshop y menos con Gimp.

He visto que falta algunas imágenes en el tutorial, también enlaces rotos con el dropBox. ¿El autor sigue aún en pie?
Es un mega tutorial muy bueno que necesita esos archivos listo para descargar, a parte de eso, el google code, también está desactualizado y te redirecciona a GitHut, a parte de eso, Code Google desaparecerá por el , así que es bueno sustituir los nuevos enlaces por si acaso.

Espero que actualice su tutorial, es muy buen tutorial y se merece lo mejor.

Saludos.
Hombre, seguir seguimos en pie.

Cada cual con sus asuntos y cada uno dándole caña a temas megadriveros por lados distintos (no muy separados tampoco) pero sí que hace ya tiempo que aparcamos los tutos y de hecho hasta terminamos pasando un tanto de las sgdk.

El dropbox es el de Lucho que se asoma poco por aquí. Le daré el toque por lo menos para corregir los enlaces.

Gracias por lo que nos toca ;)

EDIT: después de unas rápidas pesquisas mucho me temo que al menos de manera indefinida los tutos van a tener que quedar relegados a esa base teórica que sigue estando disponible.

Tampoco es que los originales los conservemos por ningún lado ^_^UUU pero sobre todo sucede que la evolución de las librerías sgdk ha sido notable desde entonces y el problema de incompatibilidades con códigos basados en una versión obsoleta iba a estar a la orden del día.

De cualquier manera mantengo que como base teórica siguen siendo válidos y aquí queda el hilo para resolver dudas cuando surjan :)
Buenas:

Le he avisado por privado al creador de este tema para que corrija los enlaces. Así me bajo todos los ejemplos.

Eso si, lo bueno que hagan más tutoriales entre todos aunque sean cosas tontas. Una cosa tonta que quiero hacer es solo manejar textos, hacer menús y navegar por él. Por ejemplo:

La duda es ser capaz de crear textos en pantalla y navegar entre menús. Por cada botón un menú, si pulsas el botón z por poner un ejemplo, vuelves a la pantalla principal, si pulsas START limpia toda la pantalla, si pulsas cualquier botón, por ejemplo el btón A, llega a un mensaje de texto que dice Pantalla A para saber que has pulsado botón A.

Imagen
Aunque sea sencilo de usar los switch case, puede haber novatos como curiosidad ver este tipo de cosas, así se harán tutoriales de todo tipo.

Lo que no se si se puede manejar la eeprom del juego para controlar algunos pines activarlo o desactivarlo a 1 o a 0.

Saludos.
Yo sigo usando SGDK, no me importa resolver las dudas específicas que vayan surgiendo, se libre de envirme un PM cuando lo necesites.

Además tienes el código fuente de Chase y Bughunt que fueron liberados junto al juego, con eso puedes ver un poco como es el código de un juego completo.
Buenas:

Lo bueno sería que se animen hacer mini tutoriales de lo que sea entre todos y luego poco a poco ir recopilándolo.

Voy a mirar esos enlaces.

Gracias por la información.
Hola a todos, he comenzado el tutorial para ver si hago alguna cosita para la negrita.
De inicio el primer tutorial, con el "hola mundo", no funciona, da un error de "instrucción ilegal".

Me he vuelto loco 2 días, al final este otro "hola mundo" sí funciona:

#include <genesis.h>
int main()
{
       VDP_drawText("Hello World!", 10, 13);

    while(1){
        VDP_waitVSync();
    }

       return (0);
}


Por algún motivo, con el último SGDK y el último CodeBlocks, hay que meter el while() o da error.
¿Alguno sigue aún tocando la scene de MD?
@danibus
si llega al return 0, el programa acaba, de ahí el error
el programa debe quedar en ejecución, de ahí que necesites el bucle
@Troopa Jr
Así es, pero como en el tuto no lo específica y pone que lo pruebes [360º]
Voy a seguir dándole al tema . Gracias por contestar
jelou

Estoy probando a mover sprites por pantalla. Problema, si la detección del mando la hago con

JOY_init();
JOY_setEventHandler( &myJoyHandler );


tristemente cada vez que pulso un botón, el sprite se mueve.... 1 vez.
No vuelve a ejecutar la función hasta que suelto el botón y le vuelvo a dar. Imposible dejar pulsado derecha y que se mueva el sprite.

Si lo hago en plan cutre, una función que teste el valor de los botones en el bucle principal del main, funciona perfectamente.

Edit: Decir que estoy mirando el ejemplo "joytest" del SGDK. Que raro, hace ambas cosas a la vez, por un lado detecta de forma asíncrona los botones A,B,C y por otro en cada frame lee RIGHT, LEFT con una llamada desde el main.
Justo hace unos días me pasó lo mismo.
Al parecer, el JOY_setEventHandler hace que se llame a la función que pasas (callback) cuando hay un cambio. Como mantener un botón no es un cambio... No llama al callback más.
Al final, opté por hacer un gestor de inputs por mi cuenta (algo similar a lo que comentabas, pero un poco más elaborado).


Edit: otra opción que se me acaba de ocurrir sería :
1 Guardar los parámetros pasados al callback (u16 changed, u16 state),
2 Procesarlos dónde toque LogicaInput() por ejemplo (haciendo el jugador.x++ o poniendo estados -como "saltando"-)
3 Después de procesarlo, resetear el changed a 0 dado que esos cambios ya se procesaron.
4 En las siguientes llamadas a LogicaInput() del while de main no habrá change, pero el "state & CONSTANTE_BOTON" dará true y además tendrás el estado a "saltando".

De esa forma, el callback sería la parte donde recuperas cambios y estado de botones dejando la lógica en otra parte.
Gracias. Por cierto, callback, manejador... No hay otra traducción? Me chirrían y creo que en mis tiempos de C tenían otro nombre.
Interrupciones software? No me acuerdo
Programar para la Mega es algo que sé que voy a hacer sí o sí, lo que pasa que entre que ahora tengo bastante carga de trabajo y que también estoy metido en un proyecto personal, tenía pensado postponerlo (y es la mejor decisión).

Pero es difícil resistir porque es algo que me apetece mucho... así que qué narices, vamos a ello XD

Iré comentando por aquí mis dudas, que serán muchas, y progreso, que será menos.
danibus escribió:Gracias. Por cierto, callback, manejador... No hay otra traducción? Me chirrían y creo que en mis tiempos de C tenían otro nombre.
Interrupciones software? No me acuerdo


Internamente entiendo que es un puntero a función al que se le llama.
En la documentación/tutorial de las SGDK lo llaman callback y por éso use dicha nomenclatura.
https://github.com/Stephane-D/SGDK/wiki/Tuto-Input
He visto que la traducción sería "retrollamada"... se me hace raruna.

@matasiete : Yo me lo estoy pasando bien refrescando C y viendo que funcionan cosas en la Megadrive (es como un pequeño sueño hecho realidad [risita] ).



PD: Para trabajar con paletas de las imágenes y dibujar en general me está funcionando muy bien el Aseprite (además de tener scripts). Lo comento por si os dan problemas otros editores.
Os dejo por aquí un par de demos que piqué para enseñar algunos conceptos a un compañero.

Ésta primera es sobre usos del modo HL/S con SGDK (que en lo relativo a la aplicación de prioridades a los planos es para mi gusto "demasiado peculiar"). Pero bueno, tampoco tiene en el fondo tanto enredo.

Imagen

Test HLS Planos SGDK - Proyecto Code Blocks

#include "sprite.h"

// CONSTANT VALUES ////////////////////////////////////////
#define SCREEN_WIDTH_TILES     40
#define SCREEEN_HEIGHT_TILES   28

#define SCENARIO_POS_X          0
#define SCENARIO_POS_Y          0

#define SCENARIO_WIDTH_TILES    SCREEN_WIDTH_TILES
#define SCENARIO_HEIGHT_TILES   SCREEEN_HEIGHT_TILES

#define SCENARIO_NUM_TILES      SCENARIO_WIDTH_TILES * SCENARIO_HEIGHT_TILES


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

    // Local data _________________________________________

    // Scenario (planes)
    u16 tilemap_buffer[SCENARIO_NUM_TILES];

    u16 *shadowmap_tilemap = bga_priority_image.map->tilemap;
    u16 *aplan_tilemap = &tilemap_buffer[0];

    u16 numtiles = SCENARIO_NUM_TILES;

    // Sprite stuff
    u16 sprite_x, sprite_y, sprite_movx, sprite_movy;
    Sprite* sprite;

    // Process ____________________________________________

    // Dump BGA tilemap into RAM
    memcpyU16(aplan_tilemap, bga_image.map->tilemap, SCENARIO_NUM_TILES);

    while(numtiles--)
    {
        if(*shadowmap_tilemap)
            *aplan_tilemap |= TILE_ATTR_PRIORITY_MASK;

        aplan_tilemap++;
        shadowmap_tilemap++;
    }

    // Load tileset and tilemap for APLAN
    VDP_loadTileSet(bga_image.tileset, bgb_image.tileset->numTile, DMA);
    VDP_setTileMapDataRectEx(PLAN_A, &tilemap_buffer[0], 0/*u16 basetile*/,
        SCENARIO_POS_X, SCENARIO_POS_Y,
        SCENARIO_WIDTH_TILES, SCENARIO_HEIGHT_TILES, SCENARIO_WIDTH_TILES);

    // Load scenario for BPLAN "as it is"
    VDP_drawImage(PLAN_B, &bgb_image, SCENARIO_POS_X, SCENARIO_POS_Y);

    // Init and load the sprite
    SPR_init(16, 256, 256);
    sprite_x = 0; sprite_y = 0; sprite_movx = 1; sprite_movy = 1;
    sprite = SPR_addSprite(&star_sprite, sprite_x, sprite_y, TILE_ATTR(PAL3, TRUE, FALSE, FALSE));

    // Set the palette taken from the scenario (BLAN image)
    VDP_setPalette(PAL0, (u16*) bgb_image.palette->data);

    // Set the palette from the sprite
    VDP_setPalette(PAL3, (u16*) star_sprite.palette->data);

    // Enable HL/S mode
    VDP_setHilightShadow(1);

   // LOOP
   while(TRUE)
    {

        // Check border collisions (reverse mov)
        if(sprite_x < 0 || sprite_x > 304) sprite_movx *= -1;
        if(sprite_y < 0 || sprite_y > 196) sprite_movy *= -1;

        sprite_x += sprite_movx; sprite_y += sprite_movy;

        SPR_setPosition(sprite, sprite_x, sprite_y);

        SPR_update();

        VDP_waitVSync();
    }

    return 0;
}


Imagen

En líneas generales...
  • Cada pantalla/escenario (que va volcado sobre el plano B) tiene que tener su correspondiente imagen de mapa de prioridades. Como digo, para rellenar, como placeholder, vale una imagen negra entera.
  • Aparte y sólo siendo necesaria una imagen de este estilo para todo el juego: necesitamos, ahora sí, y tiene que ser así y no de otra manera, una imagen negra entera que será realmente el contenido gráfico que se volcará al plano A (de lo que hablábamos antes era de mapas de prioridades: "este tile va en alta, este otro tile va en baja...").
  • El mapa B se carga y se dibuja tal cual (y a la hora de exportar desde rescomp le podemos decir que use la compresión óptima BEST).
  • El mapa A general (negro) lo volcamos a un buffer y con un bucle le aplicamos la prioridad a cada tile según nos indique el mapa/imagen de prioridad correspondiente a esa pantalla. (Eso lo hace el bucle del código que empieza por "while(numtiles--)").
    Con eso anterior ya hemos parcheado la información del tilemap A con las prioridades que toque.
  • Entonces, a diferencia del plano B que como hemos dicho lo cargamos y pintamos con la función estándar sin más, el A lo cargamos y pintamos usando una función para cada cosa: VDP_loadTileSet y VDP_setTileMapDataRectEx.
  • Y ya con eso, listo. Tenemos el plano A para aplicar una máscara shadow a los tiles del plano B (y a los sprites en baja de haberlos).

-------------------------

Y este otro realmente es una tontada probando cómo gestionar grupos de sprites haciendo uso de arrays de punteros a funciones para invocar las respectivas rutinas de movimiento (no vayáis a tomar el código como dogma porque de algunas partes distan muy mucho de estar optimizadas).

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

DEMO "PROPSPRITES" METEOROLOG? - PART?ULAS AMBIENTE

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


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


//---------------------------------------------------------
// ASSETS
//---------------------------------------------------------
#include "sprite.h"


//---------------------------------------------------------
// CONSTANTES (DEFINES)
//---------------------------------------------------------
#define MAX_PARTICULAS   64
#define MAX_TIPOS_PARTICULAS 4

#define ANCHO_PANTALLA   320
#define ALTO_PANTALLA   224

#define ANCHO_PLANO      512
#define ALTO_PLANO      256

#define PARTICULA_TIPO_LLUVIA   0
#define PARTICULA_TIPO_ASCUA   1
#define PARTICULA_TIPO_NIEVE   2
#define PARTICULA_TIPO_HOJA      3

#define PARTICULA_TIPO_DEFAULT  PARTICULA_TIPO_LLUVIA

#define TIEMPO_CAMBIO_EFECTO   80


//---------------------------------------------------------
// FUNCIONES
//---------------------------------------------------------
void creaParticulas(void);
void inicializaParticulas(u8);
void mueveParticulas(u8);

void mueveParticulasLluvia(u8);
void mueveParticulasAscua(u8);
void mueveParticulasNieve(u8);
void mueveParticulasHoja(u8);


//---------------------------------------------------------
// STRUCTS
//---------------------------------------------------------
struct t_particula
{
   Sprite* sprite;

   s16 posx, posy;
   s16 movx, movy;

};

//---------------------------------------------------------
// DATA
//---------------------------------------------------------
struct t_particula particulas[MAX_PARTICULAS];

// Array de punteros a funciones
void (*funcionesMueveParticulas[MAX_TIPOS_PARTICULAS])(u8) =
{
   mueveParticulasLluvia,
   mueveParticulasAscua,
   mueveParticulasNieve,
   mueveParticulasHoja
};

// Buffer para textos en pantalla
char texto[8];

//---------------------------------------------------------
// MACROS
//---------------------------------------------------------
#define ESCRIBECIFRA(str, x, y); \
       intToStr((str), texto, 1); \
        BMP_clearText((x), (y), 7); \
        BMP_drawText(texto, (x), (y));


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

    // DATOS LOCALES ______________________________________

    u8 tipo_particulas = PARTICULA_TIPO_LLUVIA;
    u16 temporizador = 0;


    // PROCESO (Inicialización y cargas) __________________

    // init sprites engine
    SPR_init(MAX_PARTICULAS, 256, 256);

    // Cargamos la paleta
    VDP_setPalette(PAL0, particles_sprite.palette->data);

    // Creamos las partícuas
    creaParticulas();


    // BUCLE PRINCIPAL ____________________________________

    while(1)
    {
       // Debug temporizador
        ESCRIBECIFRA(temporizador, 1, 2);

       mueveParticulas(tipo_particulas);

        // Cuando el temporizador llegue al tiempo establecido
        // se iniclializa un nuevo tipo de partícula
        if(temporizador == TIEMPO_CAMBIO_EFECTO)
        {
            tipo_particulas++;

           if(tipo_particulas == MAX_TIPOS_PARTICULAS)
              tipo_particulas = PARTICULA_TIPO_LLUVIA;

           temporizador = 0;

           inicializaParticulas(tipo_particulas);
        }

        temporizador++;

       SPR_update();

        VDP_waitVSync();

    }

    return 0;
}


///////////////////////////////////////////////////////////
// FUNCIONES
///////////////////////////////////////////////////////////


//---------------------------------------------------------
// CREA PARTICULAS
//---------------------------------------------------------
void creaParticulas()
{
    u8 i;

   for(i = 0; i< MAX_PARTICULAS; i++)
    {
       // Creamos los sprites
       particulas[i].sprite = SPR_addSprite(&particles_sprite, -32, -32, TILE_ATTR(PAL0, TRUE, FALSE, FALSE));

       // Generamos posiciones aleatorias sobre el plano
       particulas[i].posx = random()%ANCHO_PLANO;
       particulas[i].posy = random()%ALTO_PLANO;
    }

    // Inicializamos con el tipo predeterminado
    inicializaParticulas(PARTICULA_TIPO_DEFAULT);
}


//---------------------------------------------------------
// INICIALIZA PARTICULAS
//---------------------------------------------------------
void inicializaParticulas(u8 tipo)
{
   u8 i;
   s16 movx = 0, movy = 0;

   // Variaciones del tipo de desplazamiento dependiendo
   // del tipo de partícula que se vaya a mostrar
    for(i = 0; i< MAX_PARTICULAS; i++)
    {

      switch(tipo)
      {
         case PARTICULA_TIPO_LLUVIA:
            movx = 1 + random()%3;
            movy = 1 + random()%4;
         break;

         case PARTICULA_TIPO_ASCUA:
            movx = -1 - random()%3;
            movy = -2 - random()%3;
         break;

         case PARTICULA_TIPO_NIEVE:
            movx = -2 - random()%5;
            movy =  2 - random()%2;
         break;

         case PARTICULA_TIPO_HOJA:
            movx = -1 + random()%3;
            movy = 1 + random()%3;
         break;
      }

       particulas[i].movx = movx;
      particulas[i].movy = movy;

        SPR_setAnim(particulas[i].sprite, tipo);
    }

   // Debug TIPO particula
   ESCRIBECIFRA(tipo, 1, 1);

}


//---------------------------------------------------------
// MUEVE PARTICULAS
//---------------------------------------------------------
void mueveParticulas(u8 tipo)
{
    u8 i;

   for(i = 0; i<MAX_PARTICULAS; i++)
    {

       funcionesMueveParticulas[tipo](i);

       SPR_setPosition(particulas[i].sprite, particulas[i].posx, particulas[i].posy);
    }

}


//---------------------------------------------------------
// MUEVE PARTICULAS LLUVIA
//---------------------------------------------------------
void mueveParticulasLluvia(u8 id)
{
    particulas[id].posx += particulas[id].movx;
    particulas[id].posy += particulas[id].movy;
}

//---------------------------------------------------------
// MUEVE PARTICULAS ASCUA
//---------------------------------------------------------
void mueveParticulasAscua(u8 id)
{
    particulas[id].posx += particulas[id].movx + random()%2;
    particulas[id].posy += particulas[id].movy + random()%3;
}

//---------------------------------------------------------
// MUEVE PARTICULAS NIEVE
//---------------------------------------------------------
void mueveParticulasNieve(u8 id)
{
    particulas[id].posx += particulas[id].movx + random()%3 * (random()%2 * -1);
    particulas[id].posy += particulas[id].movy;
}

//---------------------------------------------------------
// MUEVE PARTICULAS HOJA
//---------------------------------------------------------
void mueveParticulasHoja(u8 id)
{
   particulas[id].posx += particulas[id].movx + random()%2;
    particulas[id].posy += particulas[id].movy + random()%2;
}


Test Sprites SGDK - Proyecto Code Blocks
Madre mía, con eso tengo faena para el resto del mes. Me pondré a ello en cuanto toque un poco más el tema de sprites.

Gracias por el código.
-------------


Aventuras en megadrive.
Voy a portar un juego que tengo hecho para móvil a la negrita.

La documentación que hay por ahí sobre el SGDK a veces no es correcta, ya que el propio sgdk ha ido cambiando. Así que he decidido ir documentando todo lo que hago y hacer un híbrido blog de notas-blog.

Cómo yo mismo estoy aprendiendo, lo voy corrigiendo poco a poco y voy añadiendo cosas. Por favor, si hay errores o tenéis sugerencias, decirlo.


Está en www.danielbustos.com
Redirigido a wordpress, me vale con algo sencillo.
He encontrado ya algo de tiempo, aunque más bien lo he forzado, y he empezado ya con los tutos. Estoy siguiendo mitad los que hay aquí y mitad los que hay en la documentación del sgdk (que son estos mismos pero más breves y actualizados a la versión actual).

He hecho el setup del entorno, eclipse en mi caso (son muchos años ya), esa parte bien.

El tuto de controles tambien bien, pero después me he puesto a improvisar un poco y ya la he liado. No he llegado muy lejos. Quede claro que llevaba 15 años sin picar una linea en C, tendré que refrescarlo a la vez que sigo con los tutos.

No sé si soy yo o es el sgdk, pero algo está funcionando mal (obviamente soy yo).

Alguien puede echarle un vistazo y ver si hay algo muy evidente?
Puede ser que el sgdk no se lleva bien con strcat?

https://github.com/diegomtassis/sgdk-te ... handling.c

Picar sin unit tests me mata.
@matasiete

Puedes probarlo sin usar strcat? por si las moscas....

De todas formas, en la realidad, no se suele usar el inputhandler, sino que consultas el estado de los pads una vez por frame, suele ser más fiable.
Perdona @matasiete Cuando pones "algo está funcionando mal", ¿a qué te refieres?. Lo digo por saber el comportamiento que esperabas ^_^U

@danibus Está haciendo unos minitutoriales / bitácora muy apañaetes, te recomiendo echar un ojo a su web para ésta y otras cosillas :
https://danibus.wordpress.com/2019/03/12/05-aventuras-en-megadrive-controles/

Ánimo, que yo también llevaba años sin tocar C [oki]
@kusfo79 que sea con el input handler es lo de menos, el problema lo tengo operando con cadenas e imprimiendo en pantalla.

Si no uso strcat, ¿cómo se opera con cadenas?

#include <genesis.h>

void logButtonStatus(const char *str, const char *isPushed, u16 x, u16 y);

void inputHandler(u16 joy, u16 changed, u16 state) {

   logInputButton(joy, BUTTON_START, changed, state, "S", 5, 12);

   logInputButton(joy, BUTTON_A, changed, state, "A", 5, 14);
   logInputButton(joy, BUTTON_B, changed, state, "B", 5, 15);
   logInputButton(joy, BUTTON_C, changed, state, "C", 5, 16);

   logInputButton(joy, BUTTON_X, changed, state, "X", 5, 18);
   logInputButton(joy, BUTTON_Y, changed, state, "Y", 5, 19);
   logInputButton(joy, BUTTON_Z, changed, state, "Z", 5, 20);

   logInputButton(joy, BUTTON_UP, changed, state, "U", 5, 22);
   logInputButton(joy, BUTTON_DOWN, changed, state, "D", 5, 23);
   logInputButton(joy, BUTTON_LEFT, changed, state, "L", 5, 24);
   logInputButton(joy, BUTTON_RIGHT, changed, state, "R", 5, 25);
}

void logInputButton(u16 joy, u16 button, u16 changed, u16 state, const char *str, u16 x, u16 y) {

   if (joy == JOY_1) {

      if (state & button) {
         logButtonStatus(str, "1", x, y);

      } else if (changed & button) {
         logButtonStatus(str, "0", x, y);
      }
   }
}

void logButtonStatus(const char *str, const char *isPushed, u16 x, u16 y) {

   char buf[strlen(str) + 3];
   strcat(strcat(buf, str), isPushed);
   VDP_drawText(buf, x, y);
}


Resultado:

Imagen

Obviamente no es lo que esperaba.
El caos es aún mayor si en vez de usar una letra para identificar cada botón uso una cadena tipo "Button A".
Cambiando strlen(str) + 3 por otros valores, por ejemplo 10, lo hace todo aún peor.
Está claro que es algo relacionado con reservar memoria.

Creo que es buen momento para empezar a usar el debugger del Gens Kmod.

@Nekete tengo controlado lo de que todo programa hace bien lo que tiene que hacer, sólo que eso no siempre coincide con lo que el programador quiere que haga ;)

Seguir tutos está bien pero como de verdad se aprende es probando cosas nuevas y analizando resultados.

Hoy tengo el día libre, hay que avanzar con esto :)
@matasiete

a ver, yo no uso SGDK directamente, pero todo lo que sea librerias de cadenas de C no suelen funcionar con los SDK's de consola viejunos, así que....
@kusfo79 sí, me estoy dando cuenta, esto es C pero sin librerías. Tampoco free() ni malloc(). Toca echarle un vistazo mejor a la API del sgdk, y estudiar todos los ejemplos que pille.

Va a ser divertido :)
Bueno ya me voy aclarando algo más. He hecho todos los tutoriales "oficiales", aunque tampoco es que sea mucho, y he dado un repaso a los samples que vienen con el SGDK, ahí ya hay más miga. Teniendo en cuenta que el objetivo de los samples es didáctico la verdad que podían haberse hecho más legibles, pero bueno, cada uno tiene su estilo.

Ahora estoy con el siguiente reto, portar a Megadrive el Jetpac de Spectrum. No es que sea nada del otro mundo, ni siquiera tiene scroll, pero sirve para ir conociendo el API. La verdad que es muy entretenido.

Avance de momento poco pero tengo estos días algo de tiempo libre así que espero avanzar.
https://github.com/diegomtassis/md-jetpac

La rom:
https://github.com/diegomtassis/md-jetp ... ut/rom.bin
@matasiete
Ánimo con el Jetpac, menudos recuerdos jajaja

Yo estoy peleándome ahora con S/H. Está curioso, pero complicado.
@matasiete
Buena idea la de portar un juego sencillito de Spectrum como el Jetpac.
Que se te de bien :)
Como primer juego con la mega está genial. Y ya tienes cosillas funcionando.

Que se de muy bien :)
Sigo echándole horas y cada vez más enganchado. Una cosa es pintar el suelo, las 3 plataformas y el jetman moviéndose por la pantalla, cosa que se hace fácil copiando y adaptando el sample de sprites que viene con el sgdk, y otra hacer que interactúe con lo que tienes en pantalla. En los dos últimos días le he metido bastantes horas y todas dedicadas al engine. Menudo tema lo de las colisiones, pero me queda muy poco ya para conseguir que no atraviese las plataformas, y por el camino voy refrescando C y descubriendo muchas cosas nuevas del sgdk. Fundamental entender todos los samples que vienen con él.

En el jetpac original las plataformas son siempre las mismas y están en el mismo sitio, pero yo estoy haciendo el engine con creación dinámica de niveles y así poder hacer como Sega con los ports de Super Hang On o Mercs, meter un modo que clave el original y otro con algunas cosas nuevas. Por ejemplo en el nuevo modo estoy pensando en meter niveles en los que haya muchas plataformas pequeñas, otro en el que no haya suelo y al caer el jetman pierda una vida, otro con plataformas generadas aleatoriamente, etc. Veremos hasta dónde llego.
@matasiete
Grande. Pon por aquí un ejemplo sencillo de colision cuando lo tengas dominado, yo aún no me he puesto con eso.
Pues ya tengo listo el motor de colisiones. Hacer que el jetman se posase en las plataformas no ha sido excesivamente difícil, pero que funcionase a la vez la detección de colisiones verticales y horizontales me ha dado más trabajo. @danibus ejemplo sencillo... no sé qué decirte, seguramente es porque soy neófito en este tema pero la verdad que tiene su complejidad. Lo he hecho todo en plan voraz osea que con el paso de los días se me va a ocurrir sí o sí cómo simplificarlo. Sé que hay teoría sobre colisiones, tengo que echarle también un vistazo y seguro que veo cómo mejorar mi motor, pero como ejercicio para ir cogiendo soltura me ha servido.

Es un poco cómico, pero cuando al final he conseguido que funcionase me he sentido como Tom Hanks en Naúfrago cuando hace fuego por primera vez.

El sgdk viene con un struct Box, el problema es que las coordenadas son de tipo s16 y en mi Jetpac uso coordenadas de tipo fix16, igual que en el sample del sprite de Sonic, para poder tener velocidad y aceleración con decimales (aunque el jetpac original no tiene aceleración, ya veremos si se la meto en el modo nuevo), osea que si uso esa Box tengo que estar continuamente haciendo conversiones de s16 a fix16 y viceversa, así que me hice una Box_f16 con coordenadas fix16.

El tema de colisiones lo tengo distribuido entre estos 3 ficheros, por si quieres echarles un vistazo.
https://github.com/diegomtassis/md-jetp ... /physics.h
https://github.com/diegomtassis/md-jetp ... /physics.c
https://github.com/diegomtassis/md-jetp ... c/jetman.c
Gracias, lo miraré.

Yo con los distintos tipos estoy volviéndome loco, porque hace mucho que no programo y no me aclaro.

Cuando intento debugear con kdebugalert () se supone que tengo que usar un tipo determinado (creo que era fix16, hablo de memoria), y muchas veces me salen valores... Raros.

O cuando hago un simple if(posiciony > 100) y luego le asigno esa posición a un sprite y me aparece volando en vez de estar en la posicion que espero.

Con lo sencillo que era programar en Gamemaker, con tipado automático.... Ains, quien me mandará meterme en estos berenjenales
@danibus cierto, que el compilador no avise cuando mezclas en una misma operación diferentes tipos es una *****, pero es lo que tiene programar en C. Yo vengo de 15 años programando única y exclusivamente para la JVM y no te digo lo que es volver a C. Pero bueno, también lo estoy difrutando. Preocuparse de reservar y liberar memoria es lo más :Ð .

Sé lo que dices de los sprites locos, y no deja de ser una ventaja, cuando pasa sabes al 99% que estás mezclando tipos por algún lado. A mi me ha pasado estos días infinidad de veces, el jetman se acerca a una plataforma y de repente aparece en el otro lado de la pantalla [qmparto]
@danibus excelentes esas entradas en tu blog explicando el modo shadow & highlight, las he leído mientras echaba un par de horas muertas en el aeropuerto y ya se me ha ocurrido alguna idea para ponerlo en uso.

¿Creéis que los menús de los everdrive están hechos con s&h? Todos los textos en el mismo color apagado excepto la opción seleccionada que aparece en color más claro.

Sé que es fácil de saber con un emulador a mano pero la duda se me ha venido ahora y esta semana estoy fuera de casa.
Yo lo habría hecho asignando otra paleta con el color apagado (dado que es sólo un menú con fondo negro) por no complicarme. Pero me suena que el Megagames Almanac sí lo usaba para hacer transparencias en los textos.
Edit: no he mirado mucho hl/s pero sería buena idea
  • Nueva versión de SGDK (1.40)
  • Stephane ha creado su Patreon
Todo aquel que disfrute del homebrew en la Mega debería pensarse seriamente financiar a Stephane, aunque sea de forma testimonial. Cada mejora en el SGDK significa más y mejores juegos para la MD.

Acabo de añadir un post de HS en mi blog, espero lo degustéis con salud.

PD: Algunos de los ejemplos de HS de post anteriores no son correctos, me he fiado demasiado de gensKmod, lo tengo pendiente de corregir.

Por otro lado, a ver cuando saco tiempo para subir código listo para compilar para poder consultarlo junto con el blog.
343 respuestas
13, 4, 5, 6, 7