reklama

Umíme ve Flashi – 20. díl – detekce kolize II.

V dnešním díle upravíme detekci kolize do obecně použitelné podoby, umožňující zjišťovat kolizi dvou objektů v aktuálních pozicích včetně užitečné funkce, zjišťující možnou kolizi dvou objektů, která teprve nastane.

Funkce detekce kolize

V předchozím díle jsme měli funkce, detekující kolize objektů, umístěné přímo na symbolu podlahy, což není zrovna praktické řešení, ovšem pro prvotní seznámení se s touto problematikou nám vyhovovalo. Dnes se zaměříme na převedení těchto funkcí do obecné podoby, která nám umožní pohodlné zjištění detekce kolize dvou objektů.

Otevřeme si zdrojový soubor z minulého dílu (ke stažení zde) a do prvního snímku začneme psát upravené funkce. První, kterou z minulého skriptu vytvoříme, nám bude sloužit pro zjišťování aktuální kolize dvou objektů:

hit = function (ref_obj:Object, test_obj:Object) {
 dotyk = new Object();
 dotyk.cast = "nic";
 sour_x = test_obj._x;
 sour_y = test_obj._y;
 sour_w = test_obj._width;
 sour_h = test_obj._height;
 for (i=1; i<test_obj._width; i++) {
  if (ref_obj.hitTest(sour_x+i, sour_y+sour_h, true)) {
   trace("dotyk spodní");
   dotyk.cast = "spodni";
  }
 }
 for (i=1; i<test_obj._width; i++) {
  if (ref_obj.hitTest(sour_x+i, sour_y, true)) {
   trace("dotyk horní");
   dotyk.cast = "horni";
  }
 }
 for (i=1; i<test_obj._height; i++) {
  if (ref_obj.hitTest(sour_x, sour_y+i, true)) {
   trace("dotyk levý");
   dotyk.cast = "leva";
  }
 }
 for (i=1; i<test_obj._height; i++) {
  if (ref_obj.hitTest(sour_x+sour_w, sour_y+i, true)) {
   trace("dotyk pravý");
   dotyk.cast = "prava";
  }
 }
 return dotyk;
};

Nová funkce „hit“ požaduje dvě proměnné typu „Object“. Je to pochopitelné, protože potřebujme testovat pozici dvou objektů. Uvedená funkce je téměř shodná s tou, kterou jsme použili v minulém díle. Opět v ní testujeme průnik prvního objektu s krajními body objektu druhého.

Pomocí čtyř cyklů FOR projdeme každou stranu druhého objektu po 1px. Pokud bychom chtěli zjemnit detekci, můžeme proměnnou „i“ navyšovat o nižší hodnoty než je „1“, ale v tomto případě by došlo ke zbytečnému navýšení náročnosti na procesor, proto volíme jako nejnižší hodnotu číslo 1.

Funkce „hit“ nám podle výsledků vrací v proměnné „cast“ objektu „dotyk“ informaci o tom, kterou stranou se testovaný objekt dotýká prvního objektu „ref_obj“. Pokud není žádný dotyk, hodnota proměnné „cast“ je nezměněná, tedy „nic“.

Druhá funkce, kterou si připravíme, nám umožňuje s předstihem zjišťovat kolizi dvou objektů. Tato funkce najde uplatnění při pohybu figurkou. Umožní nám zjistit blízkost objektu, vůči kterému pohybující figurku testujeme. Nejčastěji tak budeme zjišťovat blízkou přítomnost podlahy, abychom zajistili co nejtěsnější umístění figurky právě k objektu podlahy.

Funkce v minulém díle sice padající figurku správně zastavila v okamžiku, kdy se dostala k hranici podlahy, ale vzhledem k hodnotě posunutí, která byla nastavena na 5px se mohlo stát, že figurka zůstala „viset“ až 5px nad okrajem objektu podlahy.

Funkce pro detekci budoucí kolize vypadá takto:

fut_hit = function (ref_obj_2:Object, test_obj_2:Object, x_posuv:Number, y_posuv:Number) {
 dotyk_2 = new Object();
 dotyk_2.cast = "nic";
 sour_x_2 = test_obj_2._x+x_posuv;
 sour_y_2 = test_obj_2._y+y_posuv;
 sour_w_2 = test_obj_2._width;
 sour_h_2 = test_obj_2._height;
 for (a=1; a<test_obj_2._width; a++) {
  if (ref_obj_2.hitTest(sour_x_2+a, sour_y_2+sour_h_2, true)) {
   trace("dotyk spodní");
   dotyk_2.cast = "spodni";
  }
 }
 for (a=1; a<test_obj_2._width; a++) {
  if (ref_obj_2.hitTest(sour_x_2+a, sour_y_2, true)) {
   trace("dotyk horní");
   dotyk_2.cast = "horni";
  }
 }
 for (a=1; a<test_obj._height; a++) {
  if (ref_obj_2.hitTest(sour_x_2, sour_y_2+a, true)) {
   trace("dotyk levý");
   dotyk_2.cast = "leva";
  }
 }
 for (a=1; a<test_obj._height; a++) {
  if (ref_obj_2.hitTest(sour_x_2+sour_w_2, sour_y_2+a, true)) {
   trace("dotyk pravý");
   dotyk_2.cast = "prava";
  }
 }
 return dotyk_2;
};

Pokud se podíváme a porovnáme ji s předchozí funkcí, zjistíme, že se od sebe téměř neliší. První funkci pro jsme pouze obohatili o dvě proměnné, které určují již zmíněný posuv. Protože testujeme objekt vůči souřadnici, můžeme do testované souřadnice vložit i připadnou budoucí hodnotu, která zde představuje polohu objektu, ve které by se figurka nacházela.

Ona budoucí poloha je právě určena pomocí požadovaných proměnných „x_posuv“ a „y_posuv“. Tyto proměnné představují posuv objektu od jeho aktuální polohy.

Poslední funkce bude už přímo sloužit objektu figurky. Pomocí ní funkce zajistíme správné umisťování figurky na objekt podlahy v závislosti na vzájemné poloze obou objektů:

test_hit = function (ref_obj_3:Object, test_obj_3:Object, p_x:Number, p_y:Number) {
 test = fut_hit(ref_obj_3, test_obj_3, p_x*posuv, p_y*posuv);
 if (test.cast == "nic") {
  trace("nic");
  test_obj_3._x += p_x*posuv;
  test_obj_3._y += p_y*posuv;
 } else {
  tx = 1;
  test2 = fut_hit(ref_obj_3, test_obj_3, p_x*tx, p_y*tx);
  if (test2.cast == "nic") {
   do {
    test_obj_3._x += p_x*tx;
    test_obj_3._y += p_y*tx;
    test2 = fut_hit(ref_obj_3, test_obj_3, p_x*2, p_y*2);
   } while (test2.cast == "nic");
  }
 }
};

Jako počáteční proměnné opět požadujeme dva objekty, jeden referenční (objekt podlahy) a druhý testovaný (figurka). Dále potřebujeme znát znaménko posuvu, který chceme uskutečnit. Jedná se o určení směru, kterým se bude dále ubírat objekt figurky. Tyto hodnoty proměnných „p_x“ a „p_y“ jsou buď „-1“ nebo „+1“. V této funkci již využíváme připravenou funkci pro detekci budoucí kolize dvou objektů a podle výsledku buď posuneme objektem na další pozici a nebo, pokud jsme v blízkosti referenčního objektu (podlaha), zjemníme posuv na 1px.

Tímto dosáhneme posouvání objektu až na rozdíl 1px od objektu podlahy. Máme zaručeno, že se objekt nezastaví ve vzdálenosti 1-5px od kraje objektu podlahy. Nakonec už jen na začátek skriptu prvního snímku připíšeme hodnotu proměnné „posuv=5;“ abychom nastavili rychlost figurky.

Než ovšem vyzkoušíme nové funkce, musíme je vložit k objektu podlahy. Vybereme proto tento objekt a původní akce přepíšeme tímto skriptem:

