Vánoční hra - 1. část
14.12.2006· Autor: Ondřej Brichta·
Přidat komentář
Nedávno jsme si zde ukázali tvorbu vlastní třídy, kterou jsme využili k vystřelování objektů. Dnes na tento článek navážeme a vytvoříme si základní prvek naší hry, kterým je sněhulák, vrhající sněhové koule.
Princip hry
Ve hře samotné budou vystupovat dvě postavy – sněhuláci, kteří budou po sobě házet sněhové koule. Jeden ze sněhuláků bude ovládán hráčem, druhý sněhulák bude házet koule zcela náhodně. Bude nakonec na nás, jak moc této „náhodě“ pomůžeme a jaký nastavíme konečný rozptyl soupeře. Prakticky tak budeme tímto rozptylem určovat obtížnost, ale k té se dostaneme až v dalším díle. Dnes nás čeká sněhulák, který bude házet sněhové koule podle našeho zadání. Výsledek dnešního snažení si můžeme prohlédnout zde: snehulak
Využijeme zdrojové soubory z článku, kdy jsme si připravili vlastní třídu „Strela“, která umožňuje vystřelovat objekty dle výchozích parametrů. Pokud vytvoříme MovieClip jako objekt této třídy (pravým tlačítkem myši klepneme na daný objekt v knihovně symbolů a pod položkou Linkage nastavíme třídu „Strela“), můžeme mu nastavit tyto vlastnosti:
| Atribut |
Popis hodnoty |
| tiha |
vlastnost která reprezentuje tíhu vystřeleného objektu |
| uhel |
úhel, pod kterým je objekt vystřelen |
| sila |
vlastnost, reprezentující sílu s jakou je objekt vystřelen |
| rychlost |
vlastnost, kterou definujeme velikost kroku v onEnterFrame události, která aktualizuje polohu objektu |
| testObject |
objekt, vůči kterému testujeme střelu, pokud se střela s objektem srazí, zůstane na místě bez dalšího pohybu |
Kromě uvedených vlastností (v rámci souboru třídy se jedná o veřejné proměnné, v rámci objektu této třídy mluvíme o vlastnostech/atributech) máme zatím dispozici metodu fire(), kterou objekt vystřelujeme.
Dynamika sněhuláka
Dnešním úkolem bude vytvoření sněhuláka, který bude odhazovat sněhové koule. Asi největší problém se skrývá v pohybu paže sněhuláka, která bude sněhovou kouli vystřelovat. Pokud budeme chtít, aby nebyl pohyb strnulý a sněhulák opravdu budil dojem házení koule, musíme mu před odhozením vložit sněhovou kouli do ruky, ruku napřáhnout, mrštit a až poté můžeme zavolat metodu fire() a odhodit sněhovou kouli.
Dynamika nápřahu a odhozu je velmi dobře simulovatelná pomocí třídy Tween, kterou využijeme pro rotaci:
moveObj = function (obj:Object, rotace:Number):Void {
posunTyp = mx.transitions.easing.Strong.easeIn;
posun = new mx.transitions.Tween(obj, "_rotation", posunTyp, obj._rotation, rotace, 12, false);
posun.onMotionFinished = function() {
trace("Pohyb dokončen");
};
};
Menší problém se tak vyskytne až v situaci, kdy se ruka sněhuláka pohybuje a my chceme, aby během pohybu měl sněhulák v ruce sněhovou kouli až do okamžiku jejího vystřelení. Musíme tak během celé rotace ruky sněhuláka sledovat polohu jejího konce, kde má být umístěna sněhová koule.
Vypomůžeme si malým MovieClipem, který umístíme právě na konec ruky sněhuláka. Během rotace ruky pak použijeme metodu localToGlobal, která umožňuje převést lokální souřadnice (pomocného objektu na konci ruky) na souřadnice globální. Metoda se používá ve tvaru:
var bod:Object = {x:10, y:10};
hand.localToGlobal(bod);
trace(„Globální souřadnice x : “+bod.x);
trace(„Globální souřadnice y : “+bod.y);
Sněhulák
Teorii máme za sebou, podívejme se tedy na vlastní aplikaci. Nejprve si stáhneme zdrojová data (odkaz na předchézí data) v předcházejícího článku. Nesmíme zapomenout umístit do stejného adresáře jak zdrojový FLA soubor, tak i zdrojový soubor „Strela.as“.
Otevřeme si zdrojový soubor a vytvoříme MovieClip, do kterého nakreslíme samotného sněhuláka. Sněhuláka umístíme na scénu a pojmenujeme jeho instanci „snehulak“. V movieClipu sněhuláka vytvoříme další MovieClip, který bude představovat ruku. Aby byl pohyb ruky bezproblémový, nakreslíme jí tak, aby měla „rameno“ ve středu MovieClipu:

