28. července 2008

Programování postupných procesů ve Flashi

Při vytváření složitější Flash animace často narazíte na problém, jak šikovně naprogramovat jednotlivé na sebe postupně navazující fáze animace, kdy pro přechod z jedné fáze do druhé je nutné, aby byla splněna pokaždé jiná podmínka. Použití konstrukce if - else if - else je přitom problematické, protože do ní musíte zahrnout nejen podmínky nutné pro provedení určité části kódu, ale také podmínky, které vylučují provedení dané části částí kódu po nabytí platnosti jiných podmínek.

Je nutné opravdu dobře promyslet všechny možné kombinace podmínek a přesně je vymezit. Musíte se přitom zabývat i ošetřením kombinací, které Vás vlastně ani nezajímají. Ve výsledku pak často obdržíte velmi nepřehledný a nepružný kód, který nám znesnadní práci a budoucí úpravy.

Ano, je pravda, že následující kód je jasný, elegantní a přehledný:

_root.onEnterFrame = function()
{
// stanoveni aktualni hodnoty promenne cas
if (cas > 5)
{
// kod pro casovy interval (5,10>
}
else if (cas > 10)
{
// kod pro casovy interval (10,15>
}
else if (cas > 15)
{
// kod pro casovy interval (15,20>
}
else if (cas > 20)
{
// nic ... uz se nema provadet zadny kod
}
else
{
// kod pro casovy interval <0,5>
}
};

Nyní si ale představte, že po dosažení času 5s chcete nějaké akce provést jen jednorázově a po té až do 10s provádět jiné příkazy. Dále, že po dosažení 10s musíte otestovat, jestli již doběhla nějaká jiná část animace až do konce a teprve pak provést opět jednorázově nějaké příkazy a až do 15s provádět pak úplně jiné a teprve pak vás bude zajímat, jestli čas už přesáhl 15s atd. Vznikne Vám pak kód, z něhož se kamsi vytratila elegance a hlavně "jednoznačnost na první pohled":

_root.onEnterFrame = function()
{
// stanoveni aktualni hodnoty promenne cas
if (cas > 5)
{
if (!cas5)
{
// kod jednorazovy po dosazeni 5s
cas5 = true;
}
else
{
// kod pro casovy interval (5,10>
}
}
else if (cas > 10)
{
if (dobehlaAnimacePro10)
{
if (!cas10)
{
// kod jednorazovy po dosazeni 10s a splneni podminky dobehnuti jine animace
cas10 = true;
}
else
{
if (cas > 15)
{
// kod pro casovy interval (15,20>
}
else if (cas > 20)
{
// nic ... uz se nema provadet zadny kod
}
else
{
// kod pro casovy interval (10,15>
}
}
}
}
else
{
// kod pro casovy interval <0,5>
}
};

Hrůza, že?

Když se nad tím, co provádí uvedený rozhodovací strom zamyslíte, uvědomíte si, že se jedná o postupné fáze nějakého procesu, kde se jako postačující rozlišovací údaj pro provedení té které fáze dá použít pouze název dané fáze. Ten si můžete uložit do pomocné proměnné s příznačným jménem faze a pak už je snadné napsat pouze jednoúrovňový řetězec podmínek if - else if, kde se bude testovat pouze hodnota proměnné faze a nic jiného. Pro ohraničení jednotlivých částí kódu lze stejně tak použít i konstrukci switch - case - ta se mně osobně líbí více:

faze = "_0-5_";
_root.onEnterFrame = function()
{
// stanoveni aktualni hodnoty promenne cas
switch (faze)
{
case "_0-5_" :
// kod pro casovy interval <0,5>
if (cas > 5)
{
faze = "_5_";
}
break;
case "_5_" :
// kod jednorazovy po dosazeni 5s
faze = "_5-10_";
break;
case "_5-10_" :
// kod pro casovy interval (5,10>
if (cas > 10)
{
faze = "_10.1_";
}
break;
case "_10.1_" :
if (dobehlaAnimacePro10)
{
faze = "_10.2_";
}
break;
case "_10.2_" :
// kod jednorazovy po dosazeni 10s a splneni podminky dobehnuti jine animace
faze = "_10-15_";
break;
case "_10-15_" :
// kod pro casovy interval (10,15>
if (cas > 15)
{
faze = "_15-20_";
}
break;
case "_15-20_" :
// kod pro casovy interval (15,20>
if (cas > 20)
{
faze = "_20_";
}
break;
case "_20_" :
// nic ... uz se nema provadet zadny kod
// tuto vetev case vlastne uz ani psat nemusime
break;
}
};

Takovýto zápis má několik výhod. Pokud si pojmenujete jednotlivé fáze dostatečně výstižně, bude se Vám v kódu lehčeji orientovat. Také již nemusíte řešit ošetřování všech možných kombinací ohraničujících podmínek. Zde řešíte už jen to, co v dané fázi přichází v úvahu a nic víc. Můžete tak snadno přidávat či ubírat další fáze, a je jedno jestli na začátku, konci či přímo v těle stromu procesu. Můžete také některé fáze v rámci ladění programu snadno „přemostit“, a to pouhým přepsáním resp. připojením řádku pro změnu obsahu proměnné faze s odpovídající hodnotou. Můžete si na různých místech procesu vytvořit speciální fáze, které pak můžete použít jako vstupní body při skoku doprostřed procesu atd.

Princip tohoto řešení je, že použijete pomocnou proměnnou faze, přičemž pouze její obsah a nic jiného určuje, co se má v danou chvíli v rámci probíhajícího postupného procesu provádět a co již ne nebo ještě ne. Tím si často spletitý mnohoúrovňový rozhodovací strom abstrahujete do dvou jednoduše pojmutelných logických vrstev. V první vrstvě se pouze na základě obsahu proměnné faze rozhodne, co se bude provádět a teprve v druhé vrstvě, uvnitř každé části procesu se řeší, kdy se má hodnota proměnné faze změnit a jak.

Žádné komentáře:

Okomentovat

Chovejte se zde, prosím, jako v místnosti plné lidí, na kterých Vám záleží. Děkuji :o)