Greenfoot

Z MiS
(Rozdíly mezi verzemi)
Přejít na: navigace, hledání
(Zjištění kolize prvků ve hře: Doplněno, rozšířeno.)
(Další tipy: Přidána možnost skládat objekty mimo obrazovku.)
(Není zobrazeno 9 mezilehlých verzí od 1 uživatele.)
Řádka 3: Řádka 3:
  
 
== Co je to Greenfoot? ==
 
== Co je to Greenfoot? ==
Dokumentaci tříd najdete na adrese:
 
* [http://www.greenfoot.org/files/javadoc/ Greenfoot.org → Javadoc]
 
  
 +
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 ==
+
; Princip funkce
 
* Vzhled hry popisuje třída, která musí být potomkem třídy <code>World</code>. Předpokládejme, že se bude jmenovat <code>HraWorld</code>, ale název si můžeme vymyslet.
 
* Vzhled hry popisuje třída, která musí být potomkem třídy <code>World</code>. Předpokládejme, že se bude jmenovat <code>HraWorld</code>, ale název si můžeme vymyslet.
 
* Na hrací ploše jsou aktéři (''actor'').
 
* Na hrací ploše jsou aktéři (''actor'').
Řádka 19: Řádka 18:
 
## Zavolá se metoda <code>act()</code> pro všechny aktéry.
 
## Zavolá se metoda <code>act()</code> pro všechny aktéry.
  
 
== 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ů ==
 
== Vytváření aktérů ==
; Příprava instance actora
+
; Příprava instance aktéra
 
* Prvky ve hře (postavy atd.) jsou třídy, které jsou potomky třídy <code>Actor</code>.
 
* Prvky ve hře (postavy atd.) jsou třídy, které jsou potomky třídy <code>Actor</code>.
 
* Jejich instance vytváříme stejně jako vždy v Javě: operátorem <code>new</code>.
 
* Jejich instance vytváříme stejně jako vždy v Javě: operátorem <code>new</code>.
  
;Umístění instance na plochu:
+
;Umístění instance aktéra na plochu:
 
* Metoda <code>World.addObject(Actor actor, int x, int y)</code>.
 
* Metoda <code>World.addObject(Actor actor, int x, int y)</code>.
* Umístí actora na pozici (x, y)
+
* Umístí aktéra na pozici (x, y)
  
; Odstranění actora z plochy
+
; Odstranění aktéra z plochy
 
* Metoda <code>World.removeObject(Actor actor)</code>.
 
* Metoda <code>World.removeObject(Actor actor)</code>.
 +
 +
<div class="Priklad">
 +
Příklad — Vytvoření aktéra třídy <code>Panacek</code> 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);
 +
    ...
 +
  }
 +
</div>
 +
  
  
Řádka 84: Řádka 91:
 
     }
 
     }
 
  }
 
  }
 +
 +
 +
 +
=== 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>:
 +
    GreenfootImage imgVlevo = new GreenfootImage("Vlevo!", 50, Color.RED, Color.RIGHT);
 +
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 java.awt.Color;'''
 +
    ...
 +
  
  
Řádka 121: Řádka 139:
  
  
== Náhodná čísla ==
+
 
 +
== Zjištění pozice myši ==
 +
<code>MouseInfo Greenfoot.getMouseInfo()</code>
 +
* Vrací instanci třídy <code>MouseInfo</code>.
 +
* <code>MouseInfo</code> nese informace o:
 +
** Pozici X a Y kurzoru: <code>int MouseInfo.getX()</code>, <code>int MouseInfo.getY()</code>
 +
** Stisku tlačítek,...
 +
 
 +
; 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:
 
; Standardní řešení Javy:
 
* <code>Math.random()</code> ... vrací čísla z intervalu &lt;0, 1)
 
* <code>Math.random()</code> ... vrací čísla z intervalu &lt;0, 1)
Řádka 129: Řádka 173:
 
** Vrací čísla z množiny {0, 1, ..., limit-1}.
 
** 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 <code>isAtEdge()</code>.
 +
if (this.isAtEdge()) {
 +
    this.turn(180);
 +
}
 +
 +
=== Objekty mimo obrazovku ===
 +
* Pokud v konstruktoru světa (třída <code>World</code>) 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 prvků ve hře ==
+
== Zjištění kolize aktérů ve hře ==
* Ke zjištění kolizí slouží metody ve třídě <tt>Actor</tt>, které se jmenují <code>get...Object...</code>.
+
* Ke zjištění kolizí slouží metody ve třídě <tt>Actor</tt>, které se jmenují <code>get''XXX''Object''YYY''</code>.
 
* Metod je hodně, ale chovají se podobně:
 
* Metod je hodně, ale chovají se podobně:
  getOneIntersectingObject(class)
+
  '''get'''OneIntersecting'''Object'''(class)
* Vrátí jeden kolidující objekt dané třídy nebo <code>null</code>.
+
* Vrátí jeden kolidující objekt.
  getIntersectingObjects(class)
+
* Řeší kolizi jen objektů té třídy, kterou zadáme jako parametr.
 +
* Pokud chceme, aby řešil kolize s&nbsp;objekty libovolné třídy, zadáme jako parametr <code>null</code>.
 +
  '''get'''Intersecting'''Object'''s(class)
 
* Vrátí seznam všech objektů, kolidujících s aktérem.
 
* Vrátí seznam všech objektů, kolidujících s aktérem.
  getOneObjectAtOffset(int dx, int dy, class)
+
  '''get'''One'''Object'''AtOffset(int dx, int dy, class)
 
* Vrátí jednoho aktéra z&nbsp;aktérů vzdálených nejvýše (dx, dy)(viz dále).
 
* Vrátí jednoho aktéra z&nbsp;aktérů vzdálených nejvýše (dx, dy)(viz dále).
 
  ...
 
  ...
  
 
; Výběr třídy objektů
 
; Výběr třídy objektů
* Pokud zadáte parametr typu <tt>class</tt>, bere v potaz pouze objekty zadaného typu. Pokud zadáme <code>null</code>, berou se v potaz všechny objekty.
+
* Pokud zadáte parametr typu <tt>class</tt>, bere v potaz pouze objekty zadaného typu. Pokud zadáme <code>null</code>, berou se v&nbsp;potaz všechny objekty.
  
 
Příklad:
 
Příklad:
Řádka 154: Řádka 215:
 
* první kolidující objekt daného typu nebo <code>null</code> když nekoliduje žádný objekt daného typu:
 
* první kolidující objekt daného typu nebo <code>null</code> když nekoliduje žádný objekt daného typu:
 
  private void vyresKolidujici() {
 
  private void vyresKolidujici() {
     Predmet predmet = this.getOneIntersectingObject(Predmet.class);  
+
     Predmet predmet = (Predmet) this.getOneIntersectingObject(Predmet.class);  
 
     if (predmet != null) {
 
     if (predmet != null) {
 
       ''... Co se má dít, třeba: ...''
 
       ''... Co se má dít, třeba: ...''
Řádka 178: Řádka 239:
 
* objects at offset ... objekty, které jsou v dané vzdálenosti (dx, dy) od stávajícího objektu
 
* objects at offset ... objekty, které jsou v dané vzdálenosti (dx, dy) od stávajícího objektu
  
== Řešení typických situací ==
+
== Práce s&nbsp;prostředím hry (World) ==
=== 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
+
=== Nastavení pozadí hrací plochy ===
  public void act() {
+
* Obrázek na pozadí prostředí/světa změníme metodou:
    // ...
+
  World.setBackground(GreenfootImage obrazek)
    if (this.getX() < 1) {
+
* Tuto metodu můžeme zavolat například v&nbsp;konstruktoru našeho potomka třídy <code>World</code>.
        World svet = this.getWorld();
+
        if (svet != null) {
+
            this.getWorld().removeObject(this);
+
        }
+
    }
+
}
+
  
=== Výpis stavu hry, hlášky ===
+
=== Přepínání prostředí/světů v&nbsp;Greenfootu ===
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é vzory#Jedináček|návrhový vzor Jedináček (Singleton)]].
+
* Pokud potřebujete přepnout hru do jiného prostředí (světa), máte k&nbsp;dispozici metodu:
 
+
Greenfoot.setWorld(World ''novySvet'')
  public class Pocitadlo extends Actor
+
<div class="Priklad">
 +
Příklad:
 +
1. krok: Upravte třídu MyWorld:
 +
  public class MyWorld extends World
 
  {
 
  {
    // Implementace Jedináčka:
+
int citac = 0;
    private static Pocitadlo prvniHrac = null;
+
int konec = 300;
    public static Pocitadlo getInstance() {
+
public MyWorld()
        if (this.prvniHrac == null)
+
{
            this.prvniHrac = new Pocitadlo();
+
super(600, 400, 1);  
        }
+
}
        return this.prvniHrac;
+
public void act() {
    }
+
System.out.println("Zbývá: "+(this.konec-this.citac));
   
+
this.citac++;
    // A zbytek kódu:
+
if (this.citac > this.konec)  
    private int stav;
+
{
   
+
Greenfoot.setWorld(new DruhySvet());
    '''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);
+
    }
+
 
  }
 
  }
 
+
2. krok: Vytvořte druhou instanci třídy World, které nastavte jako pozadí některý obrázek ze záložky Backgrounds:
Na plochu počítadlo přidáme:
+
public class DruhySvet extends World
 
+
  {
  public HraWorld() {
+
public MyWorld()
    ...
+
{
    this.addObject(Pocitadlo.getInstance(), 20, 20);
+
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í &mdash; dojde ke změně prostředí hry (world).
 +
</div>
  
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 ===
 
  
  
Řádka 263: Řádka 290:
  
  
== Další stránky ==
+
== 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ů]].
 
* 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&nbsp;angličtině), popisující řešení problémů v&nbsp;Greenfootu. Zkuste ve vyhledávači najít: <code>greenfoot ''téma-které-hledáte''</code>.
 +
* Dokumentaci tříd najdete na adrese [http://www.greenfoot.org/files/javadoc/ Greenfoot.org &rarr; Javadoc]

Verze z 17. 2. 2020, 13:17


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
Průběh hry
  1. Vytvoří se instance třídy HraWorld (resp. jak jsme nazvali svého potomka třídy World).
  2. Spustí se konstruktor třídy HraWorld.
  3. A dále se opakuje:
    1. Zavolá se metoda act() na svět (potomka třídy HraWorld).
    2. Zavolá se metoda act() pro všechny aktéry.


Vytváření aktérů

Příprava instance aktéra
Umístění instance aktéra na plochu
Odstranění aktéra z plochy

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í
Absolutní pozicování
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.RIGHT);

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;
   ...


Reakce na klávesy

Stisk klávesy (napsání písmenka)

String Greenfoot.getKey()

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)


Zjištění pozice myši

MouseInfo Greenfoot.getMouseInfo()
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
Řešení Greenfootu

Okraj obrazovky

if (this.isAtEdge()) {
    this.turn(180);
}

Objekty mimo obrazovku

public class MyWorld extends World
{
    public MyWorld()
    {
        super(600, 400, 1, false); 
    }
}

Zjištění kolize aktérů ve hře

getOneIntersectingObject(class)
getIntersectingObjects(class)
getOneObjectAtOffset(int dx, int dy, class)
...
Výběr třídy objektů

Příklad:

List<Actor> seznam = this.getIntersectingObjects(null); 
List<Jablko> seznam = this.getIntersectingObjects(Jablko.class);
Návratová hodnota

Tyto metody vrací buď:

private void vyresKolidujici() {
   Predmet predmet = (Predmet) this.getOneIntersectingObject(Predmet.class); 
   if (predmet != null) {
      ... Co se má dít, třeba: ...
      this.getWorld().removeObject(predmet);
   }
}
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

Práce s prostředím hry (World)

Nastavení pozadí hrací plochy

World.setBackground(GreenfootImage obrazek)

Přepínání prostředí/světů v Greenfootu

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!


Související stránky


Zdroje

Osobní nástroje
Jmenné prostory
Varianty
Akce
Výuka
Navigace
Nástroje