Pohyb objektů pomocí ActionScriptu

14.8.2006· Autor: Ondřej Brichta· Počet komentářů: 13

Způsobů, jak rozpohybovat objekty na scéně je mnoho. V dnešním díle se zaměříme na možnosti pohybování s objekty pomocí příkazů ActionScriptu. Začneme od jednoduchých řešení pomocí onEnterFrame událostí až se nakonec dostaneme k velmi užitečné Tween třídě.

Pohyb pomocí onEnterFrame

Pokud chceme pohybovat objekty po scéně, máme několik možností. Relativně nejjednodušším způsobem je použití MotionTween animace, kdy máme v jedné vrstvě časové osy dva klíčové snímky, v každém z nich je totožný objekt (MC, Button) a pomocí MotionTween animace je vytvořen pohyb mezi oběma klíčovými snímky. Blíže jsme se tomuto tématu věnovali zde .

Určitě se ale setkáme s případy (hry, složitější animace…), kdy bude potřeba vytvořit pohyb objektu pomocí příkazů ActionScriptu. Ovládání pohybu objektů na scéně se provádí pomocí změny jejich souřadnic a to v časové závislosti. Jak plyne čas, měníme postupně hodnoty x-ové nebo y-ové souřadnice objektu, který se tak pohybuje po scéně.

Nejjednodušším způsobem, jak zajistit plynulý pohyb objektů je využití události onEnterFrame, která náleží veškerým objektům typu (z třídy) MovieClip (MC). Událost onEnterFrame neustále opakuje příkazy v ní vložené, takže pokud napíšeme tento skript:

_root.onEnterFrame = function() {
_root.objekt._x += 10;
_root.objekt._y += 10;
};

MovieClip pojmenovaný „objekt“, umístěný na hlavní scéně, se bude pomocí tohoto skriptu plynule pohybovat o 10px v x-ovém a v y-ovém směru. Abychom pohyb objektu na určené místo udělali univerzálnějším, připravíme si funkci, s jejíž pomocí budeme s objekty pohybovat.

Funkce pro pohyb objektů

V novém dokumentu si na scéně připravíme tři vstupní dynamické textové pole, které budou sloužit pro zadávání souřadnic a určení délky pohybu. Pole pojmenujeme „new_x“, „new_y“ a „snimky“. Dále si vytvoříme MovieClip objekt, kterým budeme pohybovat a pojmenujeme jej „objekt“. Nakonec na scénu vložíme tlačítko, které pojmenujeme „start_b“.

Do akcí prvního snímku hlavní časové osy vložíme tento skript:

moveObj = function (obj:Object, cil_x:Number, cil_y:Number, doba:Number):Void {
posuv_x = cil_x-obj._x;
posuv_y = cil_y-obj._y;
count = 0;
obj.onEnterFrame = function() {
count++;
obj._x += posuv_x/doba;
obj._y += posuv_y/doba;
if (count == doba) {
delete obj.onEnterFrame;
}
};
};
start_b.onRelease = function() {
moveObj(objekt, new_x.text, new_y.text, snimky.text);
};

Jedná se o velmi jednoduchou funkci, pojmenovanou „moveObj“ s jejíž pomocí můžeme pohybovat jakýmkoliv objektem na scéně. Tato funkce obsahuje celkem 4 parametry, kde prvním (obj) definujeme objekt, kterým chceme hýbat, další dva parametry (cil_x, cil_y) slouží k určení cílové pozice objektu a poslední parametr (doba) slouží k určení doby (v počtu snímků) pohybu objektu.

Jakmile je funkce spuštěná, objektu přiřadíme pomocí onEnterFrame události skript, který zajistí plynulý pohyb objektu k cílové pozici. Tento pohyb trvá, dokud není počítadlo kroků (count) rovno době, kterou měl celý pohyb trvat. Pokud doba vypršela, vymažeme onEnterFrame událost z MovieClipu, abychom zbytečně nezatěžovali procesor.

 

Zrychlení a zpomalení pohybu

Ne vždycky se spokojíme s jednoduchým pohybem, který je bez jakéhokoliv zrychlení či zpomalení. Zrychlující či zpomalující objekty působí při svém pohybu vždy přirozeněji než objekty s konstantní rychlostí. Pro vytvoření postupně se zpomalujícího pohybu přepíšeme předchozí skript tímto:

moveObj = function (obj:Object, cil_x:Number, cil_y:Number, doba:Number):Void {
i = 0;
plus = 0.5/doba;
count = 0;
posuv_x = cil_x-obj._x;
posuv_y = cil_y-obj._y;
startX = obj._x;
startY = obj._y;
obj.onEnterFrame = function() {
count++;
i += plus;
obj._x = startX+posuv_x*(Math.sin(Math.PI*i));
obj._y = startY+posuv_y*(Math.sin(Math.PI*i));
if (count == doba) {
delete obj.onEnterFrame;
}
};
};
start_b.onRelease = function() {
moveObj(objekt, new_x.text, new_y.text, snimky.text);
};

Pro vytvoření plynulého dojezdu jsme zde použili goniometrickou funkci Sinus(x). Prohlédneme si nejdřív tento graf:

graf1

Graf zobrazuje sinusoidu a červeně zvýrazněná část vyznačuje oblast, která nás zajímá. Pokud se podíváme pozorněji, tak y-ové hodnoty jsou v rozmezí od -1 do 1 a ve vyznačené oblasti pak hodnot 0 až 1 přičemž od 0 hodnoty rostou společně s x-ovou osou pozvolněji. Pokud využijeme této vlastnosti a vynásobíme jí cílovou pozicí objektu (posuv_x), dostaneme postupně se zpomalující pohyb objektu.

Abychom nezůstali pouze u zpomalování, upravíme si skript tak, aby vytvořil plynule zrychlující a zpomalující se pohyb:

 

moveObj = function (obj:Object, cil_x:Number, cil_y:Number, doba:Number):Void {
delete obj.onEnterFrame;
i = 0.5;
plus = 1/doba;
count = 0;
posuv_x = cil_x-obj._x;
posuv_y = cil_y-obj._y;
startX = obj._x;
startY = obj._y;
obj.onEnterFrame = function() {
count++;
i += plus;
obj._x = startX+(posuv_x*(1-(Math.sin(Math.PI*i))))/2;
obj._y = startY+(posuv_y*(1-(Math.sin(Math.PI*i))))/2;
if (count == doba) {
delete obj.onEnterFrame;
}
};
};
start_b.onRelease = function() {
moveObj(objekt, new_x.text, new_y.text, snimky.text);
};
this.onEnterFrame = function() {
if (Key.isDown(Key.UP)) {
moveObj(objekt, objekt._x, objekt._y-50, 12);
}
if (Key.isDown(Key.DOWN)) {
moveObj(objekt, objekt._x, objekt._y+50, 12);
}
if (Key.isDown(Key.LEFT)) {
moveObj(objekt, objekt._x-50, objekt._y, 12);
}
if (Key.isDown(Key.RIGHT)) {
moveObj(objekt, objekt._x+50, objekt._y, 12);
}
};

V tomto případě využijeme jinou část sinusoidy:

graf

Jak je patrné ze zvýrazněné části grafu, pohyb bude nejdříve zrychlovat, přes oblast s přibližně konstantní rychlostí až se opět dostane ke zpomalování. Vzhledem k rozšíření oblasti grafu, kterou využíváme, je nutné posunout „počátek“ pomocí proměnné „i“ o půl periody, proto jsme nastavili počáteční hodnotu na 0.5.

Na konci samotného skriptu jsme si připravili v onEnterFrame události hlavní osy testování stisknutých kurzorových šipek. Zde pomocí metody isDown() zjišťujeme, jestli není některá ze šipek stisknutá. Pokud ano, necháme objekt posunout o příslušný počet bodů, podle toho, kterou klávesu jsme stisknuli.

Pohyb pomocí Tween třídy

Nakonec si představíme asi nejjednodušší řešení pohybu objektu. Využijeme Tween třídu a upravíme předchozí skripty:

moveObj = function (obj:Object, cil_x:Number, cil_y:Number, doba:Number):Void {
posunTyp = mx.transitions.easing.Strong.easeInOut;
posun = new mx.transitions.Tween(obj, "_x", posunTyp, obj._x, cil_x, doba, false);
posun = new mx.transitions.Tween(obj, "_y", posunTyp, obj._y, cil_y, doba, false);
posun.onMotionFinished = function() {
trace("Pohyb dokončen");
};
};
start_b.onRelease = function() {
moveObj(objekt, new_x.text, new_y.text, snimky.text);
};

 

A to je vše. Veškerá ta námaha se sledováním průběhu sinusoidy je pryč a vše se krásně vešlo do tří řádků. Ale hezky od začátku. Pro samotný pohyb objektu na novou pozici jsme použili instanci (posun) Tween třídy, které jsme předali několik důležitých parametrů.

Prvním je instance objektu, kterým chceme pohybovat (obj). Následuje vlastnost (může být prakticky jakákoliv vlastnost/proměnná cíleného objektu), kterou chceme změnit. V našem případě měníme x-ovou a y-ovou pozici objektu. Třetím parametrem je typ pohybu, který objekt bude vykonávat. Máme na výběr z těchto možností:

 
   
Back objekt o kousek přejede cílovou pozici a pak se do ní vrátí
Bounce efekt postupného tlumení odrazů cílové pozice
Elastic objekt postupně „dokmitává“ kolem cílové pozice
Regular, Strong obdobné efekty, kdy dojde k postupnému zpomalení/zrychlení na koncích pohybu
None bez jakéhokoliv efektu

Uvedené efekty mohou ovlivnit začátek, konec nebo obě části pohybu objektu. Kterou část ovlivňují, určuje poslední metoda v nastavení typu pohybu:

 
   
easeIn ovlivnění začátku animace
easeOut ovlivnění konce animace
easeInOut ovlivněn začátek i konec
easeNone bez ovlivnění pohybu

Například zápis:

posunTyp = mx.transitions.easing.Elastic.easeInOut;

vytvoří pohyb, kdy se objekt na začátku pohybu rozhoupe a stejným způsobem i pohyb dokončí.

Pokud budeme pokračovat v rozboru parametrů Tween instance, dalším parametrem po typu pohybu je výchozí hodnota proměnné, v našem případě je to aktuální souřadnice objektu (obj._x, obj._y). Následuje konečná hodnota proměnné (cil_x, cil_y). Předposledním parametrem (doba) určujeme délku trvání pohybu objektu. Jestli je délka v sekundách a nebo ve snímcích, to určuje poslední parametr, který může nabývat logických hodnot true(časový údaj) a false(údaj ve snímcích).

Z výše uvedeného je patrné, že použití Tween třídy je mnohem jednodušší a komfortnější. Ovšem pokud máme animace složené z většího množství vektorových objektů, může se zde projevit rozsáhlejší programové pozadí třídy. V takovýchto případech dochází ke ztrátě plynulosti animací a je vhodnější použít „klasických“ metod animace pohybů pomocí ActionScriptu.

Zdrojové soubory k článku jsou k dispozici zde.

 

 

 

 

 

Ondřej Brichta Vývojář flashových a mobilních AIR aplikací, šéfredaktor Flash.cz, školitel produktů Flash, Flex, Flash Media Server

E-mail: ob(zavinac)obria.cz | Web: http://www.obria.cz |

Motto: <°))))><

Komentáře k článku  
rozšíření Tween class Dritst | 15.8.2006 18:29
nechapu richmondos | 7.9.2006 19:44
Re: nechapu OBr | 7.9.2006 20:02
Re: Re: nechapu richmondos | 7.9.2006 22:07
Re: Re: Re: nechapu OBr | 7.9.2006 22:19
Re: Re: Re: Re: nechapu richmondos | 7.9.2006 22:30
Re: Re: Re: Re: Re: nechapu OBr | 7.9.2006 22:42
Re: Re: Re: Re: Re: nechapu OBr | 7.9.2006 22:52
Re: Re: Re: Re: Re: Re: nechapu richmondos | 7.9.2006 23:01
prosím o pomoc Kubino | 16.11.2006 7:49
prosím o pomoc 2 Kubino | 16.11.2006 7:53
Re: Re: Re: Re: nechapu dodos2 | 7.8.2007 17:54
jednotky Simon P40 | 26.5.2009 17:06

Přihlášení uživatele