Allegro - Knihovna pro programování her III. - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:

Soutěž

Sponzorem soutěže je:

IDIF

 

Kde se koná výstava fotografií Luďka Vojtěchovského?

V dnešní soutěži hrajeme o:



C/C++

Allegro - Knihovna pro programování her III.

19. prosince 2001, 00.00 | V dnešním díle se nejdříve seznámíme s novými datovýmí typy. Poté si povíme něco o načítání a ukládání obrázků včetně blittingu na obrazovku. Jako vždy vše vyzkoušíme na praktickém příkladu..

V dnešním díle, jak jsem minule slíbil, si povíme o načítání a ukládání obrázků a zkusíme si nějaký příklad.

Než začneme…


Nejdříve si povíme o novém datovém typu a to o struktuře BITMAP, se kterou budeme provádět téměř všechny operace co se týče výstupu na obrazovku. I naše dobře známá proměnná screen je samozřejmě typu BITMAP.

Struktura BITMAP je definována v hlavičkovém souboru allegro.h a vypadá následovně:
typedef struct BITMAP          /* a bitmap structure */
{                              
   int w, h;                   /* width and height in pixels */
   int clip;                   /* flag if clipping is turned on */
   int cl, cr, ct, cb;         /* clip left, right, top and bottom values */
   GFX_VTABLE *vtable;         /* drawing functions */
   void (*write_bank)(void);   /* write bank selector, see bank.s */
   void (*read_bank)(void);    /* read bank selector, see bank.s */
   void *dat;                  /* the memory we allocated for the bitmap */
   int bitmap_id;              /* for identifying sub-bitmaps */
   void *extra;                /* points to a structure with more info */
   int x_ofs;         	    /* horizontal offset (for sub-bitmaps) */
   int y_ofs;                  /* vertical offset (for sub-bitmaps) */
   int seg;                    /* bitmap segment */
   unsigned char *line[0];     /* pointers to the start of each line */
} BITMAP;

Nás prozatím budou zajímat jen parametry w a h, což je šířka a výška BITMAPy.

Dále si ukážeme jak vypadá typ PALLETE, který je definován opět v hlav. souboru allegro.h:
typedef struct RGB
{
   unsigned char r, g, b;
   unsigned char filler;
} RGB;

#define PAL_SIZE     256

typedef RGB PALLETE[PAL_SIZE];

Je to vlastně pole 256 struktur typu RGB, ale to jsem zde uvedl jen z toho důvodu kdyby někdo pracoval v módu 8bpp kde je paleta nutností, aby věděl co je paleta zač. My už budeme většinou používat paletu jako parametr funkcí pro práci s grafikou a budeme pracovat v módu 16bpp, který se o paletu nezajímá.

Načítání obrázků


Na to máme k dispozici spoustu funkcí, které pracují s obrázky různých typů. My ale použijeme univerzální funkci na načítaní obrázků ( Jen si vzpomeňte na makro makecol, které mělo odvozeniny jako makecol8, makecol15 atd., ale my jsme používali pouze toto univerzální, které platilo pro všechny bpp. ) a to funkci jejíž prototyp je:

BITMAP *load_bitmap(const char *filename, RGB *pal);

Vrací pointer na typ BITMAP ( ,což asi každému došlo ) a jako první parametr bere jméno souboru a podle přípony rozeznává formáty. Podporuje BMP, PCX, TGA (v dalších verzích Allegra je i formát LBM). Druhý parametr je typu PALETTE nebo pole RGB chcete-li, ale ten funkci pouze dáme a dál se o něj nemusíme starat, pokud pracujeme v 16bpp a více, ale pokud máme 8bpp tak bychom měli po načtení obrázku zavolat funkci:

set_palette(pal);

a to právě s parametrem pal.

Např.:
bmp = load_bitmap("c:\\windows\\mraky.bmp", pal);

kde bmp je pointer na typ BITMAP a pal je typu PALETTE nebo PALLETE ( tyto dva typy jsou identické).

Blitting na obrazovku


