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

Špičkoví hackeři útočili na prohlížeče. Chrome odolal, ale Edge je tragédie

Špičkoví hackeři útočili na prohlížeče. Chrome odolal, ale Edge je tragédie

** Do Vancouveru se sjeli hackeři ** Soutěžili v útocích na prohlížeče ** Chrome odolal, ale Edge to projel na celé čáře

22.  3.  2017 | Jakub Čížek | 79

Pojďme programovat elektroniku: Meteostanice, která bude díky Sigfoxu posílat stav počasí třeba z vrcholu Sněžky

Pojďme programovat elektroniku: Meteostanice, která bude díky Sigfoxu posílat stav počasí třeba z vrcholu Sněžky

** Příští roky budou ve znamení internetu věcí ** Podívali jsme se podrobně na síť Sigfox ** Takhle s ní komunikují krabičky z celé Evropy

19.  3.  2017 | Jakub Čížek | 18

Kde nejlevněji uložit 1 TB dat: Srovnali jsme aktuální ceny cloudových úložišť

Kde nejlevněji uložit 1 TB dat: Srovnali jsme aktuální ceny cloudových úložišť

** Srovnali jsme známá cloudová úložiště podle toho, kolik měsíčně zaplatíte za 1TB ** Ceny se pohybují od dvou stovek až po tisíc korun ** Google umožní uložit až 30 TB dat

18.  3.  2017 | Stanislav Janů | 115

Obří Mechroboti jsou realitou, měří čtyři metry a mají hmotnost přes 1,5 tuny

Obří Mechroboti jsou realitou, měří čtyři metry a mají hmotnost přes 1,5 tuny

** Jihokorejská společnost Hankook Mirae Technology vyrábí obří Mechroboty ** Jsou určené pro ovládání člověkem uvnitř ** V prodeji se objeví koncem tohoto roku za 200 milionů korun

20.  3.  2017 | Karel Javůrek | 18


Aktuální číslo časopisu Computer

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

AMD Ryzen přichází

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

Příslušenství do USB-C