›_ ebskola.lv
← 4.4 4.6 →

4.5 Sadursmju noteikšanas (Collision detection) pamati

Stundas uzdevums: Izstrādāt matemātisku algoritmu, kas reāllaikā pārbauda, vai divi spēles elementi (piemēram, spēlētājs un šķērslis) ekrānā pārklājas, un atbilstoši reaģēt.

2.6.1. Izstrādā komplicētas darbības un algoritmus; 5.2.1. Definē problēmas būtību un risina kompleksus izaicinājumus.

70 min darba sadalījums: 1. uzdevums (~20 min) - atjauno teorijas piemēru vai minimālo prototipu; 2. uzdevums (~25 min) - pielieto to galvenajā uzdevumā; 3. uzdevums (~25 min) - pārbaudi rezultātu, izlabo kļūdas un tikai beigās pieraksti vienu secinājumu. Papildus/4. līmeņa uzdevums ir paredzēts tikai tad, ja pamatdarbs ir pabeigts.

Pirms sāc: izmanto iepriekš apgūto un šīs lapas teorijas/koda piemērus. Ja vajadzīga jauna komanda vai rīks, vispirms atrodi tās paraugu teorijas sadaļā.

Teorija: Kā dators redz sadursmi?

Dators neskatās uz tavu uzzīmēto varoni kā uz cilvēku. Tas redz tikai kastes (taisnstūrus). Divas kastes saduras TIKAI TAD, ja vienlaicīgi izpildās četri nosacījumi:

Tīmekļa pārlūkprogrammās ir iebūvēts ģeniāls rīks getBoundingClientRect(), kas uzreiz iedod elementa X un Y koordinātas, kā arī tā platumu un augstumu, padarot šo matemātiku daudz vieglāku!

Praktiskie uzdevumi

1. uzdevums - Iesildies ar gatavu piemēru

Šis ir īss iesildīšanās uzdevums. Nokopē sagatavi, ielīmē to pareizajā koda vietā un palaid. Šeit pietiek droši izmēģināt tēmu 4.5 Sadursmju noteikšanas (Collision detection) pamati; detalizētu izpratni veidosi nākamajos uzdevumos.

Kopējamais piemērs vai sagatave: izmanto šo bloku kā starta punktu, nevis kā gala risinājumu.

<section class="iesildisanas-demo">
  <h2>4.5 Sadursmju noteikšanas (Collision detection) pamati</h2>
  <p id="rezultats">Sākuma teksts</p>
  <button id="poga">Pārbaudīt</button>
</section>
.iesildisanas-demo {
  padding: 16px;
  border: 2px solid #FFB142;
  border-radius: 6px;
}

.iesildisanas-demo button {
  cursor: pointer;
}
const rezultats = document.querySelector("#rezultats");
const poga = document.querySelector("#poga");

poga.addEventListener("click", () => {
  rezultats.textContent = "Kods darbojas: 4.5 Sadursmju noteikšanas (Collision detection) pamati";
});
  1. Atver darba failu vai rīku. Sagataves ievieto atbilstošajos projekta failos: index.html, style.css un script.js.
  2. Nokopē visu piemēra bloku no šī uzdevuma un ielīmē to norādītajā vietā.
  3. Palaid kodu tieši tādu, kāds tas ir, un pārliecinies, ka parādās rezultāts, izvade vai vismaz nav kļūdas paziņojuma.
  4. Atrodi vienu drošu vietu, ko drīkst mainīt: tekstu, skaitli, krāsu, mainīgā vērtību vai testa ierakstu.
  5. Maini tikai šo vienu vērtību un palaid kodu vēlreiz.
  6. Salīdzini rezultātu pirms un pēc izmaiņas. Ja parādās kļūda, atcel pēdējo izmaiņu un palaid vēlreiz.
  7. Turpini pie 2. uzdevuma tikai tad, kad šis mazais piemērs darbojas.

2. uzdevums - Ievieto algoritmu projektā