Než všechno skloubíme dohromady tak si ještě povíme o poslední funkci pro náš příklad. A tím je funkce:

void blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);

První parametr je zdrojová BITMAPa, druhý je cílová ( v našem případě to bude screen ). Další dva source_x a source_y a poslední dva width a height určují jak velký obdélník se má zkopírovat z BITMAPy source do dest. Zbylé parametry dest_x a dest_y určují souřadnice na BITMAPě dest kam se má vlepit přenášený kus dat. Viz obrázek.

Ukládání obrázků


K ukládání obrázků slouží podobná funkce jako k načítání a to:

int save_bitmap(const char *filename, BITMAP *bmp, const RGB *pal);

Opět uloží bmp s paletou pal do souboru filename, který bere jako přípony BMP, PCX a TGA.

Paletu získáme pomocí příkazu:

get_palette(pal);

Nelze ale použít přímo jako parametr na místo BITMAPy screen a proto si musíme vytvořit tzv. sub-bitmapu.

K tomu slouží funkce:

BITMAP *create_sub_bitmap(BITMAP *parent, int x, y, width, height);

Jak to funguje? Máme např. naší obrazovku a to proměnnou screen o rozměrech 640*480 bodů a vytvoříme si třeba tzv. sub-bitmapu bmp o rozměrech 1024*768 bodů. To znamená, že obě dvě bitmapy budou sdílet 640*480 bodů. Tedy pokud něco nakreslíme do bmp objeví se to i na obrazovce a tedy se to objeví v proměnné screen.

Uvolnění paměti


Pokud přestaneme pracovat s nějakou proměnnou, pro kterou jste alokovali paměť pomocí load_bitmap, create_sub_bitmap atd. tak byste ji měli uvolnit. K uvolnění pointeru na int v C slouží funkce free a v C++ delete, a tak v Allegru je k tomu funkce:

void destroy_bitmap(BITMAP *bitmap);

která si jako parametr bere pointer na BITMAPu, což se asi dalo čekat, že?

Příklad

Vše si ukážeme na příkladu, který načte soubor mraky.bmp, který jsem si vypůjčil z adresáře Windows, zobrazí ho na obrazovku a bude měnit paletu.
#include "allegro.h" // hlav. soubor. allegra

int main(void)
{
  int result, i;
  BITMAP *bmp;
  PALETTE pal;
  RGB pal_swap;
  char* soubor = "c:\\windows\\mraky.bmp";

  if ( (result = allegro_init() ) != 0 )  // inicializuje allegro
  {
    printf("Nejde Allegro! - %s\n\nZmackni cokoliv.",allegro_error);
    getch();
    return 0;
  }
  // nahodi mod 640 * 480 * 8

  set_color_depth(8);
  if ( (result = set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) ) < 0) {
    set_gfx_mode(GFX_TEXT, 80, 25, 0, 0);
    printf("Nejde grafika! - %s\n\nZmackni cokoliv.",allegro_error);
    getch();
    allegro_exit();
    return 0;
  }


  // nacte bitmapu ze souboru
  bmp = load_bitmap(soubor, pal);

  set_palette(pal);
  // tzv. plivne to na obrazovku
  blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h);

  while (!kbhit())
  {

    pal_swap = pal[0];
    for (i = 0; i < 255; i++)
    {
     pal[i] = pal[i + 1];

    }

    pal[255] = pal_swap;

  }

  // ziska paletu a ulozi obsah na obr.
  get_palette(pal);
  bmp = create_sub_bitmap(screen, 0, 0, SCREEN_W, SCREEN_H);
  save_bitmap("mraky.pcx", bmp, pal);

  // uvolni pamet
  destroy_bitmap(bmp);

  allegro_exit();

  return 0;
}

Příště si řekneme více o funkci blit a o tom co to je "Double Buffering", přičemž se naučíme vytvářet vlastní virtuální obrazovky. Nakonec vše zakončíme příkladem jako vždy.

Příklad si můžete stáhnou zde.

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » C/C++  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: