4.5. tēma: Sadursmju noteikšanas (Collision detection) pamati

Tavs šīs stundas izaicinājums: 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.

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!

1. uzdevums: Objektu robežu nolasīšana

Iemācīties iegūt precīzas elementu koordinātas un izmērus no HTML lapas.

Izpildes soļi:

  1. Sava JS faila apakšā izveido jaunu funkciju function parbauditSadursmi() { ... }.
  2. Funkcijas iekšienē iegūsti abu elementu (varoņa un ienaidnieka) "kastes" datus:
    let varonisKaste = varonisObj.getBoundingClientRect();
    let ienaidnieksKaste = ienaidnieksObj.getBoundingClientRect();
  3. Izvadi konsolē varoņa datus, lai saprastu, kā tie izskatās: console.log(varonisKaste.left, varonisKaste.top);.

2. uzdevums: Sadursmes loģikas algoritms (If)

Uzrakstīt milzu "If" nosacījumu, kas pārbauda visu četru malu pārklāšanos.

Izpildes soļi:

  1. Funkcijā dzēs console.log un pievieno sekojošu nosacījumu:
    if (varonisKaste.left < ienaidnieksKaste.right && varonisKaste.right > ienaidnieksKaste.left && varonisKaste.top < ienaidnieksKaste.bottom && varonisKaste.bottom > ienaidnieksKaste.top) { ... }
  2. Šī bloka iekšienē ieraksti kodu, kas notiek sadursmes brīdī, piemēram: alert("Sadursme!");.
  3. Pārbaudi kodu manuāli: pārvieto varoni ar bultiņām, līdz tas pieskaras ienaidniekam, un manuāli izsauc parbauditSadursmi() konsolē. Vai "alert" parādās?

3. uzdevums: Sadursmes pārbaude reāllaikā (Spēles ciklā)

Ievietot sadursmes pārbaudi spēles ciklā, lai tā notiktu automātiski, bez apstājas.

Izpildes soļi:

  1. Atrodi savu iepriekšējā stundā izveidoto spēles ciklu (setInterval, kurā kustas ienaidnieks vai krīt laiks).
  2. Ievieto parbauditSadursmi(); funkcijas izsaukumu tieši šī cikla (intervāla) iekšpusē. Tagad pārlūks pārbaudīs sadursmi 50 reizes sekundē!
  3. Nomaini kaitinošo alert pret kaut ko elegantāku: samazini spēlētāja dzīvības vai izsauc funkciju clearInterval(), lai apstādinātu spēli ("Game Over"). Veic Commit un Push uz GitHub.

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 ➡