Allegro - Knihovna pro programování her IV. - 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:



C/C++

Allegro - Knihovna pro programování her IV.

11. ledna 2002, 00.00 | Další z řady dílů o Allegru nás seznámí s Double Bufferingem a blíže s funkcí blit. Také se naučíme vytvářet svoje vlastní virtuální obrazovky a samozřejmostí je i příklad na kterém si vše předvedeme.

V minulém díle jsem slíbil, že si povíme o funkci blit a o Double Bufferingu, ale ještě před tím bych Vám rád řekl něco, na co jsem byl upozorněn v komentáři.

Funkce allegro_exit(); může být vynechána a allegro se o uvolnění "postará". A pokud používáte C++ tak by Vám mohla nadělat tato funkce pěknou paseku. Například kdyby jste ji zavolali v destruktoru. Dokonce, i když se podíváte na zdrojové soubory, které jsou ke stažení na internetu tak se i tam čas od času vynechává. Ale hodně se vyskytuje ve starších zdrojových souborech. Já tuto funkci prozatím používat budu, abych nepletl začátečníky.

Funkce blit a kouzla s ní


O samotné funkci blit si povídat nebudeme, ale seznámíme se s jejími odvozeninami a to s funkcemi masked_blit, stretch_blit a kombinací obojího masked_stretch_blit (přičemž tato funkce není ve verzi 3.12, ale objevila se až později ).

Jako první si povíme o masked_blit, ale ještě před tím si řekneme o tom co je to mód transparent nebo transparent color.

Pokud programujete webové stránky a chcete vykreslit na nějaký vzorek např. červené kolečko tak použijete formát .gif a červené kolečko namalujete např. na bílý povrch a bílou barvu nastavíte jako transparentní což je právě transparent color.
Nebo taky existuje to, že například se zapne v programu mód transparent a ten třeba nevykresluje černou barvu. Možností je více, ale většinou jsou podobné těmto.
Dalo by se říci, že je to jedno a totéž.

Ale teď k tomu jak funguje funkce masked_blit, jejíž prototyp vypadá naprosto stejně jako u funkce blit až na název:

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

Tato funkce používá obě dvě výše jmenované metody, ale pro kterou se rozhodne to záleží na barevné hloubce jestli je 8bpp nebo větší.

Pokud používáte 8bpp tak máte paletu o 256 prvcích typu RGB jak jsme si ukázali minule. A právě tady se používá první verze a to transparent color. A barva transparentní bude taková jakou navolíte do palety s indexem 0. To znamená, že pokud chcete mít jako transparentní barvu černou nastavíte si to např. tímto způsobem:

pal[0].r = 0;
pal[0].g = 0;
pal[0].b = 0;

kde pal je typu PALETTE samozřejmě.

Ale když používáte 15, 16, 24 nebo 32 bpp tak je zde použit druhý způsob. Vykreslujete obrázek pomocí funkce masked_blit a tím jakoby zapnete mód transparent, který nevykresluje světlou/jasnou růžovou barvu, kde položky RED a BLUE mají hodnotu 255 a GREEN má hodnotu 0. Barvu dostanete například pomocí makecol(255, 0, 255);. Další zajímavá funkce je stretch_blit:

void stretch_blit(BITMAP *source, BITMAP *dest, int source_x, source_y, source_width, source_height, int dest_x, dest_y, dest_width, dest_height);

Tato funkce má deset parametrů, ale není to tolik jak by se mohlo na první pohled zdát. První dva parametry jsou zdrojová a cílová BITMAPa. Další 4 parametry určují zdrojový obdélník a poslední 4 parametry určují cílový obdélník. To znamená, že pomocí této funkce můžete tzv. ZOOMovat. Například máte obrázek o rozměrech 100 * 100 pixelů v proměnné bmp a potřebuje ho překreslit na obrazovku aby měl 200*200 pixelů volala by se funkce s následujícími parametry:

stretch_blit(bmp, screen, 0, 0, 100, 100, 0, 0, 200, 200);

nebo obecněji:

stretch_blit(bmp, screen, 0, 0, bmp->w, bmp->h, 0, 0, bmp->w * 2, bmp->h * 2);

Jestli potřebujete naprogramovat preview obrázků tak se nemusíte s tím programovat "ručně", ale tato funkce Vám ulehčí spoustu práce.

Další funkce je kombinací těchto dvou zmiňovaných a to funkce:

void masked_stretch_blit(BITMAP *source, BITMAP *dest, int source_x, source_y, source_w, source_h, int dest_x, dest_y, dest_w, dest_h);

Parametry stejné jako u funkce stretch_blit akorát používá mód transparent nebo transparent color.

Virtuální obrazovky


S tím jsme se nepřímo setkali už minule při ukládání obrázků, ale dneska si o tom povíme více.

Jako první bych představil asi nejpoužívanější funkci pro práci s virtuálními obrazovkami a to:

BITMAP *create_bitmap(int width, int height);

Příklad:
BITMAP *backbuffer;

backbuffer = create_bitmap(SCREEN_W, SCREEN_H);