onClipEvent (enterFrame) {
 if (Key.isDown(Key.LEFT) && Key.isDown(Key.DOWN)) {
  _root.test_hit(this, _root.obj, -1, 1);
 } else if (Key.isDown(Key.LEFT) && Key.isDown(Key.UP)) {
  _root.test_hit(this, _root.obj, -1, -1);
 } else if (Key.isDown(Key.RIGHT) && Key.isDown(Key.DOWN)) {
  _root.test_hit(this, _root.obj, 1, 1);
 } else if (Key.isDown(Key.RIGHT) && Key.isDown(Key.UP)) {
  _root.test_hit(this, _root.obj, +1, -1);
 } else if (Key.isDown(Key.RIGHT)) {
  _root.test_hit(this, _root.obj, 1, 0);
 } else if (Key.isDown(Key.LEFT)) {
  _root.test_hit(this, _root.obj, -1, 0);
 } else if (Key.isDown(Key.UP)) {
  _root.test_hit(this, _root.obj, 0, -1);
 } else {
  _root.test_hit(this, _root.obj, 0, 1);
 }
}

V události onEnterFrame pomocí funkce „test_hit()“ provádíme testování dotyku objektu figurky s objektem podlahy na hlavní scéně. Všimneme si hodnot značek posuvu a to především v té části, kde požadujeme pouze posuv v jednom směru. Zde ve směru, kde nechceme žádný pohyb, uvedeme hodnotu „0“ a objekt figurky tak testujeme v posunutí pouze jedním směrem.

Nyní už jen otestujeme výslednou animaci, která může vypadat takto. Zdrojový soubor dnešní ukázky je ke stažení zde.

Témata článku: Software, Programování, Elsa, Horn, Cast

1 komentář

Nejnovější komentáře

  • gully, gully 20. 2. 2006 9:08:31
    http://diskuse-zaciname-s-flash-mx-2004.wz.cz
reklama
Určitě si přečtěte

Vybíráte herní periferii nebo hardware? Pak zapomeňte na nálepku Gaming

Vybíráte herní periferii nebo hardware? Pak zapomeňte na nálepku Gaming

** Herní hardware se od toho běžného často liší jen vzhledem ** Při výběru stále nezapomínejte na základní parametry ** Poradíme jak vybrat herní hardware i periferie

20.  2.  2017 | Stanislav Janů | 36

10 nejhorších produktů v historii Microsoftu

10 nejhorších produktů v historii Microsoftu

20.  2.  2017 | Karel Javůrek | 141

AMD oficiálně představilo procesory Ryzen. Známe i jejich české ceny

AMD oficiálně představilo procesory Ryzen. Známe i jejich české ceny

** AMD uvedlo první tři procesory Ryzen 7 ** Všechny budou pracovat s osmi jádry a šestnácti vlákny ** Na pulty obchodů se dostanou už za týden

22.  2.  2017 | Stanislav Janů | 133

EU se děsí Windows 10. Prý o nás vědí až příliš. Microsoft chystá změny

EU se děsí Windows 10. Prý o nás vědí až příliš. Microsoft chystá změny

** Evropští úředníci chtějí, aby byly Desítky transparentnější ** Microsoft od jara skutečně chystá změny ** Ochráncům soukromí to ale nestačí

21.  2.  2017 | Jakub Čížek | 219

Remix Singularity: Microsoft si na tom vylámal zuby. Jak dopadne Android?

Remix Singularity: Microsoft si na tom vylámal zuby. Jak dopadne Android?

** Microsoft do svých telefonů integroval desktopové prostředí ** Moc to ale nevyšlo, chyběl pořádný výkon ** Teď to zkoušejí ex-googleři s Remix Singularity

23.  2.  2017 | Jakub Čížek | 74


Aktuální číslo časopisu Computer

Supertéma o počítačové bezpečnosti

AMD Ryzen přichází

Velké testy kinoprojektorů a levných špuntových sluchátek

Příslušenství do USB-C

reklama
reklama