Stránka sa načítava, prosím čakajte…
© 2005 – 2024 Roman Horváth, všetky práva vyhradené. Dnes je 4. 5. 2024.
Dátum: 25. 3. 2020, pred štyrmi rokmi
Ukážka jednej z možností ako implementovať mechanizmus kolízií. Toto je jedna z tých komplikovanejších možností, ale dúfame, že vďaka komentárom z nej čitateľ bude vedieť odvodiť aj zjednodušené verzie.
- Súbory na prevzatie 2,78 kB (2,72 KiB), 26. 3. 2020
Trieda Hra.java
~
import knižnica.*; public class Hra extends GRobot { /**## Takto označené komentáre súvisia s kolíziami. ##**/ private final Zoznam<Plošinka> plošinky = new Zoznam<>(); private final Zoznam<Guľôčka> guľôčky = new Zoznam<>(); private int čas = 0; // Interval na „generovanie“ nových guľôčok private Hra() { super(400, 600); Svet.nekresli(); if (Svet.prvéSpustenie()) { Svet.zbaľ(); Svet.vystreď(); } skry(); for (int i = 0; i < 8; ++i) nováPlošinka(i * 65); nováHra(); } public void nováPlošinka(int zvisláPoloha) { Plošinka plošinka = new Plošinka(); plošinka.polohaY(Svet.náhodnéReálneČíslo(-198, -202) + zvisláPoloha); plošinky.pridaj(plošinka); } public void nováHra() { Svet.nekresli(); for (Plošinka plošinka : plošinky) { plošinka.polohaX(0); plošinka.aktivuj(); } for (Guľôčka guľôčka : guľôčky) guľôčka.deaktivuj(); čas = 0; Svet.kresli(); } public void nováGuľôčka() { Guľôčka nováGuľôčka = null; for (Guľôčka guľôčka : guľôčky) if (guľôčka.neaktívny()) { nováGuľôčka = guľôčka; break; } if (null == nováGuľôčka) { nováGuľôčka = new Guľôčka(); guľôčky.pridaj(nováGuľôčka); } nováGuľôčka.náhodnáPoloha(); nováGuľôčka.polohaY(Svet.najväčšieY()); nováGuľôčka.rýchlosť(0, false); nováGuľôčka.aktivuj(); } @Override public void uvoľnenieKlávesu() { switch (ÚdajeUdalostí.kláves()) { case Kláves.VK_H: // Pauza. if (Svet.časovačAktívny()) Svet.zastavČasovač(); else Svet.spustiČasovač(); break; } } @Override public void tik() { if (0 == ++čas % 50) nováGuľôčka(); /**## Toto je hlavný cyklus detekcie kolízií medzi guľôčkami ##**/ /**## a plošinkami. ##**/ for (Guľôčka guľôčka : guľôčky) if (guľôčka.aktívny()) { // Kolízie kontrolujeme len pre aktívne guľôčky. for (Plošinka plošinka : plošinky) { // Rovnako len pre aktívne plošinky. if (plošinka.aktívny() && guľôčka.koliduje(plošinka)) { // Keď je kolízia potvrdená, tak upravíme vlastnosti // guľôčky tak, aby sme simulovali odrazenie sa od // pohybujúceho sa objektu… // (Plošinka sa pohybuje nerušene ďalej.) guľôčka.odskoč(guľôčka.rýchlosť() - (guľôčka.rýchlosť() < 0 ? -1 : 1)); guľôčka.rýchlosť(-0.75 * guľôčka.rýchlosť()); guľôčka.rýchlosťPosunu( plošinka.rýchlosťPosunu() / 2, false); guľôčka.zrýchleniePosunu(-0.1, false); guľôčka.zastavPoSpomaleníPosunu(); break; } } } /**## Tu by boli ďalšie detekcie kolízií. ##**/ } public static void main(String[] args) { Svet.použiKonfiguráciu("Hra.cfg"); new Hra(); } }
Trieda Guľôčka.java
~
import knižnica.*; public class Guľôčka extends GRobot { public Guľôčka() { // Oraničenie je upravené tak, aby guľôčka nesmela ani o kúsok // vyjsť za pravý alebo ľavý okraj. ohranič(Svet.najväčšieX() - veľkosť(), Svet.najväčšieY(), PLOT); zdvihniPero(); skoč(Svet.najväčšieY()); // (presun k hornému okraju) vpravo(180); // („čelom vzad“) najväčšiaRýchlosť(20); zrýchlenie(1); } /**## Táto metóda slúži na zistenie toho, či táto guľôčka koliduje ##**/ /**## so zadanou plošinkou. Metóda používa metódu z triedy Plošinka: ##**/ /**## bodVPlošinke. ##**/ public boolean koliduje(Plošinka plošinka) { // Postupne skontrolujeme 12 bodov po obvode guľôčky. (Používame // celočíselný uhol u, pretože to na tieto účely stačí.) for (int u = 0; u < 360; u += 30) { // Poloha guľôčky je bod v jej strede. Ten prevezmeme: Bod bod = poloha(); // A prepočítame ho podľa uhla u tak, aby ležal na obvode // guľôčky: bod.posuňVSmere(u, veľkosť()); // Overenie, či sa bod ležiaci na obvode guľôčky nachádza // vo vnútri plošinky (detaily tohto overenia si určuje // plošinka): if (plošinka.bodVPlošinke(bod)) return true; } return false; } @Override public void kresliTvar() { krúžok(); } @Override public void aktivácia() { zobraz(); } @Override public void deaktivácia() { rýchlosťPosunu(0, false); zrýchleniePosunu(0, false); skry(); } @Override public void mimoHraníc() { // Vtedy a len vtedy, keď guľôčka prepadne pod spodnú hranicu sa // deaktivuje… if (polohaY() < Svet.najmenšieY() + veľkosť()) deaktivuj(); } }
Trieda Plošinka.java
~
import knižnica.*; public class Plošinka extends GRobot { private int šírka; public Plošinka() { this(50); // Volanie „toho druhého“ konštruktora (nižšie). } public Plošinka(int šírka) { this.šírka = šírka; ohranič(ODRAZ); zdvihniPero(); rýchlosťPosunu(Svet.náhodnéReálneČíslo(-6, 6), false); mimoHraníc(); } /**## Táto metóda slúži na rýchle overenie prítomnosti bodu ##**/ /**## v plošinke, ktorej sme definovali vlastnú šírku (nevyužili ##**/ /**## sme preddefinovanú vlastnosť robota pomer). ##**/ public boolean bodVPlošinke(Poloha bod) { // V guľôčke (v metóde koliduje) je spomínané, že „detaily overenia // (kolízie) si určuje plošinka.“ Toto je ten detail a je veľmi // prostý – len zistenie, či zadaný bod (ktorý posielame z metódy // koliduje v triede Guľôčka) leží v obdĺžniku plošinky (alebo nie): return bodVObdĺžniku(bod, šírka, veľkosť()); } // („Patrilo by sa“ sem doprogramovať aj metódy na čítanie a zápis // šírky, ktorú momentálne nastavujeme iba jednorazovo prostredníctvom // konštruktora, pretože to je v súlade so zásadami OOP.) @Override public void kresliTvar() { obdĺžnik(šírka, veľkosť()); } @Override public void aktivácia() { priehľadnosť(1.0); } @Override public void deaktivácia() { priehľadnosť(0.25); } @Override public void mimoHraníc() { // Pri kontakte s hranicou (pravou alebo ľavou, keďže sa pohybujeme // len doprava a doľava) sa upraví rýchlosť posunu a zmení (obráti) // smer pohybu plošinky. rýchlosťPosunu(-rýchlosťPosunu() * Svet.náhodnéReálneČíslo(.75, 1.5)); if (rýchlosťPosunu() > 0) { if (rýchlosťPosunu() > 6) rýchlosťPosunu(6); else if (rýchlosťPosunu() < 2) rýchlosťPosunu(2); } else { if (rýchlosťPosunu() < -6) rýchlosťPosunu(-6); else if (rýchlosťPosunu() > -2) rýchlosťPosunu(-2); } } }
Ukážka „hry“ po spustení.