41. Zrážky

Rozšírenie action26; programy začínajú riadkom ;@modern (kapitola 35). Nadväzuje na kapitolu 40.

Na čo to je

Hra potrebuje vedieť, či strela trafila, či loď narazila do steny alebo do nepriateľa. Atari to vie samo: obvod GTIA si pri kreslení každého obrazu zapisuje, ktorý hráč alebo strela sa prekryl s ktorým hráčom a s ktorou farbou obrázka. Program tieto zrážky (collisions) len prečíta.

Druhá možnosť je spočítať zrážku v programe z polôh a rozmerov objektov. Obe majú svoje výhody – tento program ukazuje obe naraz.

Program: kameň padá na loď

Súbor examples/pm-hit.act:

Action!
;@modern
; A rock falls on a ship: a collision from the hardware and from PMOverlap

BYTE ARRAY ship=[$18 $3C $7E $FF $FF $DB $81 $81],
           rock=[$3C $7E $FF $FF $FF $FF $7E $3C]

PROC Main()
  BYTE y, hw=[0], sw=[0]

  PMGraphics(1)
  PMCreate(0, ship, 8, 1, 120, 180)   ; the ship at the bottom
  PMCreate(1, rock, 8, 1, 120, 100)   ; the rock above it
  PMColor(0, 1, 12)
  PMColor(1, 2, 6)
  PMWait()
  HitClr()

  FOR y=101 TO 190
  DO
    PMWait()                          ; the rock at y-1 is on the screen now
    IF hw=0 AND PMHitPM(1)&1 THEN     ; player 1 met player 0
      hw=y-1
    FI
    HitClr()
    PMVPos(1, y)                      ; the rock one row lower
    IF sw=0 AND PMOverlap(0, 1) THEN  ; the rectangles overlap at once
      sw=y
    FI
  OD

  Print("PMOverlap: the rock hit the ship at y=")
  PrintBE(sw)
  Print("Hardware:  the rock hit the ship at y=")
  PrintBE(hw)
RETURN

Preklad a spustenie

action26 pm-hit.act --sim
PMOverlap: the rock hit the ship at y=173
Hardware:  the rock hit the ship at y=0

Simulátor nemá obvod GTIA, preto hardvér v ňom zrážku nehlási (0). V emulátore (--run) vypíše program oba riadky s y=173: kameň v riadkoch 173–180 sa dotkne lode v riadku 180.

Ako to funguje

Zrážky z hardvéru:

RutinaVráti
PMHitPM(n)bity 0–3: s ktorými hráčmi sa objekt n zrazil (bit 0 = hráč 0, hodnota 1; bit 1 = hráč 1, hodnota 2 …)
PMHitPF(n)bity 0–3: s ktorými farbami obrázka (playfield 0–3) sa objekt n zrazil
PMHit(n, c)1 alebo 0: c 0–3 je hráč, 4–7 farba obrázka 0–3 (ako v Tool Kite)
HitClr()všetky zrážky vynuluje

PMHitPM(1)&1 je teda „hráč 1 narazil do hráča 0“. Rovnako by platilo PMHitPM(0)&2 – zrážku hráčov hlási hardvér u oboch.

Dve pravidlá hardvérových zrážok:

  1. Bity sa len pridávajú. Raz nastavený bit ostane, kým program nezavolá HitClr(). Bez neho by jeden náraz platil navždy.
  2. Zrážka sa zistí až pri kreslení. Hneď po PMVPos registre ešte hovoria o starej polohe. Preto slučka robí vždy to isté: počkaj na obraz (PMWait) → prečítaj → HitClr → pohni. Program si preto pamätá y-1 – zrážku našiel obraz, v ktorom bol kameň ešte o riadok vyššie.

Zrážka z programu: PMOverlap(a, b) vráti 1, keď sa prekrývajú obdĺžniky dvoch objektov (poloha, šírka a počet riadkov tvaru, ktoré si runtime pamätá). Funguje hneď po pohybe, aj pre neviditeľný objekt a aj pre dve strely (hardvér zrážku strely so strelou nepozná). Je to však len obdĺžnik: prázdne rohy tvaru sa rátajú tiež. Hardvér naopak hlási len skutočne nakreslené body.

Zrážky s obrázkom a strely

PMHitPF(n) hlási, do ktorej farby obrázka objekt narazil. Pozor na textový režim: písmená v GRAPHICS 0 sa hlásia ako farba 2 (hodnota 4), hoci ich farbu nastavuje SetColor(1, …):

Action!
IF PMHitPF(4)&4 THEN    ; strela 0 (objekt 4) narazila do textu
  PMClear(4)
FI

Strely sú objekty 4–7. Tvar strely sú dva spodné bity každého bajtu ([1 1 1] – úzka, [3 3 3] – široká) a strela má farbu svojho hráča:

Action!
BYTE ARRAY shot=[1 1 1 1]
PMCreate(4, shot, 4, 1, x+3, 170)   ; strela 0 z lode
PMVPos(4, sy)                       ; letí hore
IF PMHitPM(4)&2 THEN …              ; strela 0 trafila hráča 1

Celá hra so strelou, textom a životmi je lekcia examples/modern/collide.act.

Na čo si dať pozor

Časté chyby

Čo sa staloPrečo
zrážka platí stále, aj keď sa objekty už rozišlichýba HitClr()
zrážka sa nezistí, hoci sa objekty prekrývajúčítaš hneď po pohybe, nie po PMWait()
zrážka s textom sa nehlási pri PMHitPF(n)&2text v GRAPHICS 0 je farba 2: &4
PMOverlap hlási zrážku o kúsok skôrráta obdĺžniky, nie body

Vyskúšaj si

  1. Posuň kameň v programe na x=126 (len dva stĺpce nad pravým okrajom lode). Kedy nahlási zrážku PMOverlap a kedy hardvér?
  2. Daj lodi strelu: PMCreate(4, shot, 4, 1, 123, 175) a v slučke ju posúvaj hore. Kedy ju zastaví PMHitPM(4)&2?
  3. Vypíš na obrazovku riadok textu a nechaj kameň padať cez neho. Zistí to PMHitPF(1)?

Zhrnutie

Podrobnejšie: lekcia 46 examples/modern/collide.act, ukážka examples/pmgM.act.

Späť: 40. Hráči a strely · Ďalej: 42. Viac objektov, banky a menu