TlačiťTlačiť Slovenčina English Hľadať RSS

© 2005 – 2024 Roman Horváth, všetky práva vyhradené. Dnes je 23. 4. 2024.

Stránka sa načítava, prosím čakajte…

Dátum: 8. 9. 2020, pred štyrmi rokmi

Obidve verzie „papáčov“ publikované v tejto kapitole boli cielene spracované tak, aby boli čo najjednoduchšie (čo je najvýraznejšie vidno pri triede Papáč z „pilulkovej“ verzie) a aby ukazovali niekoľko konceptov, ktoré sú pri troche úsilia izolovateľné.

Napríklad:

  • úvodné inštrukcie sú reprezentované triedami Pomocník (obidve verzie sú prakticky identické), pričom každý projekt ukazuje ich mierne odlišné použitie,
  • viacero tried ukazuje ako zariadiť to, aby sa robot (reprezentujúci určitú entitu v hre) po deaktivácii automaticky skryl a naopak pri aktivácii zobrazil,
  • takmer každá trieda ukazuje spôsob kreslenia vlastného tvaru robota (celá kapitola ukazuje viacero spôsobov)
  • a obidve verzie projektu ukazujú podobný spôsob riešenia detekcie interakcií herných prvkov.

Komentáre zdrojových kódov sú čo najstriedmejšie. Úlohou čitateľa je pokúsiť sa čo najviac kódu interpretovať samostatne.

Táto verzia (okrem iného) ukazuje:

  • spôsob ovládania papáča klávesnicou (obsluhou reakcií v triede Papáč),
  • experimentálny efekt priebežného kombinovania, rozmazávania a tienenia snímok bielou farbou (pozri animovanú ukážku nižšie).

 

obrázok 
Hra po spustení.
  obrázok 
Ukážka hrania.

 

ikonaBalíček so zdrojovými súbormi na prevzatie: papac-klavesnica.7z 2,46 kB (2,40 KiB), 8. 9. 2020

 

Cukríky v tejto verzii sú pulzujúce koláčiky. Keby sme vypli efekt rozmazávania, cukríky by boli krúžky cyklicky meniace svoju veľkosť. Cyklická zmena veľkosti je implementovaná s pomocou triedy Rad. otvárané v novom okne
(obvykle ide o externý odkaz)

Aktivácia (okrem zobrazenia) resetuje cukrík: „zamieša“ jeho vlastnosti. (Deaktivácia cukrík skryje.)

Verzia z „piluliek“

~

import knižnica.*;

public class Cukrík extends GRobot
{
	// Spoločné kreslenie tvaru cukríkov.
	private final static KreslenieTvaru tvar = r -> r.krúžok();


	// (K náhodnej farbe.)
	private final static Zoznam<Farba> farby = new Zoznam<>(
		červená, zelená, modrá, tyrkysová, purpurová, žltá,
		šedá, ružová, oranžová, tmavohnedá, hnedá, svetlohnedá);


	// (K cyklickej zmene veľkosti.)
	private Rad rad = new Rad(7, 13, 2);


	public Cukrík()
	{
		hrúbkaČiary(3.5);
		vlastnýTvar(tvar);

		aktivuj(false);
	}


	// (K cyklickej zmene veľkosti.)
	@Override public void aktivita() { veľkosť(rad.daj()); }

	@Override public void aktivácia()
	{
		// (K cyklickej zmene veľkosti.)
		rad.zamiešaj();

		// (K náhodnej farbe.)
		farba(farby.náhodný());

		náhodnýSmer();
		náhodnáPoloha();

		// (Pri aktivácii zobraz.)
		zobraz();
	}

	// (Pri deaktivácii skry.)
	@Override public void deaktivácia() { skry(); }
}
  HlavnáTrieda »

Verzia z „piluliek“

~

import knižnica.*;

public class HlavnáTrieda extends GRobot
{
	// Patrí k rozmazávaniu prostredia.
	private final static Farba bielyTieň = new Farba(255, 255, 255, 64);


	// Prvky hry.
	private final Papáč papáč;
	private final Zoznam<Cukrík> cukríky = new Zoznam<>();
	private final Pomocník pomocník = new Pomocník();


	private HlavnáTrieda()
	{
		super(600, 600);
		Svet.zbaľ();
		skry();

		// Ukážka primitívneho pomocníka, ktorého sme použili v testovacej
		// fáze projektu. Tieto krátke úvodné inštrukcie boli pozdržané
		// neodporúčaným spôsobom – synchrónnym čakaním.
		/* {
			final String[] pomocník = {"Pomocník",
				"Ovládajte papáča kurzorovými klávesmi a zbierajte pri " +
				"tom pulzujúce cukríky. Hra sa končí vyzbieraním všetkých " +
				"cukríkov.", "Veľa zdaru!"
			};

			for (String odsek : pomocník)
				Svet.vypíšRiadok(odsek, riadok);
			Svet.prekresli();
			Svet.čakajNaKlikAleboKláves();
			strop.vymažTexty();
		} */

		// Vytvorenie prvkov hry.
		papáč = new Papáč();
		for (int i = 0; i < 70; ++i)
			cukríky.pridaj(new Cukrík());

		// Aktivácia pomocníka zobrazí jeho texty a pozastaví časovač.
		pomocník.aktivuj();
	}


	@Override public void tik()
	{
		// (K testu dokončenia hry.)
		boolean zjedené = true;

		// Patrí k rozmazávaniu prostredia.
		podlaha.rozmaž();
		podlaha.vyplň(bielyTieň);

		for (Cukrík cukrík : cukríky)
		{
			if (cukrík.aktívny())
			{
				// (K testu dokončenia hry.)
				zjedené = false;

				if (cukrík.koliduje(papáč))
					cukrík.deaktivuj();
				else
					// Patrí k rozmazávaniu prostredia.
					cukrík.pečiatka();
			}
		}

		if (zjedené)
		{
			// Keď je všetko zjedené, deaktivuje sa papáč a zastaví časovač.
			papáč.deaktivuj();
			Svet.zastavČasovač();
		}
		else
			// Patrí k rozmazávaniu prostredia.
			papáč.pečiatka();
	}

	@Override public void klik()
	{
		// Kliknutie najprv overí, či je aktívny pomocník.
		if (pomocník.aktívny())
		{
			// Ak je, tak ho deaktivuje.
			pomocník.deaktivuj();
		}
		else
		{
			// Inak bez otázok naštartuje novú hru.
			Svet.nekresli();
			for (Cukrík cukrík : cukríky) cukrík.aktivuj();
			papáč.aktivuj();
			Svet.spustiČasovač();
			Svet.kresli();
		}
	}

	@Override public void uvoľnenieKlávesu()
	{
		// (Deaktivácia pomocníka po uvoľnení ľubovoľného klávesu.)
		if (pomocník.aktívny()) pomocník.deaktivuj();
	}


	public static void main(String[] args)
	{
		Svet.nekresli();
		new HlavnáTrieda();
		Svet.kresli();
	}
}
« Cukrík Papáč »

Papáč je žltý krúžok olemovaný čiernou farbou. Trieda zároveň implementuje ovládanie klávesnicou (v reakciách na udalosti klávesnice). Aktivácia papáča, okrem zobrazenia, pošle domov. (Deaktivácia ho skryje.)

Verzia z „piluliek“

~

import knižnica.*;

public class Papáč extends GRobot
{
	public Papáč()
	{
		ohranič();
		hrúbkaČiary(2.5);
		veľkosť(10.5);
		zdvihniPero();

		// (Vlastný tvar papáča.)
		vlastnýTvar(r ->
			{
				Farba f = r.farba();
				r.farba(žltá);
				r.kruh();
				r.farba(f);
				r.kružnica();
			});

		aktivuj(false);
	}


	@Override public void stlačenieKlávesu()
	{
		switch (ÚdajeUdalostí.kláves())
		{
			case Kláves.HORE:   rýchlosť(7, false); break;
			case Kláves.DOLE:   rýchlosť(-7, false); break;
			case Kláves.VPRAVO: rýchlosťPosunu(7, false); break;
			case Kláves.VĽAVO:  rýchlosťPosunu(-7, false); break;
		}
	}

	@Override public void uvoľnenieKlávesu()
	{
		switch (ÚdajeUdalostí.kláves())
		{
			case Kláves.HORE:
			case Kláves.DOLE:   rýchlosť(0, false); break;
			case Kláves.VPRAVO:
			case Kláves.VĽAVO:  rýchlosťPosunu(0, false); break;
		}
	}


	// (Pri aktivácii choď domov a zobraz.)
	@Override public void aktivácia() { domov(); zobraz(); }

	// (Pri deaktivácii skry.)
	@Override public void deaktivácia() { skry(); }
}
« HlavnáTrieda Pomocník »

Verzia z „piluliek“

~

import knižnica.*;

public class Pomocník extends GRobot
{
	// (Texty pomocníka.)
	private final static String[] pomocník = {"Pomocník", "",
		"Ovládajte papáča kurzorovými klávesmi a zbierajte",
		"pri tom pulzujúce cukríky. Hra sa končí vyzbieraním",
		"všetkých cukríkov.", "", "Veľa zdaru!"
	};

	// (Vnútorný koordinačný príznak.)
	private boolean textyZobrazené = false;


	// Konštruktor so základnými nastaveniami.
	public Pomocník()
	{
		skry();
		farba(tmavoatramentová);
		písmo("Cambria", 20);
		kresliNaStrop();
		hrúbkaČiary(3);
	}


	// Metóda, ktorá nakreslí texty (na strop – podľa konfigurácie
	// v konštruktore).
	public void nakresli()
	{
		Farba f = farba();
		skočNa(stred);

		farba(papierová);
		vyplňObdĺžnik(250, 20 + pomocník.length * 15);
		farba(uhlíková);
		kresliObdĺžnik(250, 20 + pomocník.length * 15);

		farba(f);
		skoč(pomocník.length * 15 - 15);
		for (String text : pomocník)
		{
			text(text);
			odskoč(30);
		}
	}


	// (Pri aktivácii zálohuje grafiku stropu a nakreslí texty, ak neboli
	// nakreslené.)
	@Override public void aktivácia()
	{
		if (!textyZobrazené)
		{
			strop.zálohujGrafiku(this);
			nakresli();
			textyZobrazené = true;
			Svet.zastavČasovač();
		}
	}

	// (Pri deaktivácii obnoví grafiku stropu, ak boli predtým texty
	// nakreslené.)
	@Override public void deaktivácia()
	{
		if (textyZobrazené)
		{
			strop.obnovGrafiku(this);
			textyZobrazené = false;
			Svet.spustiČasovač();
		}
	}
}
« Papáč  

Táto verzia ukazuje jeden z možných spôsobov ovládania papáča myšou. Ovládanie a celé správanie papáča je implementované v hlavnej triede (pričom nejde o žiadnu „špeciálnu“ implementáciu; je to robot, ktorý má mnoho preddefinovaných funkcií). Samotná papáčova trieda je veľmi jednoduchá – obsahuje iba konštruktor, ktorý papáča inicializuje.

Zaujímavé je všimnúť si časti hlavnej triedy, ktoré sú označené komentárom „// (K blikaniu papáča.)“ Tie sa podieľajú na tom, že tento papáč pravidelne bliká v dvoch odtieňoch šedej.

 

obrázok 
Hra po spustení.
  obrázok 
Ukážka hrania.

 

ikonaBalíček so zdrojovými súbormi na prevzatie: papac-mys.7z 2,94 kB (2,87 KiB), 8. 9. 2020

 

Tieto cukríky sú „blikotavými pilulkami“ – obdĺžnikmi so zaoblenými rohmi, ktorých farba sa cyklicky mení v rámci preddefinovanej palety. Striedanie farieb je implementované s pomocou triedy Rad. otvárané v novom okne
(obvykle ide o externý odkaz)

Verzia z „koláčikov“

~

import knižnica.*;

public class Cukrík extends GRobot
{
	// Spoločné kreslenie tvaru cukríkov.
	private final static KreslenieTvaru tvar = r -> r.obdĺžnik();


	// (K cyklickej zmene farieb.)
	private final static Zoznam<Farba> farby = new Zoznam<>(
		tmavožltá, oranžová, ružová, červená, purpurová, modrá,
		tmaváNebeská, svetloatramentová, tmavotyrkysová, zelená,
		svetlošedá, čierna);


	// (K cyklickej zmene farieb.)
	private Rad rad = new Rad(0, farby.veľkosť() - 1);


	public Cukrík(double veľkosť)
	{
		pomer(2.0);
		veľkosť(veľkosť);
		hrúbkaČiary(5 + ((veľkosť - 10.0) / 10.0));
		zaoblenie(2.0 * veľkosť);
		vlastnýTvar(tvar);

		aktivuj(false);
	}


	// (K cyklickej zmene farieb.)
	@Override public void aktivita() { farba(farby.daj(rad.daj())); }

	@Override public void aktivácia()
	{
		// (K cyklickej zmene farieb.)
		rad.zamiešaj();

		náhodnýSmer();
		náhodnáPoloha();

		// (Pri aktivácii zobraz.)
		zobraz();
	}

	// (Pri deaktivácii skry.)
	@Override public void deaktivácia() { skry(); }
}
  HlavnáTrieda »

Verzia z „koláčikov“

~

import knižnica.*;

public class HlavnáTrieda extends GRobot
{
	// Prvky hry.
	private final Papáč papáč;
	private final Zoznam<Cukrík> cukríky = new Zoznam<>();
	private final Pomocník pomocník = new Pomocník();


	// (K blikaniu papáča.)
	private int blikač = 0;


	// Príznak ukončenia hry.
	private boolean hotovo = false;


	private HlavnáTrieda()
	{
		super(600, 600);
		Svet.zbaľ();
		skry();

		// Ukážka primitívneho pomocníka, ktorého sme použili v testovacej
		// fáze projektu. Tieto krátke úvodné inštrukcie boli pozdržané
		// neodporúčaným spôsobom – synchrónnym čakaním.
		/* {
			final String[] pomocník = {"Pomocník",
				"Ovládajte papáča klikaním ľubovoľného tlačidla myši. " +
				"Zbierajte cukríky. Začnite s menšími, pretože príliš " +
				"veľké papáč nezvládne.", "Veľa zdaru!"
			};

			for (String odsek : pomocník)
				Svet.vypíšRiadok(odsek, riadok);
			Svet.prekresli();
			Svet.čakajNaKlikAleboKláves();
			strop.vymažTexty();
		} */

		// Vytvorenie prvkov hry.
		papáč = new Papáč();
		for (int i = 0; i < 15; ++i)
			cukríky.pridaj(new Cukrík(5 + i * 3));

		// Prvá kontrola prvkov hry.
		kontrolaCukríkov();
		kontrolaPapáča();

		// Aktivácia pomocníka zobrazí jeho texty a pozastaví časovač.
		pomocník.aktivuj();
	}


	// Táto metóda slúži na kontrolu (prílišnej) kolízie cukríkov
	// a premiestnenie (resp. reset) kolidujúceho cukríka na nové
	// umiestnenie (aktiváciou). Kontrola sa vykonáva pri štarte novej hry.
	private void kontrolaCukríkov()
	{
		for (int i = 0; i < 100; ++i)
		{
			boolean žiadnaKolízia = true;
			for (Cukrík cukrík1 : cukríky)
				for (Cukrík cukrík2 : cukríky)
					if (!cukrík1.equals(cukrík2) &&
						cukrík1.koliduje(cukrík2))
					{
						žiadnaKolízia = false;
						cukrík1.aktivuj();
					}
			if (žiadnaKolízia) break;
		}
	}

	// Táto metóda slúži na overenie kolízie papáča a cukríkov a jeho
	// premiestnenie v prípade zistenia kolízie. Táto kontrola sa vykonáva
	// pri kažnom vytvorení nového papáča (vrátane štartu novej hry).
	private void kontrolaPapáča()
	{
		for (int i = 0; i < 100; ++i)
		{
			boolean žiadnaKolízia = true;
			for (Cukrík cukrík : cukríky)
				if (cukrík.viditeľný() && papáč.koliduje(cukrík))
				{
					žiadnaKolízia = false;
					papáč.náhodnáPoloha();
				}
			if (žiadnaKolízia) break;
		}
	}


	@Override public void klik()
	{
		// Kliknutie najprv overí, či je aktívny pomocník.
		if (pomocník.aktívny())
		{
			// Ak je, tak ho deaktivuje.
			pomocník.deaktivuj();
		}
		// Potom sa overí, či je viditeľný papáč.
		else if (papáč.viditeľný())
		{
			// Viditeľného papáča klikanie striedavo pošle do nového
			// cieľa alebo zastaví (podľa toho, či sa hýbe):
			if (papáč.smerujeDoCieľa())
				papáč.zrušCieľ();
			else
				papáč.cieľNaMyš();
		}
		else
		{
			// Ak papáč nie je viditeľný, tak zobrazí nového.
			// (Životy sa nerátajú. Papáčov je nekonečne veľa.)

			if (hotovo)
			{
				// Pričom ak sa hra skončila, tak začne novú.
				hotovo = false;
				papáč.veľkosť(10);
				papáč.hrúbkaČiary(5);
				for (Cukrík cukrík : cukríky)
					cukrík.aktivuj();
				kontrolaCukríkov();
			}

			papáč.náhodnáPoloha();
			papáč.zobraz();
			kontrolaPapáča();
		}
	}

