[Grafika] [WebTip] [Fotografování] [Galerie] [MujMac] [Printing]
  Redakce: info (at) builder.cz   Inzerce: reklama (at) grafika.cz
Diskuzní fóra
.Net (68468)
ASP (1591)
ActiveX (168)
Allegro (136)
Assembler (3926)
C++ Builder (23160)
C/C++ (44499)
Databáze (30680)
Delphi (78806)
DelphiX (1655)
DirectX (1464)
Java (39508)
JavaScript (12598)
Matematické programy (2178)
OOP a UML (732)
OpenGL (6920)
Php (65224)
PowerBuilder (464)
Problémy a algoritmy (10473)
Programování v Linuxu (2000)
Právo a programování (3384)
Python (1353)
Ruby (136)
Visual Basic (12078)
Visual C++ (12956)
Wap (56)
Web (10895)
Web servery (5549)
Win32 (13553)
Windows CE (865)
XML/XSL (1860)
Textová inzerce
Služby Builder.cz
  • Bazar - koupím(0)
  • Bazar - prodám(0)
  • Hledám práci(0)
  • Nabízíme práci(0)
  • Projekty(0)
  • Allegro - Vektory a synchronizace scény (11. díl)
    Dnešní díl nás seznámí s vektory jak z matematiky tak z knihovny STL v C++. Povíme si o synchonizaci scény na jakém koliv počítači a vše si ukážeme na pěkném demu.
    Allegro - Knihovna pro programování her
    Předchozí díl: Allegro - Časovač (10. díl)

    Následující díl: Allegro - Datové soubory a práce s nimi (12. díl)
    Autor: Matoušek Pavel
    Rubrika: C/C++
    Publikováno: 21.03. 2002
     Tisk článku
    Poslat odkaz emailem
     

    Pro dnešní díl je potřeba se trochu seznámit s vektory. Opravdu to nebude nic těžkého a každý by to měl pochopit pokud ještě neví co to vektory jsou. Nebudu přímo vysvětlovat matematické vektory, abych Vás zbytečně nezatěžoval, ale seznámím Vás s principem - jak udělat, aby se mi obrázek na obrazovce posouval o stejný kus a nezáleželo na tom jak rychlý mám počítač?

    Nejlepší je vše si vysvětlit opět na příkladu. Vytvořil jsem jednoduché demo, které vidíte na obrázku.

    Pohybují se na obrazovce čtverečky a odrážejí se od stěn. Program taky ukazuje počet čtverečků na obrazovce a FPS.

    Ovládání

    SPACE - přidá jeden čtvereček
    ENTER - odebere jeden čtvereček
    INSERT - přidá sto čtverečků
    DELETE - smaže všechny čtevečky
    ESC - konec 

    Doporučuji si nejdříve stáhnout ukázkový příklad zde, pustit si ho a malinko mrknout na zdroják, bude se vám pak dnešní článek lépe chápat. Nezapomeňte si správně nastavit v programu cestu k obrázku. To by se Vám objevila jenom černá obrazovka.

    Jak je to řešeno programově?

    Na souřadnice jednotlivých čtverečků používám objekty ( class z C++, už o tom byla zmínka, že to jednou přijde :) ) a na dynamické pole objektů jsem si vypůjčil vector z knihovny STL. Ale nemějte strach, nepoužívám v programu žádné "vychytávky" a snažil jsem se ho napsat co možná nejjednodušeji. Nemusíte mít strach vše je vysvětleno.

    V programu používám dva časovače popsané v minulém díle. První na výpočet FPS a druhý na ty vektory.

    Vektory (pouze 2D)

    Abych nemluvil do větru tak nejdřív si povíme něco málo o našem objektu, který jsem nazval CObject.

    //definujeme si objekt jako tridu
    class CObject {
    private:<
    
    public:
    	//zduvodu pristupu a ne pres clenskou fci jako GetX(); 
    	//proto jsou verejne
    	float x,y;//pozice objektu
    	float cx,cy;//pro vektor ve 2D
    
    		CObject() {};//kostruktor
    
    	~CObject() {};//destruktor
    
    	void Init()
    	{
    		x=rand()%640;
    		y=rand()%480;
    		cx=rand()%200+1;
    		cy=rand()%200+1;
    	}
    
    	//posouva prvky a zalezi kolik ubehlo casu 
    	void Move(float cas)
    	{
    		//vypocita o jak velky kus posunout souradnice
    		//je to pres vektory cx a cy = posunuti za 1s
    		x+=cx*(cas/1000);
    		y+=cy*(cas/1000);
    
    		//kotroluje x-ovou
    		if (x<0)
    		{
    			x=0;
    			cx=-cx;
    		}
    		if (x>620)
    		{
    			x=620;
    			cx=-cx;
    		}
    		//kontroluje y-ovou
    		if (y<0)
    		{
    			y=0;
    			cy=-cy;
    		}
    		if (y>460)
    		{
    			y=460;
    			cy=-cy;
    		}
    	}
    };
    

    Private proměnné nejsou z důvodu, abych nemusel psát funkce na vrácení x, y, cx a cy a proto je vše public. Proměnné x, y jsou pozice obrázku nebo čtverečku na obrazovce. cx a cy je vektor. Např. cx=cy=50 to znamená, že se obrázek za jednu vteřinu posune o 50 pixelů doleva a dolů

    Konstruktor a destruktor jsou bez funkce. Funkce (nebo lépe metoda) Init se nám postará o inicializaci náhodných souřadnic a náhodného směru a rychlosti objektu. Je volána vždy při vytvoření nového objektu.

    Než si popíšeme metodu Move tak nejdřív vysvětlím jaká je finta v programu a proč tomu říkám vektory (teď nemyslím vector z STL). Jak jsem před chvílí zmínil tak např. cx znamená velikost posunutí za 1s. Nyní, ale co když demo běží jednou 50 FPS a podruhé 150 FPS co pak?
    Jako první si zjistíme kolik uběhlo času od posledního vykreslení scény na obrazovku. K tomu nám slouží druhý časovač.

    Rovnice na vypočítání posunuti.

    cx=50 a představme si, že hra běží pouze 2 FPS. Tedy uběhlo od posledního vykreslení 500 ms = 1/2 s. V proměnné cas tedy máme hodnotu 500, protože jsme časovač pustili na volání po každé milisekundě. Podělíme tedy cas/1000 a dostaneme jakoby část vektoru, o který se máme posunout. Tedy o 0,5cx. A když hra beží 2 FPS tak nám vyjde, že cx=2*(0,5cx) a to je pravda. 

    Pro obě souřadnice vypadá výpočet takto:

    posunutí x =cx*(cas/1000);
    posunutí y =cy*(cas/1000);

    To pak přičteme k x a k y. S tím, že cx nebo cy může být i záporné číslo. A pomocí tohoto přepočtu nám nezáleží na velikosti FPS v programu a čtverečky se budou posouvat o stejný kus.

    Metoda Move dostane jako parametr čas, který uběhl od posledního volání této funkce a vypočítá posunutí. Pak zkontroluje jestli čtvereček není mimo scénu a pokud je obrátí vektor. Např. x vyjde -5 tak nastavíme x na 0 a vektor, který mohl být cx=-35 převrátíme na cx=-cx tedy cx=35 a tím dosáhneme efektu odražení.

    To by bylo k vektorům nebo posunům nebo synchronizaci scény vše. Toto se používá už dlouho a samozřejmě dodnes ve hrách jenom je to o trochu složitější a to ještě díky tomu, že se objevujeme ve 3D prostoru. Malinko si popíšeme samotný program.

    Jako dynamické pole používám šablonu vector z STL ( moje oblíbená :-D )

    vector<CObject> v;//nas vektor pro dynamicky seznam
    CObject objPrac;//pracovni objekt pro pridavani do vektoru

    v je tedy naše proměnná pro práci s polem a objPrac je pomocná proměnná, kterou přidáváme další objekty do dynamického pole.

    Před samotnou smyčkou programu si vytvoříme alespoň 10 čteverčů, aby obrazovka nebyla po spuštění prázdná.

    	//dame jeden objekt na scenu alespon
    	for(i=0; i<POCET_NA_ZACATKU;i++)
    	{
    		objPrac.Init();
    		v.push_back(objPrac);
    	}
    

    Tedy v našem pracovním objektu objPrac zavoláme metodu Init, která vytvoří náhodný objekt (souřadnice a vektor) a pak už jenom pomocí metody vectoru push_back přidáme nový prvek na konec pole.

    V samotné smyčce programu vykreslujeme v cyklu všechny prvky pomocí této smyčky.

    	for (i=0;i<v.size();i++)
    		{
    			v[i].Move((float)cas);
    			blit(obr,bb,0,0,(int)v[i].x,(int)v[i].y,20,20);
    		}
    

    Nejdříve tedy prvek posuneme a pak vykreslíme.

    Pak program umožňuje několik málo funkcí s objekty jako je přidání a odnětí.

    		//pridej
    		if (key[KEY_SPACE])
    		{
    			objPrac.Init();
    			v.push_back(objPrac);
    			rest(20);
    		}
    		//uber
    		if (key[KEY_ENTER])
    		{
    			v.pop_back();
    			rest(20);
    		}
    		//uber vsechny
    		if (key[KEY_DEL])
    		{
    			v.erase(v.begin(),v.end());
    		}
    		//pridej 100
    		if (key[KEY_INSERT])
    		{
    			for(i=0;i<100;i++)
    			{
    				objPrac.Init();
    				v.push_back(objPrac);
    			}
    			rest(50);
    		}
    

    Tělo podmínky pro SPACE je stejné jako u inicializace. 
    ENTER místo push_back volá pop_back což je odstranění prvku ze seznamu, který je na konci. 
    DELETE vymaže celý seznam metodou erase. Ta má dvě varianty buď maže nejáký prvek nebo nekolik prvků za sebou. My volíme variantu číslo dvě a tedy chceme vymazat celý seznam a proto voláme begin() což je adresa začátku a end() což je konec seznamu ve vectoru. Metody begin a end vracejí interator. Ale myslím, že pokud se o toto téma zajímáte tam na tomto serveru vychází ještě seriál o C++ včetně STL (Standard Template Library), ale na druhou stranu jsem nepoužil nic co by se nedalo z příkladu pochopit. Tím myslím, že pro dnešní příklad jste ani vectory nemuseli znát a vše vám bylo jasné, protože nepoužívám žádné programátorské bombónky a navíc dynamické pole se dájí obejít přes lineární seznam, kde v objektu je pointer na další objekt stejného typu, což se používalo převážně v C, ale někdy i v C++. Ale vectory jsou lepší a ušetří Vám  práci a hlavně nervy
    A jako poslední je INSERT, který přídá 100 prvků do seznamu za sebou v cyklu.

    Nakonec v programu následuje odinicializace a vrácení běhu operačnímu systému.

    Vím, že program o 200 řádcích se dá jen těžce vysvětlit, ale snažil jsem se dávat všude komentáře a tak doufám, že jste všechno pochopili.

    PS: Doufám, že jsem Vás vectorem z STL a třídou class moc nepřekvapil ;-).


    Zpět na začátek stránky

    Pavel Matoušek
    Osobní stránky autora naleznete na www.pmatousek.com

    Hodnocení článku
    1 | 2 | 3 | 4 | 5
    Aktuální známka: 2.49
    (Počet známek: 3070)

    Komentáře k článku
    -- Žádné příspěvky --
    Přidat příspěvek




    info@builder.cz
    Vydává Grafika Publishing, s.r.o.
    Copyright (c) 1997-2002 Všechna práva vyhrazena