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

Operační systém běžným počítačům nedal Bill Gates, ale Gary Kildall

Operační systém běžným počítačům nedal Bill Gates, ale Gary Kildall

** Gary Kildall pochopil, že levné výpočetní čipy mohou posloužit jako univerzální počítače pro všechny ** Připravil pro ně proto první operační systém ** Později mu systém vyfoukl Microsoft a nazval ho MS DOS

23.  4.  2017 | Pavel Tronner | 56

Umělá inteligence je sice v plenkách, už teď ale přestáváme rozumět, jak vlastně funguje. To je problém

Umělá inteligence je sice v plenkách, už teď ale přestáváme rozumět, jak vlastně funguje. To je problém

** Už je to tady, lidé přestávají chápat počítače ** Systémy neuronových sítí začínají pracovat tak, že ani jejich tvůrci přesně neví, co se uvnitř děje ** Do budoucna to může být závažný problém

24.  4.  2017 | Jakub Čížek | 112

Před 35 lety měl premiéru legendární počítač ZX Spectrum. Připomeňte si „Gumáka“

Před 35 lety měl premiéru legendární počítač ZX Spectrum. Připomeňte si „Gumáka“

** Slavný osmibitový počítač Sinclair ZX Spectrum byl uveden právě před 35 lety ** Připomeňte si tento průkopnický počítač v tematických článcích ** Podívejte se, jak funguje dnes

23.  4.  2017 | Pavel Tronner | 13

Správný počítač má alespoň dva monitory. Anebo je to jinak?

Správný počítač má alespoň dva monitory. Anebo je to jinak?

** David si nedokáže představit práci bez dvou a více monitorů ** Kubovi naopak stačí jeden a ve více displejích se ztrácí ** Jaký přístup je lepší?

23.  4.  2017 | Jakub Čížek | 59

Brněnské soudy daly stop Uberu. Je to dobře, nebo krok zpět?

Brněnské soudy daly stop Uberu. Je to dobře, nebo krok zpět?

** Před několika měsíci začal Uber nabízet své služby i v Brně ** Nyní ale narazil, soudům se to totiž nelíbí ** Má sdílená ekonomika dostat zelenou?

22.  4.  2017 | Jakub Čížek | 28


Aktuální číslo časopisu Computer

První test AMD Ryzen

Velké testy: 22 powerbank a 8 bezdrátových setů

Radíme s koupí Wi-Fi routeru

Co dokáží inteligentní domy?