Puzzle vytvořená ve Flashi jsou zábavná a nabízejí uživateli příjemné odreagování. Pro tvůrce zase znamenají mnoho výhod – jejich snadná obměna a žádné pracné „stříhání“ obrázků na dílky. Během chvilky tak můžete vytvořit mnoho zajímavých skládanek.

Pro představu toho, čím se budeme zabývat, uvádím nejprve ukázku skládanky. Můžete si ji vyzkoušet zde. Skládanku skládejte z levého horního rohu po řádcích, dílek v pravém dolním rohu totiž chybí.

Celé puzzle vytvoříte s pomocí funkce Mask a programovacího jazyka Actionscript programu FLASH 5. Jednotlivé dílky puzzle nebudete vytvářet „rozstříháním“ celého obrázku na kousky, ale tím, že se na daném dílku „promítne“ pouze část předlohy. K tomu vám poslouží výše zmíněná funkce Mask. Jednotlivé dílky potom budete posunovat pomocí Actionscriptu.

Vytvoření jednotlivých dílků

1. Nejprve vytvoříte nový symbol (Insert | New symbol) a pojmenujete ho např. obrazek. Do něj vložíte obrázek (File | Import), ze kterého budeme tvořit puzzle. Změňte velikost obrázku (Window | Panels | Info) tak, aby odpovídala našim potřebám. Budeme vytvářet puzzle o velikosti 6 x 4 dílky, přičemž velikost dílku bude 50. Potřebná velikost obrázku tedy bude 300 x 200. Obrázek umístěte tak, aby jeho levý horní roh ležel ve středu symbolu (označen křížkem), souřadnice levého horního rohu obrázku tedy budou 0,0. Pro pozdější posun obrázku to bude nutné.

2. Nyní si vytvoříte symbol, který bude sloužit jako „neviditelné“ tlačítko. S jeho pomocí budete manipulovat s jednotlivými dílky puzzle. Vytvořte nové tlačítko (Insert | New symbol | Behavior | Button) a nazvěte ho tlacitko. První tři snímky tlačítka (Up, Over a Down) ponechejte prázdné, pouze do snímku Hit nakreslete vyplněný čtverec o velikosti 50 x 50. Výsledkem bude tlačítko, které není vidět, ale reaguje na stisk.

3. Vytvořte symbol pro jeden kousek skládačky: nový symbol (Insert | New symbol), pojmenujte ho např. dilek. V něm zaveďte tři vrstvy (Insert | Layer) – kod, maska a obrazek:

4. Do nejspodnější vrstvy jménem obrazek vložte z Knihovny (Window | Library) instanci symbolu obrazek a pojmenujte ji také obrazek (Window | Panels | Instance | Name).

5. Do prostřední vrstvy maska nakreslete vyplněný čtverec o velikosti 50 x 50 (Window | Panels | Info). Umístěte ho doprostřed symbolu, souřadnice jeho středu tedy budou 0,0.

6. Z vrstvy maska nyní uděláte masku (Modify | Layer | Mask), z vrstvy obrazek zase maskovanou vrstvu (Modify | Layer | Masked). Po uzamknutí obou zmíněných vrstev (Modify | Layer | Lock) uvidíte pouze část celého obrázku.

7. Do horní vrstvy kod umístěte přetažením z Knihovny neviditelné tlačítko (nazvali jste ho tlacitko), které jste vytvořili již dříve. Tlačítko neobsahuje žádné viditelné prvky, proto bude vidět pouze světlemodrá oblast, ve které reaguje na stisk. Tlačítko umístěte tak, aby překrývalo čtverec nakreslený do vrstvy maska. Tím jste určili oblast, ve které bude dílek reagovat na stisk. Tvorba dílku je prozatím ukončena.

8. Na hlavní plochu animace nyní z Knihovny (Window | Library) umístěte instanci symbolu dilek a pojmenujte ji také dilek (Window | Panels | Instance | Name). Instanci poté posuňte mimo viditelnou plochu. Ona sama totiž nemusí být vidět, budou se z ní ovšem později duplikovat všechny dílky skládanky.

9. Abyste určili počáteční bod pro všechny dílky, vytvořte nový symbol (Insert | New symbol) jménem start. Symbol však ponechejte prázdný, bude sloužit pouze pro určení jeho souřadnic. Instanci tohoto symbolu vložíte z Knihovny (Window | Library) na hlavní plochu animace a pojmenujete ji rovněž start. Poté ji přesuňte do místa, kde budete předpokládat levý horní roh skládanky. Musíte dát ovšem pozor, aby souřadnice středu (Window | Panels | Info) této instance měly celočíselnou hodnotu, tzn. nesmí se jednat o desetinné číslo! Při výpočtech by pak docházelo k chybám a celá skládanka by kvůli tomu nefungovala.