Instanci ruky pojmenujeme „ruka“. Protože budeme chtít sledovat pozici vrcholu ruky, vytvoříme v ní MovieClip, jehož instanci pojmenujeme „drzeni“ a přesuneme jej na konec ruky, kde budeme chtít umístit házenou sněhovou kouli:

Pokud jsme postupovali správně, budeme moci zacílit vrchol ruky sněhuláka touto cestou:
snehulak.ruka.drzeni
Úprava třídy „Strela“
Nyní se můžeme soustředit pouze na úpravu ActionScriptu. Otevřeme si soubor třídy „Strela“ a vložíme do něj tyto nové funkce:
private var intervalId:Number;
public function move_hand(obj:MovieClip):Void {
intervalId = setInterval(this, "folow_hand", 10, obj);
}
private function follow_hand(hand:MovieClip):Void {
var bod:Object = {x:hand._x, y:hand._y};
hand._parent.localToGlobal(bod);
this._x = bod.x-this._width/2;
this._y = bod.y-this._height/2;
}
public function reset_hand():Void {
clearInterval(intervalId);
}
Pomocí funkce „move_hand“ nastavíme sledování pohybu objektu, který předáme v parametru této funkce. V intervalu 10 milisekund zajistíme sledování souřadnic objektu (v našem případě budeme sledovat pohyb objektu na vrcholu ruky), převedeme je na globální souřadnice hlavní scény a přesuneme na ně objekt této třídy.
Protože budeme chtít objekt vystřelit pomocí funkce „fire“, musíme umožnit zastavit sledování pohybu vrcholu ruky. To umožníme další funkcí „reset_hand“, kterou vymažeme spouštění funkce „follow_hand“ v intervalu 10 milisekund.
Konečná podoba souboru „Strela.as“ pak bude vypadat takto:
import flash.display.BitmapData;
import flash.geom.Point;
class Strela extends MovieClip {
private var bmp1:BitmapData;
private var bmp2:BitmapData;
public var tiha:Number;
public var uhel:Number;
public var sila:Number;
public var rychlost:Number;
public var testObject:MovieClip;
private var intervalId:Number;
public function move_hand(obj:MovieClip):Void {
intervalId = setInterval(this, "folow_hand", 10, obj);
}
private function folow_hand(hand:MovieClip):Void {
var bod:Object = {x:hand._x, y:hand._y};
hand._parent.localToGlobal(bod);
this._x = bod.x-this._width/2;
this._y = bod.y-this._height/2;
}
public function reset_hand():Void {
clearInterval(intervalId);
}
public function fire():Void {
bmp1 = new BitmapData(Stage.width, Stage.height, true, 0x00000000);
bmp2 = new BitmapData(Stage.width, Stage.height, true, 0x00000000);
bmp1.draw(this);
bmp2.draw(testObject);
var startY:Number = this._y;
var startX:Number = this._x;
var nm:Number = 0;
this.onEnterFrame = function() {
var bod1:Point = new Point(this._x, this._y);
var bod2:Point = new Point(testObject._x, testObject._y);
var test:Boolean = new Boolean(bmp1.hitTest(bod1, 255, bmp2, bod2));
nm += rychlost;
var vx:Number = Math.cos(Math.PI*(uhel/180))*sila;
var vy:Number = Math.sin(Math.PI*(uhel/180))*sila;
var posuvX:Number = startX+vx*nm;
var posuvY:Number = startY-1*(vy*nm-(1/2)*tiha*nm*nm);
this._x = posuvX;
this._y = posuvY;
if (kolize(this, testObject) == true) {
do {
nm -= 0.1;
var posuvX:Number = startX+vx*nm;
var posuvY:Number = startY-1*(vy*nm-(1/2)*tiha*nm*nm);
this._x = posuvX;
this._y = posuvY;
} while (kolize(this, testObject) != false);
delete this.onEnterFrame;
}
};
}
private function kolize(objekt1:MovieClip, objekt2:MovieClip):Boolean {
var bod1:Point = new Point(objekt1._x, objekt1._y);
var bod2:Point = new Point(objekt2._x, objekt2._y);
var test:Boolean = new Boolean(bmp1.hitTest(bod1, 255, bmp2, bod2));
return test;
}
}
Funkce hlavní aplikace
Přesuneme se zpět do hlavní aplikace a do prvního snímku hlavní časové osy vložíme tuto funkci:
hod_rukou = function (rot:Number, obj:MovieClip, _tiha:Number, _uhel:Number, _rychlost:Number, _sila:Number, _testobj:MovieClip):Void {
pohybTyp = mx.transitions.easing.Strong.easeIn;
var koef:Number = 1.5+_sila /20;
var start_uhel = -1*(koef*40+rot);
if (start_uhel<-180) {
start_uhel = -180;
}
rotace1 = new mx.transitions.Tween(snehulak.ruka, "_rotation", pohybTyp, snehulak.ruka._rotation, start_uhel, 12, false);
obj.move_hand(snehulak.ruka.drzeni);
rotace1.onMotionFinished = function() {
rotace2 = new mx.transitions.Tween(snehulak.ruka, "_rotation", pohybTyp, snehulak.ruka._rotation, -1*rot, 6, false);
rotace2.onMotionFinished = function() {
obj.reset_hand();
obj.tiha = _tiha;
obj.uhel = _uhel;
obj.rychlost = _rychlost;
obj.sila = _sila;
obj.testObject = _testobj;
obj.fire();
};
};
};
Funkce „hod_rukou“ přebírá hned několik parametrů, kterými nastavujeme výchozí hodnoty vystřelovaného objektu. Než ale spustíme metodou „fire“ odpálení sněhové koule, chceme nejdříve „napřáhnout“ ruku sněhuláka. Nápřah ruky bude omezen do maximální hodnoty 180° ve zpětném směru (navíc komponenta numericStepper, nastavující úhel výstřelu, by měla mít omezení od 0° do 90°), protože nechceme, aby si sněhulák při nápřahu protočil paži, nepůsobilo by to věrohodně.
Samotný výchozí úhel nápřahu bude vždy záviset na síle, se kterou budeme sněhovou kouli házet a tak při malé síle vytvoříme i menší nápřah.
Jakmile máme určený výchozí úhel nápřahu, můžeme pomocí třídy Tween provést animaci nápřahu a spustit sledování pohybu vrcholu ruky „obj.move_hand(snehulak.ruka.drzeni);“. Po dokončení animace nápřahu spustíme druhou tween animaci odhození po jejímž skončení odhodíme kouli pomocí „fire()“ metody.
Nakonec už jen upravíme skript na tlačítku spouštění animace:
on (click) {
if (num == undefined) {
num = 1;
} else {
num++;
}
_root.attachMovie("strela", "strela"+num, _root.getNextHighestDepth());
_parent.hod_rukou(_parent.uhel.value, eval("_root.strela"+num), _parent.tiha.value, _parent.uhel.value, _parent.rychlost.value, _parent.sila.value, _parent.pozadi);
}
Tímto skriptem budeme neustále generovat nové střely a odpalovat je sněhulákem do prostoru. Výslednou aplikaci si můžeme prohlédnout zde: snehulak
Zdrojové soubory jsou k dispozici zde: zdroje.zip
Ondřej Brichta Vývojář multimediálních aplikací, šéfredaktor Flash.cz, školitel produktů Flash, Flex, Flash Media Server
Web:
http://www.obria.cz
|
Motto: <°))))><