Pievieno šīs stundas paņēmienu kā nelielu, lietotājam redzamu projekta daļu.

  1. Atver script.js un pievieno sadursmju pārbaudes funkciju, kas izmanto getBoundingClientRect() uz spēlētāja un ienaidnieka elementiem.
  2. Funkcijā pārbaudi četrus nosacījumus: vai kāda no malām neatrodas ārpus otras kastes - ja visas četras neizpildās, tad ir sadursme.
  3. Izsauc parbauditSadursmi() no spelesCikls() katru kadru.
  4. Ja funkcija atgriež true, izsauc beigtSpeli().
  5. Saglabā un atver pārlūkā - sāc spēli un pievirzī spēlētāju pie ienaidnieka.
  6. Pārbaudi, ka spēle beidzas tiklīdz elementi tiekas.
  7. Salabo, ja sadursme netiek noteikta - pārliecinies, ka abi elementi ir ar position: absolute.
  8. Veic git commit -m "Add AABB collision detection".

3. uzdevums - Testē kodu un izdari secinājumu

Pārbaudi, vai algoritms darbojas paredzami vairākās situācijās.

  1. Sāc spēli un pievirzī spēlētāju pie ienaidnieka - pārbaudi, ka "Spēle beigusies" parādās.
  2. Pievieno console.log(parbauditSadursmi()) un pārbaudi konsolē, ka true parādās tikai sadursmē.
  3. Novieto spēlētāju tālu - pārbaudi, ka spēle turpinās bez kļūdas.
  4. Pārbaudi, ka pēc beigtSpeli() cikls ir apstājies un vairs netiek pārbaudītas sadursmes.
  5. Salabo, ja funkcija atgriež nepareizu rezultātu - pārbaudi getBoundingClientRect() izsaukumu laiku.
  6. Pievieno vizuālu efektu sadursmē: uz 0.5 sekundēm spēlētājam background: red.
  7. Pieraksti vienu secinājumu: ko nozīmē "AABB" un kāpēc tas ir vienkāršākais sadursmju veids.

Papildu uzdevums - Pievieno mazu funkciju

Ja pamatdarbs ir pabeigts, paplašini projektu ar vienu nelielu programmētu uzlabojumu.

  1. Pievieno otro ienaidnieku <div id="ienaidnieks2"> ar citu sākuma pozīciju laukumā.
  2. Paplašini parbauditSadursmi(), lai pārbauda arī otro ienaidnieku.
  3. Pievieno otrajam ienaidniekam vertikālu kustību (mainās Y koordināte, nevis X).
  4. Atver pārlūkā - pārbaudi, ka sadursme ar jebkuru ienaidnieku beidz spēli.
  5. Pārbaudi, ka abi ienaidnieki kustas neatkarīgi viens no otra.
  6. Veic git commit -m "Add second enemy with collision".
  7. Demonstrē klasesbiedram - vai viņš var izvairīties no abiem ienaidniekiem vienlaikus?

Biežākās kļūdas (un kā tās labot):

Koda piemērs

function parbauditSadursmi() {
    // 1. Iegūstam abu elementu kastes (izveidojot 'taisnstūrus' atmiņā)
    let speletajs = document.getElementById("speletajs").getBoundingClientRect();
    let skerslis = document.getElementById("ienaidnieks").getBoundingClientRect();

    // 2. AABB Sadursmes matemātika (vai tie PĀRKLĀJAS?)
    if (
        speletajs.left < skerslis.right &&
        speletajs.right > skerslis.left &&
        speletajs.top < skerslis.bottom &&
        speletajs.bottom > skerslis.top
    ) {
        // SADURSME IR NOTIKUSI!
        console.log("BOOM! Spēle beigusies.");
        document.getElementById("status").innerText = "GAME OVER";
        
        // Šeit parasti aptur spēles dzinēju
        // clearInterval(spelesCiklsID);
    }
}

// 3. Spēles dzinējs, kas kustina lietas un vienmēr pārbauda sadursmes
let spelesCiklsID = setInterval(function() {
    // Kustinām ienaidnieku...
    // Atjauninām laiku...
    
    // Un katru kadru pārbaudām, vai neesam saskrējušies!
    parbauditSadursmi(); 
}, 20); // 20 milisekundes = 50 FPS
Tagad tava spēle ir kļuvusi reāla – tā saprot, kad objekti saskaras, un spēj paziņot par uzvaru vai zaudējumu!
⬅ Iepriekšējā stunda Nākamā stunda ➡