10. Nyní ještě vytvořte zprávu o dokončení skládanky, která se zobrazí v případě jejího dokončení. Nový symbol (Insert | New symbol) nazvěte hotovo. Umístěte do něj (Window | Tools | Text tool) text „Blahopřeji“. Pod tento nápis ještě vložte text „Znovu“ a přes něj položte (resp. vytáhněte z Knihovny) „neviditelné“ tlačítko (symbol tlacitko), které jste vytvořili již dříve. Tlačítko bude sloužit k opětovnému rozházení skládanky po jejím složení. Na plochu nakonec umístěte instanci symbolu hotovo s názvem complete.

11. Aby měl uživatel představu, jak má skládaný obrázek vypadat, umístěte na plochu ještě zmenšenou (Modify | Transform | Scale) instanci symbolu obrazek. Půjde tedy o jakousi předlohu pro skládání. Tím jste dokončili tvorbu základního vzhledu celé skládanky, nyní se budeme věnovat programové stránce ukázky, pokusíme se ji tedy „oživit“.

Oživení v Actionscriptu

1. Do prvního snímku hlavní animace vložte kód (Window | Actions), který nastaví základní proměnné, s nimiž budete pracovat:

size=50; // velikost jednoho dilku
rows=4; // pocet radku skladanky
cols=6; // pocet sloupcu skladanky
n=1; // pomocna promenna
complete._visible=0; // skryti zpravy o slozeni skladanky

2. Vytvořte funkci jménem setpiece. Ta určí, kterou část obrázku má daný dílek představovat. Instanci obrazek, která je umístěna v symbolu dilek ve spodní vrstvě, posuňte tak, aby z celého obrázku byla nakonec skrze masku (umístěnou ve střední vrstvě) vidět pouze jeho určitá část. Proměnná size udává velikost jednoho dílku.

function setpiece (who,x,y) { // who je nazev daneho dilku, x je cislo sloupce, y cislo řádku
who.obrazek._x=-x*size-size/2; // posun obrazku do pozadovaneho sloupce
who.obrazek._y=-y*size-size/2; // posun obrazku do pozadovaneho radku
}

3. Pomocí funkce movepiece budete řadit již vytvořené dílky na ploše. Jako opěrný bod použijte souřadnice již dříve vytvořené instance start. Funkce bude vypadat následovně:

function movepiece (who,x,y) { // who je nazev daneho dilku, x je cislo sloupce, y cislo radku
who._x=x*size+start._x+size/2; // posun dilku do pozadovaneho sloupce
who._y=y*size+start._y+size/2; // posun dilku do pozadovaneho sloupce
}

4. Funkce newpiece vám poslouží k tvorbě nového dílku. Duplikací instance dilek (kterou jste již dříve umístili mimo plochu) vytvoříte nový dílek. Jeho polohu upraví funkce movepiece. Část obrázku, kterou bude zobrazovat, nastaví funkce setpiece. Parametr part ve funkci udává číslo vytvářeného dílku, přičemž dílky jsou (v našem případě) číslovány od 1 do 23.

function newpiece (part) { // part je cislo dilku
dilek.duplicateMovieClip(„piece“ add n,10+n); // duplikace noveho dilku
setpiece(eval(„piece“ add n),(part-1) % cols,Math.floor ((part-1) / cols));
movepiece(eval(„piece“ add n),(part-1) % cols,Math.floor ((part-1) / cols));
n++;
}

Ve druhém řádku kódu narazíte na funkci add. Ta slouží ke spojování dvou řetězců, nové dílky tedy budou pojmenovány piece1, piece2 atd. Proměnná n bude v tomto případě určovat číslo nového dílku. Použitá funkce duplicateMovieClip má dva parametry. První určuje nové jméno duplikovaného prvku, druhý zase tzv. hloubku. Hloubka je ekvivalentem vrstev v symbolech s tím rozdílem, že v každé hloubce může být pouze jeden prvek. Aby tedy nedocházelo k „přepisování“ dílků, musíte měnit i hloubku, do které budete nové prvky vytvářet. Opět tedy využijte proměnnou n. Protože se bude měnit s každým novým prvkem, bude mít každý prvek jinou hloubku.

Funkce eval použitá na třetím a čtvrtém řádku kódu vrací ukazatel na objekt specifikovaný řetězcem v jejím parametru. Použijte ji např. v případě, že neznáte konkrétní název instance, nebo není instance ještě vytvořena. Kód bude dílky generovat dynamicky, proto se uvedená funkce hodí. Znak % (procento) nahrazuje v Actionscriptu operátor mod, tedy zbytek celočíselného dělení. Využijete ho pro zjištění čísla sloupce, do kterého dílek náleží. V Actionscriptu není naopak zahrnuta funkce pro celočíselné dělení, proto si musíte při dělení vypomoci funkcí Math.floor (zaokrouhluje na celé číslo). Chcete-li totiž získat číslo řádky pro daný dílek, potřebujete samozřejmě celé číslo. Výraz n++ nakonec zvýší hodnotu proměnné n o 1, aby nedocházelo k přepisování dílků, jak jsem již vysvětlil dříve.

5. Nyní připravíte funkci shuffle, která poslouží k náhodnému „rozházení“ jednotlivých dílků skládanky:

function shuffle () {
for (i=1; i<=(cols*rows-1); i++) {
movepiece(eval(„/piece“ add i),-10,0);
}
for (i=1; i<=(cols*rows-1); i++) {
 bool=1;
 while (bool==1) {
  r=random(cols*rows);
  if (eval(„/piece“ add r)._x<0) {
   bool=0;
  }
 }
 movepiece(eval(„/piece“ add r),(i-1) % cols,Math.floor ((i-1) / cols));
}
}

Nejprve kód všechny dílky přesune mimo plochu, konkrétně na souřadnice -10,0 (řádek 2 až 4). Pak bude postupně pro každé místo na ploše hledat jeden dílek tak, aby bylo rozmístění vždy náhodné a aby se dílky nekryly (řádek 5 až 14). Proměnnou bool nastaví nejprve na hodnotu 1 (řádek 6). Do proměnné r vloží náhodné číslo v rozsahu 1 až 23 (řádek 7). Kód zjistí, zda již není dílek s tímto číslem na ploše (tzn., že souřadnice musí být menší než 0; řádek 8). V případě, že dílek na ploše není, změní se hodnota proměnné bool na 0 a program postupuje dále, v opačném případě hledá kód jiný dílek pro obsazení daného místa (řádek 9).

Vybraný dílek je pomocí funkce movepiece usazen na dané místo a kód se přesune na další místo (řádek 12). Cyklus bude probíhat pouze 23 x, protože místo vpravo dole bude ponecháno volné. Jeden dílek ve skládance totiž musí chybět, aby jej bylo možné přesunovat.

6. „Neviditelnému“ tlačítku v symbolu hotovo přiřaďte následující kód:

on (release) {
 _root.shuffle();
 _root.complete._visible=0;
}

Tento kód zajistí, aby bylo možné (po zobrazení zprávy o složení skládanky) stiskem tlačítka „Znovu“ dílky opět rozházet.

7. Abyste mohli kontrolovat, zda je již skládanka složena, vytvořte ještě funkci check:

function check () {
bool=1;
for (k=1; k<=(cols*rows-1); k++) {
 tx=_root.start._x+_root.size+((k-1) % cols)*size;
 ty=_root.start._y+_root.size/2+Math.floor((k-1) / cols)*size;
 if ((eval(„/piece“ add k)._y!=ty)or(eval(„/piece“ add k)._x!=tx)) {
  bool=0;
 }
}
if (bool==1) {
 complete._visible=1;
}
}

Hodnotu proměnné bool nastavte na 1 (řádek 2). U všech dílků postupně zkontrolujte, zda leží na patřičném místě (tzn. dílek 1 na 1. místě, dílek 2 na 2. místě atd.; řádek 3 až 9). Do pomocných proměnných tx a ty uložte souřadnice patřičného místa (řádek 4 až 5). Souřadnice tx a ty porovnejte se skutečnými souřadnicemi daného dílku (řádek 6).

Pokud souřadnice nesouhlasí, znamená to, že daný dílek není na svém místě. Proměnnou bool tedy nastavte na 0 (řádek 7). Jsou-li všechny dílky na svém místě (hodnota proměnné bool zůstává nezměněna, rovna 1; řádek 10), zobrazíte zprávu o složení skládanky (řádek 11).

8. Na konec kódu vložte následující řádky. Uvedený kód vytvoří na ploše 23 nových dílků a následně je zamíchá:

for (i=1; i<=(cols*rows-1); i++) { // vytvoreni 23 novych dilku
 newpiece(i);
}
shuffle(); // nahodne rozhazeni dilku
stop (); // zastaveni animace

9. Nyní je potřeba zajistit, aby dílky reagovaly na klepnutí myší a v případě volného místa docházelo k jejich přesunu. Vytvoříte proto obsluhu tlačítka uvnitř symbolu dilek. Do prvního snímku vrstvy kod v symbolu dilek umístěte následující kód:

function zkus (mx,my) {
if (move==0) {
 bool=1;
 minx=_root.start._x;
 miny=_root.start._y;
 maxx=minx+_root.cols*_root.size;
 maxy=miny+_root.rows*_root.size;
 for (i=1; i<=(_root.cols*_root.rows-1); i++) {
  if (((eval(„/piece“add i)._x==(this._x+_root.size*mx))and(eval(„/piece“add i)._y==(this._y+_root.size*my))or((this._y+my*_root.size>maxy)or((this._x+mx*_root.size)>maxx)or((this._x+mx*_root.size)<minx)or((this._y+my*_root.size)<miny)))) {
   bool=0;
  }
 }
 if (bool) {
 this._x=this._x+_root.size*mx;
 this._y=this._y+_root.size*my;
 move=1;
 }
 }
}

Funkce zkus otestuje, zda je možné dílek posunout daným směrem. Směr je zadán relativními souřadnicemi mx a my. Do proměnné bool vložíte hodnotu 1 (řádek 3). Do proměnných minx, miny, maxx, maxy uložíte minimální a maximální možné souřadnice, které může dílek mít (řádek 4 až 7).

Poté postupně porovnáte souřadnice daného dílku se všemi ostatními dílky, abyste zjistili, zda s nějakým v daném směru pohybu nekoliduje a zda neleží cílová poloha mimo vymezenou plochu (porovnáním s proměnnými minx, miny, maxx, maxy). Řádek 6 je mimořádně dlouhý, ale do Actionscriptu je třeba jej vložit bez přerušení. (řádek 4 až 9).

Pokud byly splněny výše uvedené podmínky, přesune se dílek na nové souřadnice. Abyste se ujistili, že nedojde při testování dalšího směru k opětovnému pohybu (dílek by se po klepnutí vrátil tam a zpět), nastavíte hodnotu proměnné move na 1. Proměnná tedy bude indikovat, že od posledního stisku tlačítka již došlo k pohybu dílku (řádek 10 až 14).

10. Aby dílek na stisknutí reagoval, musíte mu přiřadit příslušnou akci. „Neviditelnému“ tlačítku ve vrstvě kod symbolu dilek přiřadíte následující kód:

on (press) {
 move=0;
 zkus(1,0);
 zkus(0,1);
 zkus(-1,0);
 zkus(0,-1);
_root.check();
}

Celá akce bude probíhat ihned po stisku tlačítka (press; řádek 1), nikoli až po jeho uvolnění (release). V našem případě je to vhodnější, akce se tím zrychlí. Proměnnou move nastavte na hodnotu 0, bude tedy ukazovat, že od stisku tlačítka ještě nedošlo k pohybu dílku (řádek 2).

Otestujte, do kterého směru je možné s dílkem „pohnout“. Protože je v celé skládance volné vždy pouze jedno místo, bude možný vždy pouze jeden směr. Proto je pořadí, ve kterém budete směry testovat, čistě náhodné. K testu použijete funkci zkus, jako parametry zadáte relativní souřadnice nové pozice dílku. Ve výše uvedeném případě budou tedy odpovídat směrům nahoru, vpravo, dolů a vlevo (řádek 3 až 6).

Na závěr ještě pomocí funkce check zkontrolujete, zda již není skládanka složena. Protože je tato funkce definována v rámci celé animace a nikoli pouze v rámci symbolu dílek, musíte ji volat jako funkci celé animace (_root).

Tím je tvorba celé skládanky kompletně ukončena. Puzzle si nyní můžete vyzkoušet po spouštění celé animace (Control | Test movie). Dejte si pozor na používání českých znaků (háčků a čárek). V tomto článku jsou sice použity některé české názvy symbolů nebo instancí, jsou však vždy psány bez diakritiky.

Podobného efektu lze dosáhnout i s pomocí JavaScriptu – viz článek Hlavolam „15“, náhodná čísla a obrázky.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět