Greenfoot
(→Reakce na klávesy: Detekce alfanumerických znaků.) |
(Přidání ukázky: Game over! s textovým aktérem.) |
||
| Řádka 96: | Řádka 96: | ||
=== Aktér s textovým popisem === | === Aktér s textovým popisem === | ||
Pokud chceme místo obrázku aktéra zobrazit text, využijeme alternativní konstruktor třídy <code>GreenfootImage</code>: | Pokud chceme místo obrázku aktéra zobrazit text, využijeme alternativní konstruktor třídy <code>GreenfootImage</code>: | ||
| − | GreenfootImage imgVlevo = new GreenfootImage("Vlevo!", 50, Color.RED, Color. | + | GreenfootImage imgVlevo = new GreenfootImage("Vlevo!", 50, Color.RED, Color.YELLOW); |
| − | Zbytek kódu zůstává stejný. Jen potřebujeme navíc do hlavičky (úplně na začátek kódu třídy aktéra) doplnit k importu tříd knihovny <code>Greenfoot</code> i import třídy <code>java.awt.Color</code>: | + | Zbytek kódu zůstává stejný. Jen potřebujeme navíc do hlavičky (úplně na začátek kódu třídy aktéra) doplnit k importu tříd knihovny <code>Greenfoot</code> i import třídy <code>java.awt.Color</code>: |
import Greenfoot.*; | import Greenfoot.*; | ||
'''import java.awt.Color;''' | '''import java.awt.Color;''' | ||
... | ... | ||
| + | |||
| + | <div class="Priklad"> | ||
| + | ; Příklad — „Game over!“ | ||
| + | * Připravme si hlášení „Game over!“, které zobrazíme na konci hry. | ||
| + | |||
| + | Třída GameOver: | ||
| + | |||
| + | import Greenfoot.*; | ||
| + | import java.awt.Color; | ||
| + | |||
| + | /** Třída GameOver bude reprezentovat aktéra, který bude fungovat jako | ||
| + | * textové hlášení. | ||
| + | */ | ||
| + | public class GameOver { | ||
| + | public GameOver() { | ||
| + | GreenfootImage imgGameOver = new GreenfootImage("Vlevo!", 50, Color.YELLOW, Color.BLUE); | ||
| + | this.setImage(imgGameOver); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| + | Ukončení hry: | ||
| + | |||
| + | import Greenfoot.*; | ||
| + | |||
| + | /** Třída Panáček - po srážce s kamenem ukončí hru. */ | ||
| + | public class Panacek { | ||
| + | public void act() { | ||
| + | if (this.isTouching(Kamen.class)) { | ||
| + | World svet = this.getWorld(); | ||
| + | ''// Přidej hlášení "Game over!"'' | ||
| + | svet.addObject('''new GameOver()''', svet.getWidth()/2, svet.getHeight/2); | ||
| + | ''// Ukonči hru:'' | ||
| + | '''Greenfoot.stop();''' | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | Samozřejmě panáček toho může dělat víc a třídy se můžou jmenovat jinak. | ||
| + | </div> | ||
Aktuální verze z 18. 5. 2020, 09:08
Obsah |
Co je to Greenfoot?
Greenfoot je framework pro tvorbu jednoduchých 2D her, postavený na programovacích jazycích Java a Stride (my zde využíváme jazyk Java).
- Princip funkce
- Vzhled hry popisuje třída, která musí být potomkem třídy
World. Předpokládejme, že se bude jmenovatHraWorld, ale název si můžeme vymyslet. - Na hrací ploše jsou aktéři (actor).
- Chování aktérů je popsáno třídami, které jsou potomky třídy
Actor. - Aktéři jsou vizuálně zastoupeni obrázkem, který vybíráme při vytvoření třídy aktéra.
- Průběh hry
- Vytvoří se instance třídy
HraWorld(resp. jak jsme nazvali svého potomka třídyWorld). - Spustí se konstruktor třídy
HraWorld. - A dále se opakuje:
- Zavolá se metoda
act()na svět (potomka třídyHraWorld). - Zavolá se metoda
act()pro všechny aktéry.
- Zavolá se metoda
Vytváření aktérů
- Příprava instance aktéra
- Prvky ve hře (postavy atd.) jsou třídy, které jsou potomky třídy
Actor. - Jejich instance vytváříme stejně jako vždy v Javě: operátorem
new.
- Umístění instance aktéra na plochu
- Metoda
World.addObject(Actor actor, int x, int y). - Umístí aktéra na pozici (x, y)
- Odstranění aktéra z plochy
- Metoda
World.removeObject(Actor actor).
Příklad — Vytvoření aktéra třídy Panacek a umístění na souřadnice (200, 150).
public class MojeHra extends World {
...
public void MojeHra() {
...
Panacek panacek = new Panacek();
this.addObject(panacek, 200, 150);
...
}
Nastavení pozice aktéra
Máme dvě varianty ovládání prvku (actora):
- Relativní pozicování
-
turn(int oKolik)... otáčí o daný počet stupňů ve směru hodinových ručiček -
move(int delka)... pokročí vpřed o daný počet dílků ve směru, do kterého je otočen -
setRotation(int uhel)... natočí prvek do daného směru (0 je směr vpravo, po směru hodinových ručiček) -
turnTowards(int x, int y)... natočí prvek směrem k zadaným souřadnicím.
- Absolutní pozicování
-
setLocation(int x, int y)- přesune prvek na zadané souřadnice
- obvykle je třeba uložit si souřadnice.
- Příklad
- vytvoření metody
move(int dx, int dy)
public void act()
{
this.move(3,-1);
}
private void move(int dx, int dy) {
int cilX = this.getX()+dx;
int cilY = this.getY()+dy;
this.turnTowards(cilX, cilY);
this.setLocation(cilX, cilY);
}
Změna obrázku aktéra
Ke změně obrázku slouží metody:
Actor.setImage(GreenfootImage novyObrazek) Actor.setImage(String cestaKNovemuObrazku)
Pokud zadáme cestu k obrázku, obrázek se hledá v podsložce images složky s projektem.
- Příklad 1) Otočení vlevo či vpravo
class Panacek extends Actor
GreenfootImage imgVlevo = new GreenfootImage("imgVlevo.png");
// ...
public void act() {
// ...
if (Greenfoot.isKeyDown("left")) {
this.setLocation(this.getX()-1, this.getY());
this.setImage(imgVlevo);
}
// ...
}
}
Aktér s textovým popisem
Pokud chceme místo obrázku aktéra zobrazit text, využijeme alternativní konstruktor třídy GreenfootImage:
GreenfootImage imgVlevo = new GreenfootImage("Vlevo!", 50, Color.RED, Color.YELLOW);
Zbytek kódu zůstává stejný. Jen potřebujeme navíc do hlavičky (úplně na začátek kódu třídy aktéra) doplnit k importu tříd knihovny Greenfoot i import třídy java.awt.Color:
import Greenfoot.*; import java.awt.Color; ...
- Příklad — „Game over!“
- Připravme si hlášení „Game over!“, které zobrazíme na konci hry.
Třída GameOver:
import Greenfoot.*;
import java.awt.Color;
/** Třída GameOver bude reprezentovat aktéra, který bude fungovat jako
* textové hlášení.
*/
public class GameOver {
public GameOver() {
GreenfootImage imgGameOver = new GreenfootImage("Vlevo!", 50, Color.YELLOW, Color.BLUE);
this.setImage(imgGameOver);
}
}
Ukončení hry:
import Greenfoot.*;
/** Třída Panáček - po srážce s kamenem ukončí hru. */
public class Panacek {
public void act() {
if (this.isTouching(Kamen.class)) {
World svet = this.getWorld();
// Přidej hlášení "Game over!"
svet.addObject(new GameOver(), svet.getWidth()/2, svet.getHeight/2);
// Ukonči hru:
Greenfoot.stop();
}
}
}
Samozřejmě panáček toho může dělat víc a třídy se můžou jmenovat jinak.
Reakce na klávesy
Stisk klávesy (napsání písmenka)
String Greenfoot.getKey()
- Vrací
null, když nebyla stisknuta žádná klávesa. - Odpovídá tomu, jak píše písmenka textový editor.
- Pokud uživatel drží stisknutou klávesu déle, pak:
- Pošle se jedno písmeno,
- nějakou dobu se počká a neposílá se nic,
- pak se začne opakovaně vysílat písmeno, dokud uživatel klávesu nepustí, nebo
- Speciální klávesy:
-
"space"... mezerník -
"up","down","right","left"... šipky -
"F1",... funkční klávesy
-
- Příklad
- Pohyb podle kláves
String vstup = Greenfoot.getKey();
if (vstup != null) {
if (vstup.equals("right")) {
this.setRotation(0);
} else if (vstup.equals("left")) {
this.setRotation(180);
} else if (vstup.equals("up")) {
this.setRotation(-90);
} else if (vstup.equals("down")) {
this.setRotation(90);
}
this.move(1);
}
Detekce, zda uživatel drží klávesu
boolean Greenfoot.isKeyDown(String klavesa)
- Pokud uživatel drží klávesu delší dobu, zůstane platná pořád.
- Takto lze detekovat stisk více kláves zároveň, nemusí to však být tak spolehlivé.
Funkční klávesy
- Tímto způsobem můžeme detekovat i stisk funkčních kláves Control a Shift.
- Kódy pro tyto klávesy jsou
"control"a"shift". - Pokud tedy chceme detekovat kombinaci
<Ctrl>+<Shift>+<S>, pak píšeme:
String pismeno = Greenfoot.getKey();
if (Greenfoot.isKeyDown("control") && Greenfoot.isKeyDown("shift") && "s".equals(pismeno)) {
... co se má stát ...
}
Jak detekovat pouze písmena a čísla?
- Občas bychom chtěli reagovat pouze na alfanumerické znaky (písmena a čísla).
- K tomu můžete použít jednoduchý trik — většina funkčních kláves má totiž kódy z více písmen. Můžeme tedy využít toho, že když je funkční kód klávesy jen jedno písmeno, považujeme ho za alfanumerický znak:
String pismeno = Greenfoot.getKey();
if (pismeno.lenght() == 1) {
... co se má stát ...
}
Zjištění pozice myši
MouseInfo Greenfoot.getMouseInfo()
- Vrací instanci třídy
MouseInfo. -
MouseInfonese informace o:- Pozici X a Y kurzoru:
int MouseInfo.getX(),int MouseInfo.getY() - Stisku tlačítek,...
- Pozici X a Y kurzoru:
- Příklad
- Pohyb aktéra za myší
public void act() {
MouseInfo mi = Greenfoot.getMouseInfo();
int x = mi.getX();
int y = mi.getY();
int vzdalenost = (int) Math.sqrt(Math.pow(x-this.getX(),2)+Math.pow(y-this.getY(),2));
if (vzdalenost > 0) {
this.turnTowards(x, y);
this.move(Math.min(vzdalenost, 5));
this.setRotation(0);
}
}
Další tipy
Náhodná čísla
- Standardní řešení Javy
-
Math.random()... vrací čísla z intervalu <0, 1)
- Řešení Greenfootu
- Pro hry je často potřeba generovat celá čísla. Pro zjednodušení je tedy v Greenfootu metoda:
-
Greenfoot.getRandomNumber(int limit)- Vrací čísla z množiny {0, 1, ..., limit-1}.
Okraj obrazovky
- Pro detekci, zda je aktér na okraji obrazovky, můžeme použít metodu
isAtEdge().
if (this.isAtEdge()) {
this.turn(180);
}
Objekty mimo obrazovku
- Pokud v konstruktoru světa (třída
World) použijete volitelný parametr, můžete povolit umístění objektů mimo obrazovku.
public class MyWorld extends World
{
public MyWorld()
{
super(600, 400, 1, false);
}
}
Zjištění kolize aktérů ve hře
- Ke zjištění kolizí slouží metody ve třídě Actor, které se jmenují
getXXXObjectYYY. - Metod je hodně, ale chovají se podobně:
getOneIntersectingObject(class)
- Vrátí jeden kolidující objekt.
- Řeší kolizi jen objektů té třídy, kterou zadáme jako parametr.
- Pokud chceme, aby řešil kolize s objekty libovolné třídy, zadáme jako parametr
null.
getIntersectingObjects(class)
- Vrátí seznam všech objektů, kolidujících s aktérem.
getOneObjectAtOffset(int dx, int dy, class)
- Vrátí jednoho aktéra z aktérů vzdálených nejvýše (dx, dy)(viz dále).
...
- Výběr třídy objektů
- Pokud zadáte parametr typu class, bere v potaz pouze objekty zadaného typu. Pokud zadáme
null, berou se v potaz všechny objekty.
Příklad:
List<Actor> seznam = this.getIntersectingObjects(null);
- Bere v potaz všechny typy aktérů. Může se jednat o aktéry různých typů (instance různých tříd).
List<Jablko> seznam = this.getIntersectingObjects(Jablko.class);
- Detekuje pouze kolidující aktéry třídy
Jablko, všechny ostatní objekty ignoruje!
- Návratová hodnota
Tyto metody vrací buď:
- první kolidující objekt daného typu nebo
nullkdyž nekoliduje žádný objekt daného typu:
private void vyresKolidujici() {
Predmet predmet = (Predmet) this.getOneIntersectingObject(Predmet.class);
if (predmet != null) {
... Co se má dít, třeba: ...
this.getWorld().removeObject(predmet);
}
}
- nebo seznam (může být prázdný) všech kolidujících objektů daného typu:
private void vyresKolidujici() {
List<Actor> seznam = this.getIntersectingObjects(null);
for (Actor prvek : seznam) {
prvek.aplikuj(this);
}
}
Pokud vrací metoda seznam kolidujících objektů, pak musíme importovat třídu java.util.List tím, že napíšeme úplně na začátek:
import java.util.List;
- Filtr
- intersecting objects ... objekty, které se prolínají se stávajícím (došlo ke kolizi)
- objects at offset ... objekty, které jsou v dané vzdálenosti (dx, dy) od stávajícího objektu
Práce s prostředím hry (World)
Nastavení pozadí hrací plochy
- Obrázek na pozadí prostředí/světa změníme metodou:
World.setBackground(GreenfootImage obrazek)
- Tuto metodu můžeme zavolat například v konstruktoru našeho potomka třídy
World.
Přepínání prostředí/světů v Greenfootu
- Pokud potřebujete přepnout hru do jiného prostředí (světa), máte k dispozici metodu:
Greenfoot.setWorld(World novySvet)
Příklad: 1. krok: Upravte třídu MyWorld:
public class MyWorld extends World
{
int citac = 0;
int konec = 300;
public MyWorld()
{
super(600, 400, 1);
}
public void act() {
System.out.println("Zbývá: "+(this.konec-this.citac));
this.citac++;
if (this.citac > this.konec)
{
Greenfoot.setWorld(new DruhySvet());
}
}
}
2. krok: Vytvořte druhou instanci třídy World, které nastavte jako pozadí některý obrázek ze záložky Backgrounds:
public class DruhySvet extends World
{
public MyWorld()
{
super(600, 400, 1);
}
}
Po spuštění hry by hra měla chvíli čekat a pak by se mělo změnit pozadí — dojde ke změně prostředí hry (world).
Úkol: Zkuste si vytvořit hru!
- Vytvořte hru, na které ukážete ty prvky práce v Greenfootu, které jsme si ukázali výše.
Přikládám pár nápadů pro inspiraci z projektů řešených na Obchodní akademii Uherské Hradiště - obor Informační technologie.
Související stránky
- Greenfoot: Řešení častých úloh
- Máte-li probém se spouštěním aplikací na webu Greenfoot.org, zkuste: Spouštění appletů.
Zdroje
- Existují velmi rozsáhlá fóra (v angličtině), popisující řešení problémů v Greenfootu. Zkuste ve vyhledávači najít:
greenfoot téma-které-hledáte. - Dokumentaci tříd najdete na adrese Greenfoot.org → Javadoc