18. Mostrar y mover sólo el marciano. Octavo juego (aproximación "b"): Marciano 2 (*)

La idea de esta segunda aproximación es:

  • Movimiento sólo del "marciano", de lado a lado, bajando en la pantalla y cambiando de forma. Se podrá interrumpir pulsando Esc. No deberá salirse por los lados, y si llega a la parte inferior deberá volver a la superior.


Debería resultar bastante fácil. La única novedad por ahora es eso de "cambiar de forma". Según el caso, nuestro "personaje" puede cambiar de apariencia cada vez que lo dibujamos, de forma sucesiva, o mantener una misma forma durante varios fotogramas. En este ejemplo, vamos a coger esta última opción, pero en su variante más sencilla: cada X fotogramas (y siempre los mismos, por ejemplo, cada 3) cambiaremos la apariencia del personaje y volveremos a empezar a contar.

Todo esto, en lenguaje mucho más cercano a los de programación sería:

cargar imagen 1 y 2 del marciano
entrar a modo gráfico 
dibujar marciano en punto inicial

repetir

  aumentar posicion horizontal

  si se acerca a margen lateral de la pantalla
    cambiar sentido horizontal de avance
    bajar una línea en vertical

  si se acerca a parte inferior de la pantalla
    mover a parte superior

  aumentar contador de "fotogramas"
  si contador de fotogramas = numFotogramasPorImagen
    cambiar apariencia de marciano
    contador de fotogramas = 0

  redibujar pantalla
  pausa

hasta que se pulse ESC

Si se ha entendido la aproximación anterior, capaz de mostrar las imágenes, esta añade pocas novedades: calcular la nueva posición del marciano (cambiando de línea y de dirección o volviendo a la parte superior de la pantalla si corresponde) y salir sólo si se pulsa la tecla ESC, no con las demás teclas:

 

/*----------------------------*/
/*  Intro a la programac de   */
/*  juegos, por Nacho Cabanes */
/*                            */
/*    ipj18c.c                */
/*                            */
/*  Decimoquinto ejemplo:     */
/*    Movimiento de un        */
/*    marciano animado        */
/*                            */
/*  Comprobado con:           */
/*  - Djgpp 2.03 (gcc 3.2)    */
/*    y Allegro 4.02 - MsDos  */
/*----------------------------*/
 
/* -------------------
 
Planteamiento de esta aproximación:
 
cargar imagen 1 y 2 del marciano
entrar a modo gráfico
dibujar marciano en punto inicial
 
repetir
  aumentar posicion horizontal
  si se acerca a margen lateral de la pantalla
    cambiar sentido horizontal de avance
    bajar una línea en vertical
  si se acerca a parte inferior de la pantalla
    mover a parte superior
  aumentar contador de "fotogramas"
  si contador de fotogramas = numFotogramasPorImagen
    cambiar apariencia de marciano
    contador de fotogramas = 0
  redibujar pantalla
  pausa
hasta que se pulse ESC
 
 
------------------- */
 
 
 
#include <allegro.h>
 
 
/* -------------- Constantes globales ------------- */
#define ANCHOPANTALLA 320
#define ALTOPANTALLA 200
#define RETARDO 250
 
#define MARGENSUP   40
#define MARGENDCHO  30
#define MARGENIZQDO 30
#define MARGENINF   50
#define INCREMX      5
#define INCREMY     15
 
 
/* -------------- Variables globales -------------- */
PALETTE pal;
BITMAP *imagen;
BITMAP *nave;
BITMAP *marciano1;
BITMAP *marciano2;
 
 
/* -------------- Rutina de inicialización -------- */
int inicializa()
{
    allegro_init();        // Inicializamos Allegro
    install_keyboard();
    install_timer();
 
                           // Intentamos entrar a modo grafico
    if (set_gfx_mode(GFX_SAFE, ANCHOPANTALLA, ALTOPANTALLA, 0, 0) != 0) {
        set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
        allegro_message(
            "Incapaz de entrar a modo grafico\n%s\n",
            allegro_error);
        return 1;
    }
 
                           // e intentamos abrir imágenes
    imagen = load_pcx("spr_inv.pcx", pal);
    if (!imagen) {
        set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
        allegro_message("No se ha podido abrir la imagen\n");
        return 1;
    }
    set_palette(pal);
 
    // Ahora reservo espacio para los otros sprites
    nave = create_bitmap(16, 16);
    marciano1 = create_bitmap(16, 16);
    marciano2 = create_bitmap(16, 16);
 
    // Y los extraigo de la imagen "grande"
    blit(imagen, nave    // bitmaps de origen y destino
      , 32, 32           // coordenadas de origen
      , 0, 0             // posición de destino
      , 16, 16);         // anchura y altura
 
    blit(imagen, marciano1, 0, 32, 0, 0, 16, 16);
    blit(imagen, marciano2, 16, 32, 0, 0, 16, 16);
 
 
    // Y termino indicando que no ha habido errores
    return 0;
}
 
 
 
/* ------------------------------------------------ */
/*                                                  */
/* -------------- Cuerpo del programa ------------- */
 
int main()
{
    int fotograma = 1;
 
    int xMarciano = MARGENIZQDO;
    int yMarciano = MARGENSUP;
    int desplMarciano = INCREMX;
 
    int salir = 0;
 
    // Intento inicializar
    if (inicializa() != 0)
        exit(1);
 
 
 
    do {  // Parte que se repite hasta pulsar tecla
 
        clear_bitmap(screen);
 
        // Dibujo un marciano u otro, alternando
        if (fotograma==1) {
           draw_sprite(screen, marciano1, xMarciano, yMarciano);
           fotograma = 2;
        } else {
           draw_sprite(screen, marciano2, xMarciano, yMarciano);
           fotograma = 1;
        }
        // Y espero un poco
        rest(RETARDO);
 
        // Finalmente, calculo nueva posición
        xMarciano += desplMarciano;
        // Compruebo si debe bajar
        if ((xMarciano > ANCHOPANTALLA-16-MARGENDCHO)
            || (xMarciano < MARGENIZQDO))
        {
            desplMarciano = -desplMarciano; // Dirección contraria
            yMarciano += INCREMY;           // Y bajo una línea
        }
        // O si debe volver arriba
        if (yMarciano > ALTOPANTALLA-16-MARGENINF) {
            xMarciano = MARGENIZQDO;
            yMarciano = MARGENSUP;
            desplMarciano = INCREMX;
        }
        if (keypressed())
            if (readkey() >> 8 == KEY_ESC)
                salir = 1;
 
    } while (!salir);
 
    destroy_bitmap(imagen);
    readkey();
    return 0;
 
}
 
            /* Termino con la "macro" que me pide Allegro */
END_OF_MAIN();

 

Si está todo entendido, vamos ahora a mover dos cosas a velocidad distinta (el "marciano" y nuestra nave)...