První řádek inicializuje proměnnou backbuffer, což je pointer na typ BITMAP a druhý řádek nám vytvoří virtuální obrazovku o rozměrech obrazovky a o stejné barevné hloubce jako je screen.

Další podobná funkce je:

BITMAP *create_bitmap_ex(int color_depth, int width, int height);

Jediný rozdíl spočívá v tom, že si můžeme sami určit barevnou hloubku. Jinak jsou si tyto dvě funkce naprosto rovnocenné.

A nakonec ještě pár zajímavých funkcí, které nám leccos vypoví o našich BITMAPách:

int bitmap_color_depth(BITMAP *bmp);

Tato fce vrátí barevnou hloubku.

int bitmap_mask_color(BITMAP *bmp);

A tato funkce nám pro změnu vrátí transparentní barvu. Tedy pro mód 8bpp vrací pal[0] (podle toho co jsme si jako transparentni barvu nadefinovali) a pro zbytek bpp nám vrací číslo kde leží transparentní barva. Tedy makecol(255, 0, 255);. Samozřejmě se to liší podle toho jaký používáme mód jestli 15 bpp nebo 32 bpp apod.

Double Buffering


Se používá poměrně často i v dnešních hrách. Proč taky ne, když je jednoduchý a i rychlý. Samozřejmě existují i jiné metody jako je Page Flipping, Triple Buffering atd., ale pro naše příklady je bohatě dostačující, alespoň prozatím. Tyto metody si ale vysvětlíme až někdy příště.

Double Buffering funguje na principu dvou virtuálních obrazovek typu BITMAP v Allegru. Dodávám v Allegru z toho důvodu, že např. v DDraw ver. 7.0 to je typu LPDIRECTDRAWSURFACE7 a říká se tomu obecně surface, což je rozhraní nebo spíše pointer na rozhraní IDirectDrawSurface7, protože celé DirectX je založeno na COM (Component Object Model). Ale o tom až v seriálu o DirectX.

První virtuální obrazovka je vlastně ( už v našem případě ) proměnná screen, tedy to co vidíme na obrazovce. Druhá proměnná může být např. backbuffer opět typu BITMAP.
Znamená to, že všechno vykreslujete do backbufferu ( dále jen BB ) a pak to funkcí blit zkopírujete na obrazovku tedy do proměnné screen nebo si proto můžete vytvořit funkci např.:

void flip_to_screen(void)
{
  blit(backbuffer, screen, 0, 0, 0, 0, backbuffer->w, backbuffer->h);
}


a pak v programu po vykreslení všeho do BB akorát zavoláte tuto funkci ( flip_to_screen(); ) a je to na obrazovce. Obě dvě proměnné budou globální samozřejmě.
A k čemu vlastně slouží? Double Buffering Vám totiž odstraní tzv. blikání.

Příklad
Tradice je tradice a my si vše ukážeme na příkladu, který demonstruje to, co jsme se dnes naučili :). Pro ukázku uvádím jen jeden. Zbytek příkladů je ke stažení na konci.
#include <dos.h>
#include <stdlib.h>
#include <time.h>
#include "allegro.h" // hlav. soubor. allegra

// virt. obr. pro DB - DOUBLE BUFFERING
BITMAP *backbuffer;
char ss[20];

// zapne allegro a grafiku vcetne backbufferu
// kdyz chyba - konec programu
int init(void)
{
  int result;

  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;
  }
  set_palette(desktop_palette);

  backbuffer = create_bitmap(SCREEN_W, SCREEN_H);
}

// zkopiruje backbuffer na obrazovku
void flip_to_screen(void)
{
  blit(backbuffer, screen, 0, 0, 0, 0, backbuffer->w, backbuffer->h);
}

int main(void)
{
  int i;
  PALETTE pal;

  init();

  // kresli kolecko bez DB
  for (i = 0; i < 640; i+=5) {

    clear(screen);
    circlefill(screen, i, SCREEN_H / 2, 50, makecol(255, 0, 0));
    textout(screen,font,"BEZ DOUBLE BUFFERINGU",i,0,makecol(0, 0, 255));

    delay(40);
  }

  clear(screen);

  // kresli kolecko s DB
  for (i = 0; i < 640; i+=5) {
    clear(backbuffer);
    circlefill(backbuffer, i, SCREEN_H / 2, 50, makecol(255, 0, 0));
    textout(backbuffer,font,"S DOUBLE BUFFERINGEM",i,0,makecol(0, 0, 255));

    flip_to_screen();
    delay(40);
  }


  sprintf(ss, "%d", bitmap_mask_color(backbuffer));

  textout(screen, font, ss , 20, 20, makecol(0, 0, 255));


  getch();
  // uvolni pamet
  destroy_bitmap(backbuffer);

  // mozne i vynechat
  allegro_exit();

  return 0;
}


Příště se seznámíme s klávesnicí a myší. Nakonec zakončíme vše příkladem, který bude obsahovat Double Buffering, načítání a ukládání obrázků a to vše budeme ovládat pomocí klávesnice či myši.

Zdrojové soubory (jsou 2) si můžete stáhnou zde.

Nezapomeňte (tedy pokud ji už nemáte) si taky pořídit novou verzi Allegra 4.0. Od příště pracujeme s ní.

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: