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.
Umíme ve Flashi – 20. díl – detekce kolize II.

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
Určitě si přečtěte

Pojďme programovat elektroniku: Postavíme si titěrnou Wi-Fi meteostanici s lepším teploměrem než Netatmo

Pojďme programovat elektroniku: Postavíme si titěrnou Wi-Fi meteostanici s lepším teploměrem než Netatmo

** Dnes se podíváme na maličkou Wi-Fi destičku Wemos D1 mini ** A připojíme k ní barometrický a teplotní shield ** Poběží na ní web a nabídne i JSON API

18.  6.  2017 | Jakub Čížek | 27

Jak vybrat monitor k počítači: nenechte se zlákat nepodstatnými parametry

Jak vybrat monitor k počítači: nenechte se zlákat nepodstatnými parametry

** Na jaké parametry se zaměřit a kde vás výrobci chtějí nachytat ** Monitory se stále více specifikují pro konkrétní určení ** Náročný hráč nebo profesionální grafik mají různé požadavky

20.  6.  2017 | Tomáš Holčík | 31

Dlouhodobý test HTC Vive: co vám recenze o virtuální realitě neřeknou

Dlouhodobý test HTC Vive: co vám recenze o virtuální realitě neřeknou

** Ani hry se sebelepší grafikou vás nevtáhnou tolik, jako ve virtuální realitě ** Pro sledování filmů není VR ani zdaleka ideální ** I první generace je skvělá, stále však působí jako prototyp

20.  6.  2017 | Stanislav Janů | 19

Jak unikají informace o nových iPhonech? Třeba podprsenkami čínských pracovnic

Jak unikají informace o nových iPhonech? Třeba podprsenkami čínských pracovnic

** Na černém trhu mohou zaměstnanci továren za kradené součástky inkasovat částku ve výši ročního platu ** Velké množství informací je vyneseno i z centrály Applu ** Díly jsou pašovány v botách, podprsenkách i odpadem

21.  6.  2017 | Stanislav Janů | 20


Aktuální číslo časopisu Computer

Bojujeme proti Fake News

Dva velké testy: fotoaparáty a NASy

Co musíte vědět o změně evropského roamingu

Radíme s výběrem základní desky