12. září 2008

Jak jednoduše převést jakékoli reálné číslo na celé, které bude ležet v povoleném intervalu hodnot

Pokud ve Flash animaci potřebujete ošetřit vstup číslené hodnoty tak, abyste měli k dispozici číslo, které bude vždy celé a bude spadat do souvislého intervalu ostře omezeného hodnotami "n1" a "n2" (tzn. že tyto vymezující hodnoty patří do množiny povolených čísel), nemusíte v Action Scriptu psát žádnou složitou testovací proceduru.

Vystačíte si s jedním řádkem kódu, který jakékoli reálné číslo "x" převede na číslo celé "n" a pokud je toto zaokrouhlené číslo vně intervalu "n1" až "n2", přiřadí mu nejbližší krajní hodnotu:

n = Math.min(Math.max(n1, Math.floor(x)), n2);

Místo Math.floor(x) můžete samosebou použít Math.ceil(x) nebo Math.round(x), podle toho, jaký druh systematické chyby na vstupu předpokládáte.

Navíc zápis Math.min(Math.max(n1, n), n2); má sám o sobě elegantní tvar, který se nejen dobře pamatuje a zapisuje, ale má i jasnou vypovídací hodnotu.

2. září 2008

Pořadí změny rozměrů instance movieklipu a nastavení její rotace

Taková banalita a potrápila mne skoro hodinu, než jsem si uvědomil v čem je problém. Ale to bude tím, že jsem závadu hledal nejprve úplně jinde (píšu / psal jsem zrovna kód pro složitou aplikaci, takže než jsem se přes všechny její vrstvy dopracoval k jádru ... :o).

Oč jde?

Představte si, že máte na scéně Flash animace umístěnou instanci nebo ještě lépe více instancí movie klipu, kterým jednou za čas (v rámci resetu nastavení Flash animace) nastavujete rozměry pomocí vlastností ._width a ._height (v ActionScriptu samozřejmě). Mezi jednotlivými resety těmi instacemi po scéně různě pohybujete a někdy je i otáčíte pomocí vlastnosti ._rotation (opět v ActionScriptu). Čas od času se stane, že po resetu jsou některé instance menší, než by měly.

Možná už tušíte, kde je problém. Ano, chyba se projevuje tehdy, když je natočení "postižené" instance před resetem jiné než 0° nebo 180°.

Příčina takového divného chování je potom v pořadi, v jakém při reset nastavujete jednotlivým instancím rozměry (._width, ._height) a natočení (._rotation). Pro zjednodušení si představte, že instance jsou obdélníkové a při ._rotation=0° mají hrany rovnoběžné se scénou. Pokud budou instance před resetu natočené jinak, a reset provedete v pořadí:

instance_mc._width = sirka;
instance_mc._height = vyska;
instance_mc._rotation = 0;

bude jejich velikost (šířka a výška) nastavená tak, aby se natočené vešly do ohraničujícího obdélníku o velikosti sirka x vyska, taže po nasledném srovnání budou menší a zdeformované.

Někdy je taková věc účelná, ale pokud chcete, aby rozměry v základní poloze "seděly", musíte instance nedříve otočit do základní polohy a pak teprve nastavovat rozměry:

instance_mc._rotation = 0;
instance_mc._width = sirka;
instance_mc._height = vyska;

Pravda. Pokud rozměry instancí během pohybování s nimi neměníte a pouze je otáčíte (jak tomu bylo v mém případě), je opětovné nastavování rozměrů vlastně zbytečné (když já se ale držím zásady, že když reset, tak všeho :o). Přesto tak musíte postupovat vlastně kdykoli, kdy rozměry instance na scéně měníte a instance je v době změny rozměrů natočená jinak, než na 0° nebo 180°:

uhelNatoceni = instance_mc._rotation;
instance_mc._rotation = 0;
instance_mc._width = sirka;
instance_mc._height = vyska;
instance_mc._rotation = uhelNatoceni;

resp.:

instance_mc._rotation = 0;
instance_mc._width = sirka;
instance_mc._height = vyska;
instance_mc._rotation = novyUhelNatoceni;

Jak říkám, je to banalita :o)