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: 26. 10. 2013, pred viacerými rokmi, aktualizované: 31. 7. 2020, pred štyrmi rokmi
Tento projekt ukazuje definície tried dvoch typov postavičiek s vlastnou fyzikou. Projekt je postavený na báze programovacieho rámca grafického robota. Viac podrobností nájdete v Javadoc komentároch jednotlivých tried.
Okno aplikácie tesne po spustení. (Obidve postavičky sa prekrývajú.)
Kročko prešiel mierne hore a doprava. Skočko je práve aktívny.
Zdrojové súbory projektu na prevzatie: postavicky.7z
4,43 kB (4,33 KiB), 31. 7. 2020
~
import knižnica.*; /** * V tomto ukážkovom projekte sú naprogamované dve postavičky s odlišným * správaním. Medzi ovládaním jednej a druhej sa dá prepínať kliknutím myši. * Keď je jedna postavička aktívna, druhá je deaktivovaná (a „zmrazená“). * To je indikované ich farbou (a miernou zmenou grafiky): čierna znamená * aktivitu, šedá neaktívnosť. * * Obe sú (v prípade, že sú aktívne) ovládané kurzorovými šípkami, ale každá * z nich akoby jestvovala v odlišnom svete. * * Jedna je skákajúca (skočko) – pohybuje sa do strán, skáče a vplyvom * gravitácie padá smerom nadol (až po spodný okraj viditeľnej časti plátna). * * Druhá sa pohybuje po obrazovke do všetkých štyroch smerov (kročko) – akoby * po ploche snímanej zhora. * * Priestor pohybu obidvoch postavičiek je obmedzený na viditeľnú časť sveta * (okna aplikácie). Skúste meniť veľkosť okna aplikácie po spustení. */ public class HlavnáTrieda extends GRobot { // Inštancie postavičiek skočko a kročko: private final Skočko skočko = new Skočko(); private final Kročko kročko = new Kročko(); // Konštruktor hlavnej triedy – inicializuje aplikáciu. private HlavnáTrieda() { skry(); kročko.aktivuj(); } // Reakcia na kliknutie tlačidlom myši. @Override public void klik() { if (skočko.aktívny()) { Svet.pípni(); skočko.deaktivuj(); kročko.aktivuj(); } else { Svet.pípni(); skočko.aktivuj(); kročko.deaktivuj(); } } // Reakcia na stlačenie klávesu. @Override public void stlačenieKlávesu() { if (skočko.aktívny()) { // Ovládam skočka šípkami doľava a doprava. (Výskok je úmyselne // naprogramovaný tak, aby reagoval iba na uvoľnenie klávesu, // aby hráčovi na skákanie nestačilo mať stlačený medzeník.) switch (ÚdajeUdalostí.kláves()) { case Kláves.VĽAVO: skočko.choďVľavo(); break; case Kláves.VK_RIGHT: skočko.choďVpravo(); break; } } if (kročko.aktívny()) { // Šípkami ovládam aj kročka, ale len keď stojí. // // Pozor! Toto obmedzenie spôsobuje „zasekávanie“ pri snahe // o náhlu zmenu smeru, ale je fyzikálne správnejšie. // // Poznámky: Keď chceme (napriek fyzikálnej správnosti) // obmedzenie brániace náhlym zmenám smeru kročka odstrániť, // stačí dať nasledujúci riadok do komentára. Správanie kročka // začne pripomínať rozprávkovú veveričku, ktorá vypila priveľa // kávy. Kročko bude ignorovať svoj moment hybnosti, čo sa bude // prejavovať náhlymi zmenami smeru a „tvrdohlavým“ úsilím // o prekonanie bariér okrajov. if (kročko.stojím()) { switch (ÚdajeUdalostí.kláves()) { case Kláves.VK_LEFT: kročko.choďVľavo(); break; case Kláves.VK_RIGHT: kročko.choďVpravo(); break; case Kláves.VK_UP: kročko.choďHore(); break; case Kláves.VK_DOWN: kročko.choďDole(); break; } } } } // Reakcia na uvoľnenie klávesu. @Override public void uvoľnenieKlávesu() { if (skočko.aktívny()) { switch (ÚdajeUdalostí.kláves()) { // Šípky skočka zastavujú. case Kláves.VK_LEFT: case Kláves.VK_RIGHT: skočko.stoj(); break; // Kláves medzera sa pokúsi o skok. To, či skok nastane, // alebo nie závisí od splnenia podmienok v metóde vyskoč(). case Kláves.MEDZERA: skočko.vyskoč(); break; } } if (kročko.aktívny()) { switch (ÚdajeUdalostí.kláves()) { // Uvoľnenie klávesu šípky prikáže kročkovi, aby zastavil. case Kláves.VK_LEFT: case Kláves.VK_RIGHT: case Kláves.VK_UP: case Kláves.VK_DOWN: kročko.stoj(); break; // (Poznámka: Posledný break riadiacej štruktúry switch // nie je nikdy potrebný. Ak je uvedený, neplní žiadnu // funkciu, ale aj tak je odporúčané ho uvádzať, aby sa // nezabudlo na jeho pridanie pri prípadnom rozširovaní // tela riadiacej štruktúry.) } } } // Hlavná metóda (vstupný bod programu). public static void main(String[] args) { new HlavnáTrieda(); } }
~
import knižnica.*; /** * Táto trieda pokytuje spoločný základ pre obidve postavičky. Obsahuje * definíciu kreslenia vlastného tvaru, ktorý je iný pre aktívnu a neaktívnu * postavičku a v predvolenom konštruktore je príkaz na zdvihnutie pera * grafického robota, od ktorého je trieda odvodená. */ public class Postavička extends GRobot { // Statická inštancia kreslenia tvaru bude spoločná pre všetky // postavičky, nech by ich bolo vytvorené ľubovoľné množstvo. private final static KreslenieTvaru vlastnýTvar = r -> { if (r.aktívny()) { r.kružnica(10); r.skoč(12); r.kruh(8); r.domov(); r.vpravo(30); r.dopredu(8); r.vpravo(60); r.dopredu(8); r.domov(); r.vľavo(30); r.dopredu(8); r.vľavo(60); r.dopredu(8); } else { r.farba(šedá); r.kružnica(10); r.dopredu(12); r.kružnica(8); } }; // Predvolený konštruktor public Postavička() { zdvihniPero(); vlastnýTvar(vlastnýTvar); } }
~
import knižnica.*; /** * Trieda definujúca fyziku pre kráčajúcu postavičku. */ class Kročko extends Postavička { // Prídavné vlastnosti postavičky: // – rýchlosť v, // – zrýchlenie a. private int v, a; // Jednoduchý konštruktor resetujúci hodnoty prídavných vlastností // postavičky. public Kročko() { v = a = 0; } // Metóda starajúca sa o fyziku postavičky. @Override public void aktivita() { if (a != 0) { // Nenulové zrýchlenie mení rýchlosť. v += a; // Ak je rýchlosť menšia než nula (klesne pod nulu pri // spomaľovaní), … if (v < 0) { // … tak zastavím postavičku úplne, … v = a = 0; } // … inak (pri zrýchľovaní) obmedzím rýchlosť na max. 20 // (bodov za tik). else if (v > 20) v = 20; } // Posun postavičky dopredu o aktuálnu hodnotu rýchlosti. dopredu(v); // Nasledujú testy a ošetrenia proti presiahnutiu hraníc obrazovky. // // Principiálne (komentáre, ktoré platia pre všetky štyri smery): // // // Ak súradnica x prekročí ľavú hranicu, … // if (polohaX() < Svet.ľavýOkraj()) // { // // … tak presuniem robot naspäť na túto hranicu, … // polohaX(Svet.ľavýOkraj()); // // … obrátim ho čelom vzad … // vpravo(180); // // … a nechám ho spomaľovať (nastavím záporné zrýchlenie). // a = -1; // } // // (Podobne to platí pre všetky štyri smery, pričom nižšie sú // protiľahlé okraje spárované.) if (polohaX() < Svet.ľavýOkraj()) { polohaX(Svet.ľavýOkraj()); vpravo(180); a = -1; } else if (polohaX() > Svet.pravýOkraj()) // (Ľavý a pravý okraj sú spárované do jednej štruktúry if-else.) { polohaX(Svet.pravýOkraj()); vpravo(180); a = -1; } if (polohaY() < Svet.spodnýOkraj()) { polohaY(Svet.spodnýOkraj()); vpravo(180); a = -1; } else if (polohaY() > Svet.hornýOkraj()) // (Rovnako spodný a horný okraj.) { polohaY(Svet.hornýOkraj()); vpravo(180); a = -1; } } // Ovládanie postavičky stanovením smerov a kladného zrýchlenia. public void choďVpravo() { smer(0); a = 1; } public void choďHore() { smer(90); a = 1; } public void choďVľavo() { smer(180); a = 1; } public void choďDole() { smer(270); a = 1; } // Zastavenie postavičky určením záporného zrýchlenia. // (Postavičku nezastavíme len tak „zrazu“ – necháme ju spomaľovať.) public void stoj() { a = -2; } // Overenie, či postavička stojí. // (Keď je rýchlosť rovná nule, postava určite stojí.) public boolean stojím() { return v == 0; } }
~
import knižnica.*; /** * Trieda definujúca fyziku pre skákajúcu postavičku. */ class Skočko extends Postavička { // Prídavné vlastnosti postavičky: // – horizontálna rýchlosť vx, // – vertikálna rýchlosť vy, // – horizontálne zrýchlenie ax. // (Poznámka: Vertikálne zrýchlenie je konštantné.) private int vx, vy, ax; // Jednoduchý konštruktor resetujúci hodnoty prídavných vlastností // postavičky. public Skočko() { vx = vy = ax = 0; } // Metóda starajúca sa o fyziku postavičky. @Override public void aktivita() { // Riešenie pohybu a obmedzení vo vodorovnom smere // ----------------------------------------------- if (ax != 0) { // V prípade, že je zrýchlenie nenulové, postavička plynule // akceleruje. vx += ax; // Obmedzenie maximálnej rýchlosti na ±15 (bodov za tik): if (vx > 15) vx = 15; else if (vx < -15) vx = -15; } else { // V prípade, že je zrýchlenie nulové, postavička spomaľuje // (hodnota rýchlosti sa posúva smerom k nule). if (vx > 0) --vx; else if (vx < 0) ++vx; } // Príkaz posuňVpravo posúva robot kolmo na jeho smer. Predvolene // je smer robota nastavený na 90°, čo je hore. So smerom tohto // robota nikde nemanipulujeme, čiže jeho smer zostáva stále na // hodnote 90°. Preto príkaz posuňVpravo mení vodorovnú polohu // podľa rýchlosti vx (pri kladnej hodnote je to doprava, pri // zápornej doľava). posuňVpravo(vx); // Ak robot narazí na ľavý okraj, odrazí sa (a postupne zastaví). if (polohaX() < Svet.ľavýOkraj()) { polohaX(Svet.ľavýOkraj()); vx = -vx; ax = 0; } // To isté platí pre pravý okraj. else if (polohaX() > Svet.pravýOkraj()) { polohaX(Svet.pravýOkraj()); vx = -vx; ax = 0; } // Riešenie pohybu a obmedzení v zvislom smere // -------------------------------------------- // Robot stále gravitačne padá, takže vertikálna rýchlosť plynule // klesá po minimálnu hodnotu -15 (bodov za tik). To znamená, že // tento robot má tzv. terminálnu rýchlosť (padania) 15 bodov za tik. if (vy > -15) --vy; // Podobne ako to je pri príkaze posuňVpravo (pozri vyššie) to platí // tu pri príkaze dopredu. Ním meníme zvislú polohu robota s pomocou // rýchlosti vy. Ak je vertikálna rýchlosť kladná, tak je postavička // vo výskoku – stúpa. Ak je záporná, tak klesá. dopredu(vy); // Nasleduje úprava hraníc vo vertikálnom smere. if (polohaY() < Svet.spodnýOkraj()) { // Keď postavička narazí na spodnú hranicu, odrazí sa // a bude chvíľu stúpať (poskočí). polohaY(Svet.spodnýOkraj()); vy = 10; } else if (polohaY() > Svet.hornýOkraj()) { // Pri hornom okraji obrazovky sa iba zastaví. polohaY(Svet.hornýOkraj()); vy = 0; } } // Metódy na pridávanie rýchlosti (nastavenie zrýchlenia) postavičky // v smere do strán. Kladné číslo začne pridávať rýchlosť v smere // doprava a záporné doľava. public void choďVpravo() { ax = 1; } public void choďVľavo() { ax = -1; } // Zastavenie postavičky. Na nulovú hodnotu zrýchlenie zareaguje fyzika // postavičky v reakcii aktivita (vyššie). public void stoj() { ax = 0; } // Metóda určujúca kedy a ako vysoko môže postavička „vyskočiť.“ // Obmedzenie je nastavené tak, aby skočko mohol vyskočiť len ak sa // jeho vertikálna rýchlosť nachádza v určitých hraniciach: (−8; 5). // To znamená, že: // – ak padá príliš rýchlo, nevyskočí, // – ak je práve v počiatočnej fáze výskoku, nevyskočí. public void vyskoč() { if (vy > -8 && vy < 5) vy = 15; } }
Poznámka: Tento projekt je starší. Bude potrebné ho aktualizovať tak, aby bol kompatibilný (už sa stalo) s najnovšou verziou programovacieho rámca GRobot.
Na tejto stránke je publikovaný ukážkový projekt Postavičky obsahujúci definície hierarchie tried pre dva typy postavičiek s vlastnou fyzikou. Projekt používa skupinu tried grafického robota. Na vygenerovanie prázdneho projektu odporúčam použiť Generátor projektov BlueJ (dostupný v sekcii Softvér na prevzatie).
Triedy projektu.
~
/** * Táto trieda pokytuje spoločný základ pre obidve postavičky. Obsahuje * definíciu kreslenia vlastného tvaru, ktorý je iný pre aktívnu a neaktívnu * postavičku a v predvolenom konštruktore je príkaz na zdvihnutie pera * grafického robota, od ktorého je trieda odvodená. */ public class Postavička extends GRobot { // Statická inštancia vlastného tvaru bude spoločná pre všetky // postavičky, nech by ich bolo vytvorených ľubovoľné množstvo. private final static VlastnýTvar vlastnýTvar = new VlastnýTvar() { @Override public void kresli(GRobot r) { r.zdvihniPero(); if (r.aktívny()) { r.hrúbkaPera(2); r.kružnica(10); r.dopredu(12); r.kruh(8); r.položPero(); r.domov(); r.doprava(30); r.dopredu(8); r.doprava(60); r.dopredu(8); r.domov(); r.doľava(30); r.dopredu(8); r.doľava(60); r.dopredu(8); } else { r.farba(šedá); r.kružnica(10); r.dopredu(12); r.kružnica(8); } } }; // Predvolený konštruktor public Postavička() { zdvihniPero(); vlastnýTvar(vlastnýTvar); } }
~
/** * Trieda definujúca fyziku pre kráčajúcu postavičku. */ class Kročko extends Postavička { // Prídavné vlastnosti postavičky: // – rýchlosť v, // – zrýchlenie a, private int v, a; // Konštruktor public Kročko() { v = a = 0; } // Metóda starajúca sa o fyziku postavičky @Override public void aktivita() { if (a != 0) { // Nenulové zrýchlenie mení rýchlosť v += a; // Ak je rýchlosť menšia než nula // (klesne pod nulu pri spomaľovaní) if (v < 0) { // zastavím postavičku úplne. v = a = 0; } // Inak (pri zrýchľovaní) obmedzím // rýchlosť na max. 20 (bodov za tik). else if (v > 20) v = 20; } dopredu(v); // Nasledujú testy a ošetrenia proti presiahnutiu hraníc obrazovky, // principiálne: // // // ak súradnica x prekročí ľavú hranicu, // if (polohaX() < podlaha.ľavýOkraj()) // { // // presuniem robot naspäť na túto hranicu // polohaX(podlaha.ľavýOkraj()); // // obrátim ho čelom vzad // doprava(180); // // a nechám ho spomaľovať (nastavím záporné zrýchlenie). // a = -1; // } if (polohaX() < podlaha.ľavýOkraj()) { polohaX(podlaha.ľavýOkraj()); doprava(180); a = -1; } else if (polohaX() > podlaha.pravýOkraj()) { polohaX(podlaha.pravýOkraj()); doprava(180); a = -1; } if (polohaY() < podlaha.spodnýOkraj()) { polohaY(podlaha.spodnýOkraj()); doprava(180); a = -1; } else if (polohaY() > podlaha.hornýOkraj()) { polohaY(podlaha.hornýOkraj()); doprava(180); a = -1; } } // Ovládanie postavičky stanovením smerov a kladného zrýchlenia. public void doprava() { smer(0); a = 1; } public void hore() { smer(90); a = 1; } public void doľava() { smer(180); a = 1; } public void dole() { smer(270); a = 1; } // Zastavenie postavičky určením záporného zrýchlenia. // (Postavičku nezastavíme len tak „zrazu“ – necháme ju spomaľovať) public void stoj() { a = -2; } // Overenie, či postavička stojí. // (Keď je rýchlosť rovná nule, postava určite stojí…) public boolean stojím() { return v == 0; } }
~
/** * Trieda definujúca fyziku pre skákajúcu postavičku. */ class Skočko extends Postavička { // Prídavné vlastnosti postavičky: // – horizontálna rýchlosť vx, // – vertikálna rýchlosť vy, // – horizontálne zrýchlenie ax, private int vx, vy, ax; // Konštruktor public Skočko() { vx = vy = ax = 0; } // Metóda starajúca sa o fyziku postavičky @Override public void aktivita() { // Riešenie pohybu a obmedzení vo vodorovnom smere // ----------------------------------------------- if (ax != 0) { // V prípade, že zrýchlenie je nenulové, // postavička plynule akceleruje. vx += ax; // Obmedzenie maximálnej rýchlosti na ±15 (bodov za tik) if (vx > 15) vx = 15; else if (vx < -15) vx = -15; } else { // V prípade, že je zrýchlenie nulové, postavička spomaľuje // (posúvam hodnotu rýchlosti smerom k nule). if (vx > 0) --vx; else if (vx < 0) ++vx; } // Príkaz posuňVpravo posúva robot kolmo na jeho smer // (predvolene je smer robota nastavený na 90°, čo je hore; // so smerom tohto robota nikde nemanipulujeme, čiže stále // zostáva na tejto hodnote; takže príkaz posuňVpravo mení // vodorovnú polohu podľa rýchlosti vx). posuňVpravo(vx); // Ak robot narazí na ľavý okraj, odrazí sa. // Podobne to platí pre pravý okraj… if (polohaX() < podlaha.ľavýOkraj()) { polohaX(podlaha.ľavýOkraj()); vx = -vx; ax = 0; } else if (polohaX() > podlaha.pravýOkraj()) { polohaX(podlaha.pravýOkraj()); vx = -vx; ax = 0; } // Riešenie pohybu a obmedzení vo zvislom smere // -------------------------------------------- // Stále padá, takže vertikálna rýchlosť plynule klesá po // minimálnu hodnotu -15 (bodov za tik). if (vy > -15) --vy; // Podobne ako to bolo s príkazom posuňVpravo, je to aj // s príkazom dopredu. Ním meníme zvislú polohu robota s pomocou // rýchlosti vy. Ak je vertikálna rýchlosť kladná, postavička // je vo výskoku – stúpa… dopredu(vy); // Nasleduje úprava hraníc vo vertikálnom smere. if (polohaY() < podlaha.spodnýOkraj()) { // Keď postavička narazí na spodnú hranicu, odrazí sa // a bude chvíľu stúpať (poskočí)… polohaY(podlaha.spodnýOkraj()); vy = 10; } else if (polohaY() > podlaha.hornýOkraj()) { // Pri hornom okraji obrazovky sa iba zastaví. polohaY(podlaha.hornýOkraj()); vy = 0; } } // Metódy na pridávanie rýchlosti (nastavenie zrýchlenia) postavičky // v smere do strán. Kladné číslo začne pridávať rýchlosť v smere // doprava a záporné doľava. public void doprava() { ax = 1; } public void doľava() { ax = -1; } // Zastavenie postavičky. Na nulové zrýchlenie zareaguje // fyzika postavičky v metóde pracuj(). public void stoj() { ax = 0; } // Metóda určujúca kedy a ako vysoko môže postavička „vyskočiť“. public void skoč() { if (vy > -8 && vy < 5) vy = 15; } }
~
/** * V tomto ukážkovom projekte sú naprogamované dve „postavičky“ s odlišným * správaním. Medzi ovládaním jednej a druhej sa dá prepínať kliknutím myši. * Obe sú ovládané kurzorovými šípkami. Jedna je skákajúca, druhá sa * pohybuje do štyroch smerov. Priestor pohybu obidvoch je ohraničený * viditeľnou časťou lúky, to znamená, že sa smú pohybovať len po viditeľnej * časti plátna lúky. * * Prvá z nich je naprogramovaná tak, že vplyvom gravitácie padá smerom * nadol až po spodný okraj viditeľného plátna. Kláves medzera jej dovoľuje * „skákať“. Druhá sa pohybuje po plátne ako po ploche snímanej zhora. */ public class HlavnáTrieda extends GRobot { // Inštancie postavičiek skočko a kročko private final Skočko skočko = new Skočko(); private final Kročko kročko = new Kročko(); private HlavnáTrieda() { skry(); kročko.aktivuj(); new ObsluhaUdalostí() { @Override public void klik() { prepniPostavičku(); } @Override public void stlačenieKlávesu() { priStlačeníKlávesu(); } @Override public void uvoľnenieKlávesu() { priUvoľneníKlávesu(); } }; } private void prepniPostavičku() { if (skočko.aktívny()) { svet.pípni(); skočko.deaktivuj(); kročko.aktivuj(); } else { svet.pípni(); skočko.aktivuj(); kročko.deaktivuj(); } } private void priStlačeníKlávesu() { if (skočko.aktívny()) { // Ovládam skočka šípkami doľava a doprava. switch (údajeUdalostí.kláves()) { case Kláves.VĽAVO: skočko.doľava(); break; case Kláves.VK_RIGHT: skočko.doprava(); break; } } if (kročko.aktívny()) { // Šípkami ovládam aj kročka, ale len keď stojí. if (kročko.stojím()) { switch (údajeUdalostí.kláves()) { case Kláves.VK_LEFT: kročko.doľava(); break; case Kláves.VK_RIGHT: kročko.doprava(); break; case Kláves.VK_UP: kročko.hore(); break; case Kláves.VK_DOWN: kročko.dole(); break; } } } } private void priUvoľneníKlávesu() { if (skočko.aktívny()) { switch (údajeUdalostí.kláves()) { // Šípky skočka zastavujú. case Kláves.VK_LEFT: case Kláves.VK_RIGHT: skočko.stoj(); break; // Kláves medzera sa pokúsi o skok. // To, či skok nastane, závisí od splnenia podmienok // v metóde skoč(). case Kláves.MEDZERA: skočko.skoč(); } } if (kročko.aktívny()) { switch (údajeUdalostí.kláves()) { // Uvoľnenie klávesu šípky prikáže kročkovi, aby zastavil. case Kláves.VK_LEFT: case Kláves.VK_RIGHT: case Kláves.VK_UP: case Kláves.VK_DOWN: kročko.stoj(); } } } // Hlavná metóda… public static void main(String[] args) { new HlavnáTrieda(); } }