	@Override public void tik()
	{
		if (papáč.viditeľný())
		{
			// (K blikaniu papáča.)
			if (0 == ++blikač % 10)
			{
				if (0 == blikač / 10 % 2)
					papáč.farba(antracitová);
				else
					papáč.farba(papierová);
			}


			// Vykonanie interakcií spolu s kontrolou konca hry.

			hotovo = true;

			for (Cukrík cukrík : cukríky)
			{
				if (cukrík.viditeľný())
				{
					hotovo = false;
					if (papáč.koliduje(cukrík))
					{
						if (papáč.veľkosť() >= cukrík.veľkosť())
						{
							// Cukrík s primeranou veľkosťou je zjedený.
							cukrík.deaktivuj();
							papáč.veľkosť(3.0 + papáč.veľkosť());
							papáč.hrúbkaČiary(5 + ((papáč.veľkosť()
								- 10.0) / 10.0));
						}
						else
						{
							// Príliš veľký cukrík papáč nezvládne.
							papáč.zrušCieľ();
							papáč.skry();
						}
					}
				}
			}


			// Po skončení hry sa papáč zastaví a skryje.

			if (hotovo)
			{
				papáč.zrušCieľ();
				papáč.skry();
			}
		}
	}


	public static void main(String[] args)
	{
		Svet.nekresli();
		new HlavnáTrieda();
		Svet.kresli();
	}
}
« Cukrík Papáč »

Verzia z „koláčikov“

~

import knižnica.*;

public class Papáč extends GRobot
{
	public Papáč()
	{
		// (Úprava vizuálnych vlastností.)
		hrúbkaČiary(5);
		zdvihniPero();

		// (Vlastný tvar papáča.)
		vlastnýTvar(r -> r.krúžok());

		// (Úprava fyzikálnych vlastností.)
		najväčšiaRýchlosť(20);
		zrýchlenie(1, false);
		náhodnýSmer();
		náhodnáPoloha();
	}
}
« HlavnáTrieda Pomocník »

Verzia z „koláčikov“

~

import knižnica.*;

public class Pomocník extends GRobot
{
	// (Texty pomocníka.)
	private final static String[] pomocník = {"Pomocník", "",
		"Ovládajte papáča klikaním ľubovoľného tlačidla myši.",
		"Zbierajte cukríky. Začnite s menšími, pretože",
		"príliš veľké papáč nezvládne.", "", "Veľa zdaru!"
	};

	// (Vnútorný koordinačný príznak.)
	private boolean textyZobrazené = false;


	// Konštruktor so základnými nastaveniami.
	public Pomocník()
	{
		skry();
		farba(tmavoatramentová);
		písmo("Cambria", 20);
		kresliNaStrop();
		hrúbkaČiary(3);
	}


	// Metóda, ktorá nakreslí texty (na strop – podľa konfigurácie
	// v konštruktore).
	public void nakresli()
	{
		Farba f = farba();
		skočNa(stred);

		farba(papierová);
		vyplňObdĺžnik(250, 20 + pomocník.length * 15);
		farba(uhlíková);
		kresliObdĺžnik(250, 20 + pomocník.length * 15);

		farba(f);
		skoč(pomocník.length * 15 - 15);
		for (String text : pomocník)
		{
			text(text);
			odskoč(30);
		}
	}


	// (Pri aktivácii zálohuje grafiku stropu a nakreslí texty, ak neboli
	// nakreslené.)
	@Override public void aktivácia()
	{
		if (!textyZobrazené)
		{
			strop.zálohujGrafiku(this);
			nakresli();
			textyZobrazené = true;
			Svet.zastavČasovač();
		}
	}

	// (Pri deaktivácii obnoví grafiku stropu, ak boli predtým texty
	// nakreslené.)
	@Override public void deaktivácia()
	{
		if (textyZobrazené)
		{
			strop.obnovGrafiku(this);
			textyZobrazené = false;
			Svet.spustiČasovač();
		}
	}
}
« Papáč  

Zvoľte verziu.