Greenfoot
Obsah |
Co je to Greenfoot?
Dokumentaci tříd najdete na adrese:
Princip
- 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
Nastavení parametrů světa
- Nastavení pozadí hrací plochy
- Například v konstruktoru našeho potomka třídy World můžeme zavolat:
World.setBackground(GreenfootImage obrazek)
Vytváření aktérů
- Příprava instance actora
- 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 na plochu
- Metoda
World.addObject(Actor actor, int x, int y). - Umístí actora na pozici (x, y)
- Odstranění actora z plochy
- Metoda
World.removeObject(Actor actor).
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);
}
// ...
}
}
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é.
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}.
Zjištění kolize prvků 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 dané třídy nebo
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 = 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
Řešení typických situací
Rušení aktérů
- Příklad 1) Zrušení kolidujících actorů
private void act() {
// ...
World svet = this.getWorld();
List<Actor> seznam = this.getIntersectingObjects(null);
for (Actor prvek : seznam) {
prvek.aplikuj(this);
svet.removeObject(prvek);
}
- Příklad 2) Zrušení aktéra, který vyjel mimo obrazovku na levém okraji
public void act() {
// ...
if (this.getX() < 1) {
World svet = this.getWorld();
if (svet != null) {
this.getWorld().removeObject(this);
}
}
}
Výpis stavu hry, hlášky
Pro výpis skóre vytváříme nového speciálního „actora“ (objekt). Protože bude počitadlo pro celý projekt nejspíš jedno (nebo třeba jedno pro každého hráče), využijeme s výhodou návrhový vzor Jedináček (Singleton).
public class Pocitadlo extends Actor
{
// Implementace Jedináčka:
private static Pocitadlo prvniHrac = null;
public static Pocitadlo getInstance() {
if (this.prvniHrac == null)
this.prvniHrac = new Pocitadlo();
}
return this.prvniHrac;
}
// A zbytek kódu:
private int stav;
private Pocitadlo() { // private kvůli Jedináčkovi
this.setStav(0);
}
public void setStav(int stav) {
this.stav = stav;
String text = "Skóre: "+this.stav;
GreenfootImage obrazek = new GreenfootImage(text, 20, Color.yellow, Color.gray);
this.setImage(obrazek);
}
public void zmenStav(int zmena) {
this.setStav(this.stav+zmena);
}
}
Na plochu počítadlo přidáme:
public HraWorld() {
...
this.addObject(Pocitadlo.getInstance(), 20, 20);
...
}
Změnu skóre pak kdekoli v projektu můžeme vyvolat:
... Pocitadlo.getInstance().setStav(10); ...
nebo
... Pocitadlo.getInstance().zmenStav(-2); ...
Lze samozřejmě do počitadla přidat informaci o aktuálním počtu bodů a tu pak zvyšovat nebo snižovat dle potřeby.
Zdi
Ú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.
Další stránky
- Máte-li probém se spouštěním aplikací na webu Greenfoot.org, zkuste: Spouštění appletů.