Stránka sa načítava, prosím čakajte…
© 2005 – 2024 Roman Horváth, všetky práva vyhradené. Dnes je 24. 4. 2024.
Dátum: 1. 8. 2020, pred štyrmi rokmi
Zadanie
Naprogramujte jednoduchú hru, v ktorej sa bude na obrazovke (plátne) pohybovať množstvo bublín, ktoré bude mať hráč za úlohu čo najrýchlejšie popraskať ihlou.
Požiadavky:
- Praskanie musí hráč realizovať nejakou akciou (nesmie ísť o pasívne praskanie len pohybom kurzora myši), napríklad klikaním tlačidiel myši.
- Bubliny sa musia odrážať od okrajov obrazovky (plátna) podľa zákona rovnosti uhlov odrazu a dopadu.
- Bublina sa pri ohrození ihlou bude usilovať robiť únikové manévre.
Bonusová požiadavka:
- Nech je efekt prasknutia bubliny sprevádzaný krátkou animáciou.
Riešenie
~
import knižnica.*; /** * Trieda slúžiaca na spúšťanie aplikácie. */ public class HlavnáTrieda extends GRobot { // Zoznam všetkých bublín. private final static Zoznam<Bublina> bubliny = new Zoznam<>(); // Atribút slúžiaci na uchovanie položky ponuky „Nová hra.“ private final PoložkaPonuky nováHra; /** * Konštruktor inicializujúci aplikáciu. */ private HlavnáTrieda() { // Vykonanie niekoľkých úvodných nastavení (úprava veľkosti plátna, // skrytie hlavného robota…). super(400, 400, "Bubliny"); Svet.zbaľ(); skry(); Svet.nekresli(); // Vytvorenie všetkých bublín: for (int i = 0; i < 50; ++i) bubliny.pridaj(new Bublina()); // Pridanie položky „Nová hra“ do ponuky: nováHra = Svet.pridajPoložkuPonuky("Nová hra", Kláves.VK_N, Kláves.VK_N); // Dokončenie nastavení (úprava tvaru kurzora a spustenie novej hry). zmeňKurzorMyši(); nováHra(); } // Spustenie novej hry. private void nováHra() { Svet.nekresli(); for (Bublina bublina : bubliny) bublina.aktivuj(false); Svet.kresli(); Svet.spustiČasovač(); } /** * Reakcia na voľbu položky ponuky „Nová hra“ – potvrdzujúcou otázkou * a spustením novej hry v prípade kladnej odpovede. */ @Override public void voľbaPoložkyPonuky() { if (nováHra.aktivovaná() && ÁNO == Svet.otázka("Spustiť novú hru?")) nováHra(); } // Úprava tvaru kurzora myši. private void zmeňKurzorMyši() { // Vytvorenie (transparentného) obrázka, ktorý bude použitý na // nakreslenie a definíciu nového kurzora myši: Obrázok ihla = new Obrázok(32, 32); // Kreslenie ihly (do obrázka): kresliDoObrázka(ihla); hrúbkaČiary(2.5); farba(tyrkysová); choďNa(-16, -16); domov(); farba(modrá); kruh(4.5); // Definícia nového kurzora myši a jeho aktivácia: Svet.novýKurzorMyši(ihla, -15, -15, "ihla"); Svet.zmeňKurzorMyši("ihla"); } /** * Metóda slúžiaca na spúšťanie aplikácie. * * @param args parametre prijaté z konzoly */ public static void main(String[] args) { new HlavnáTrieda(); } }
Bublina » |
~
import knižnica.*; /** * Trieda implementujúca bublinu. */ public class Bublina extends GRobot { // Tvar bubliny je prostý krúžok s polomerom rovným veľkosti bubliny. private final static KreslenieTvaru tvar = r -> r.krúžok(); // Atribút používaný na počítanie za sebou nasledujúcej série odrazov, // čím sa dá detegovať uviaznutie. private int početOdrazov = 0; /** * Konštruktor bubliny. (Nastaví všetky jej požadované vlastnosti.) */ public Bublina() { vlastnýTvar(tvar); zdvihniPero(); hrúbkaČiary(1.75); farba(svetlotyrkysová); unikaj(); } /** * Metóda rezervovaná na implementáciu únikového manévra bubliny pri * ohrození ihlou. Momentálne je manéver veľmi jednoduchý: bublina * náhodne zmení smer a náhodne upraví svoju rýchlosť v rozmedzí ⟨5; 10⟩. */ public void unikaj() { náhodnýSmer(); rýchlosť(Svet.náhodnéCeléČíslo(5, 10), false); } /** * Metóda slúžiaca na vykonanie odrazenia sa bubliny od vodorovnej steny. */ public void odrazSaVodorovne() { uhol(360 - uhol()); dopredu(rýchlosť()); } /** * Metóda slúžiaca na vykonanie odrazenia sa bubliny od zvislej steny. */ public void odrazSaZvislo() { uhol(180 - uhol()); dopredu(rýchlosť()); } /** * Reakcia na stlačenie tlačidla myši – overí, či je bublina aktívna, či * sa kurzor myši nachádza v bubline a či bolo stlačené ľavé tlačidlo * myši. Ak sú všetky podmienky splnené, bublina praskne. */ @Override public void stlačenieTlačidlaMyši() { if (aktívny() && myšVKruhu() && ÚdajeUdalostí.tlačidloMyši(ĽAVÉ)) { Puk.pukni(this); deaktivuj(); } } /** * Reakcia na aktiváciu bubliny (presunie bublinu na náhodné miesto, * náhodne zmení jej veľkosť a zobrazí ju). */ @Override public void aktivácia() { náhodnáPoloha(); veľkosť(Svet.náhodnéCeléČíslo(8, 22)); zobraz(); } /** * Reakcia na deaktiváciu bubliny (skryje bublinu). */ @Override public void deaktivácia() { skry(); } // Súkromná metóda slúžiaca na odrazenie sa bubliny od okraja a zároveň // pomáhajúca pri detekcii uviaznutia bubliny. // // @return návratová hodnota true signalizuje, že sa bublina odrazila private boolean odrazilaSa() { if (polohaY() + veľkosť() > Svet.hornýOkraj() || polohaY() - veľkosť() < Svet.spodnýOkraj()) { odrazSaVodorovne(); return true; } else if (polohaX() + veľkosť() > Svet.pravýOkraj() || polohaX() - veľkosť() < Svet.ľavýOkraj()) { odrazSaZvislo(); return true; } return false; } /** * Vykonávanie činností počas aktívneho stavu bubliny. */ @Override public void aktivita() { if (myšVKruhu()) unikaj(); // Nasledujúci mechanizmus slúži na detekciu uviaznutia bubliny // a jej vyslobodenie: if (odrazilaSa()) { if (odrazilaSa()) { if (++početOdrazov > 5) náhodnáPoloha(); } else početOdrazov = 0; } } }
« Hlavná trieda | Puk » |
~
import knižnica.*; /** * Trieda implementujúca autonómny efekt puknutia bubliny. */ public class Puk extends GRobot { // Tvar puku je osmica lúčov rovnomerne rozmiestnených v kruhu // vzdialených od stredu o vzdialenosť rovnú aktuálnej veľkosti puku. private final static KreslenieTvaru tvar = r -> { for (int i = 0; i < 8; ++i) { r.vpravo(45); r.skoč(r.veľkosť()); r.dopredu(10); r.odskoč(10 + r.veľkosť()); } }; // Zoznam všetkých pukov. private final static Zoznam<Puk> puky = new Zoznam<>(); // Atribút uchovávajúci si pôvodnú hodnotu veľkosti bubliny, ktorej // prasknutie tento puk animuje. private double veľkosť; /** * Konštruktor prijímajúci inštanciu bubliny, ktorej prasknutie má * tento puk animovať. * * @param bublina bublina, ktorej prasknutie bude tento puk animovať */ public Puk(Bublina bublina) { vlastnýTvar(tvar); zdvihniPero(); hrúbkaČiary(1.75); farba(svetlotyrkysová); reset(bublina); } /** * Resetne puk podľa zadanej bubliny. (To jest bubliny, ktorej prasknutie * má animovať.) * * @param bublina bublina, ktorej prasknutie bude tento puk animovať */ public void reset(Bublina bublina) { skočNa(bublina); smer(bublina); rýchlosť(bublina.rýchlosť(), false); veľkosť(veľkosť = bublina.veľkosť() - 5); aktivuj(10, false); } /** * Reakcia na aktiváciu puku (zobrazí ho). */ @Override public void aktivácia() { zobraz(); } /** * Reakcia na deaktiváciu puku (skryje ho). */ @Override public void deaktivácia() { skry(); } /** * Vykonávanie činností počas aktívneho stavu puku. */ @Override public void aktivita() { veľkosť(veľkosť + 10 - trvanieAktivity()); } /** * Statická metóda hľadajúca neaktívny puk alebo vyrábajúca nový puk, ak * nejestvuje žiadny neaktívny puk. Nájdený alebo vyrobený puk sa aktivuje * pre zadanú bublinu. (To jest pre bublinu, ktorej prasknutie má * animovať.) * * @param bublina bublina, ktorej prasknutie má nájdený (alebo vyrobený) * puk animovať */ public static void pukni(Bublina bublina) { // Hľadanie neaktívneho puku: for (Puk puk : puky) if (puk.pasívny()) { // Ak je nájdený, aktivuje (resetne) sa podľa zadanej bubliny // a vykonávanie metódy sa skončí: puk.reset(bublina); return; } // Ak nie je nájdený žiadny neaktívny puk, tak sa vyrobí nový, ktorý // sa automaticky aktivuje pre zadanú bublinu): Puk puk = new Puk(bublina); puky.pridaj(puk); } }
« Bublina |
Výsledok
Ukážka vzhľadu hry tesne pred ukončením.
Návrhy na zlepšenia
- Detekcia ukončenia hry a zobrazenie víťaznej správy.
- Obnovovanie bublín po určitom dostatočne dlhom časovom intervale (aby mal hráč motiváciu pracovať rýchlo a zároveň aby mal šancu na úspešné dokončenie hry).
- Ukladanie aktuálneho stavu hry do konfigurácie.