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

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

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

Dátum: 25. 3. 2020, pred štyrmi rokmi

Ukážka jednej z možností ako implementovať mechanizmus kolízií. Toto je jedna z tých komplikovanejších možností, ale dúfame, že vďaka komentárom z nej čitateľ bude vedieť odvodiť aj zjednodušené verzie.

 

Trieda Hra.java

~

import knižnica.*;

public class Hra extends GRobot
{
	/**## Takto označené komentáre súvisia s kolíziami. ##**/

	private final Zoznam<Plošinka> plošinky = new Zoznam<>();
	private final Zoznam<Guľôčka> guľôčky = new Zoznam<>();

	private int čas = 0; // Interval na „generovanie“ nových guľôčok

	private Hra()
	{
		super(400, 600);
		Svet.nekresli();
		if (Svet.prvéSpustenie())
		{
			Svet.zbaľ();
			Svet.vystreď();
		}
		skry();

		for (int i = 0; i < 8; ++i)
			nováPlošinka(i * 65);

		nováHra();
	}

	public void nováPlošinka(int zvisláPoloha)
	{
		Plošinka plošinka = new Plošinka();
		plošinka.polohaY(Svet.náhodnéReálneČíslo(-198, -202) + zvisláPoloha);
		plošinky.pridaj(plošinka);
	}

	public void nováHra()
	{
		Svet.nekresli();

		for (Plošinka plošinka : plošinky)
		{
			plošinka.polohaX(0);
			plošinka.aktivuj();
		}

		for (Guľôčka guľôčka : guľôčky)
			guľôčka.deaktivuj();

		čas = 0;
		Svet.kresli();
	}

	public void nováGuľôčka()
	{
		Guľôčka nováGuľôčka = null;

		for (Guľôčka guľôčka : guľôčky)
			if (guľôčka.neaktívny())
			{
				nováGuľôčka = guľôčka;
				break;
			}

		if (null == nováGuľôčka)
		{
			nováGuľôčka = new Guľôčka();
			guľôčky.pridaj(nováGuľôčka);
		}

		nováGuľôčka.náhodnáPoloha();
		nováGuľôčka.polohaY(Svet.najväčšieY());
		nováGuľôčka.rýchlosť(0, false);
		nováGuľôčka.aktivuj();
	}


	@Override public void uvoľnenieKlávesu()
	{
		switch (ÚdajeUdalostí.kláves())
		{
		case Kláves.VK_H:
			// Pauza.
			if (Svet.časovačAktívny())
				Svet.zastavČasovač();
			else
				Svet.spustiČasovač();
			break;
		}
	}

	@Override public void tik()
	{
		if (0 == ++čas % 50) nováGuľôčka();

		/**## Toto je hlavný cyklus detekcie kolízií medzi guľôčkami ##**/
		/**## a plošinkami. ##**/
		for (Guľôčka guľôčka : guľôčky)
			if (guľôčka.aktívny())
			{
				// Kolízie kontrolujeme len pre aktívne guľôčky.
				for (Plošinka plošinka : plošinky)
				{
					// Rovnako len pre aktívne plošinky.
					if (plošinka.aktívny() &&
						guľôčka.koliduje(plošinka))
					{
						// Keď je kolízia potvrdená, tak upravíme vlastnosti
						// guľôčky tak, aby sme simulovali odrazenie sa od
						// pohybujúceho sa objektu…
						// (Plošinka sa pohybuje nerušene ďalej.)
						guľôčka.odskoč(guľôčka.rýchlosť() -
							(guľôčka.rýchlosť() < 0 ? -1 : 1));

						guľôčka.rýchlosť(-0.75 * guľôčka.rýchlosť());
						guľôčka.rýchlosťPosunu(
							plošinka.rýchlosťPosunu() / 2, false);
						guľôčka.zrýchleniePosunu(-0.1, false);
						guľôčka.zastavPoSpomaleníPosunu();

						break;
					}
				}
			}

		/**## Tu by boli ďalšie detekcie kolízií. ##**/
	}

	public static void main(String[] args)
	{
		Svet.použiKonfiguráciu("Hra.cfg");
		new Hra();
	}
}

Trieda Guľôčka.java

~

import knižnica.*;

public class Guľôčka extends GRobot
{
	public Guľôčka()
	{
		// Oraničenie je upravené tak, aby guľôčka nesmela ani o kúsok
		// vyjsť za pravý alebo ľavý okraj.
		ohranič(Svet.najväčšieX() - veľkosť(),
			Svet.najväčšieY(), PLOT);

		zdvihniPero();
		skoč(Svet.najväčšieY()); // (presun k hornému okraju)
		vpravo(180); // („čelom vzad“)
		najväčšiaRýchlosť(20);
		zrýchlenie(1);
	}

	/**## Táto metóda slúži na zistenie toho, či táto guľôčka koliduje ##**/
	/**## so zadanou plošinkou. Metóda používa metódu z triedy Plošinka: ##**/
	/**## bodVPlošinke. ##**/
	public boolean koliduje(Plošinka plošinka)
	{
		// Postupne skontrolujeme 12 bodov po obvode guľôčky. (Používame
		// celočíselný uhol u, pretože to na tieto účely stačí.)
		for (int u = 0; u < 360; u += 30)
		{
			// Poloha guľôčky je bod v jej strede. Ten prevezmeme:
			Bod bod = poloha();

			// A prepočítame ho podľa uhla u tak, aby ležal na obvode
			// guľôčky:
			bod.posuňVSmere(u, veľkosť());

			// Overenie, či sa bod ležiaci na obvode guľôčky nachádza
			// vo vnútri plošinky (detaily tohto overenia si určuje
			// plošinka):
			if (plošinka.bodVPlošinke(bod)) return true;
		}
		return false;
	}

	@Override public void kresliTvar()
	{
		krúžok();
	}

	@Override public void aktivácia()
	{
		zobraz();
	}

	@Override public void deaktivácia()
	{
		rýchlosťPosunu(0, false);
		zrýchleniePosunu(0, false);
		skry();
	}

	@Override public void mimoHraníc()
	{
		// Vtedy a len vtedy, keď guľôčka prepadne pod spodnú hranicu sa
		// deaktivuje…
		if (polohaY() < Svet.najmenšieY() + veľkosť()) deaktivuj();
	}
}

Trieda Plošinka.java

~

import knižnica.*;

public class Plošinka extends GRobot
{
	private int šírka;

	public Plošinka()
	{
		this(50); // Volanie „toho druhého“ konštruktora (nižšie).
	}

	public Plošinka(int šírka)
	{
		this.šírka = šírka;
		ohranič(ODRAZ);
		zdvihniPero();
		rýchlosťPosunu(Svet.náhodnéReálneČíslo(-6, 6), false);
		mimoHraníc();
	}

	/**## Táto metóda slúži na rýchle overenie prítomnosti bodu ##**/
	/**## v plošinke, ktorej sme definovali vlastnú šírku (nevyužili ##**/
	/**## sme preddefinovanú vlastnosť robota pomer). ##**/
	public boolean bodVPlošinke(Poloha bod)
	{
		// V guľôčke (v metóde koliduje) je spomínané, že „detaily overenia
		// (kolízie) si určuje plošinka.“ Toto je ten detail a je veľmi
		// prostý – len zistenie, či zadaný bod (ktorý posielame z metódy
		// koliduje v triede Guľôčka) leží v obdĺžniku plošinky (alebo nie):
		return bodVObdĺžniku(bod, šírka, veľkosť());
	}

	// („Patrilo by sa“ sem doprogramovať aj metódy na čítanie a zápis
	// šírky, ktorú momentálne nastavujeme iba jednorazovo prostredníctvom
	// konštruktora, pretože to je v súlade so zásadami OOP.)

	@Override public void kresliTvar()
	{
		obdĺžnik(šírka, veľkosť());
	}

	@Override public void aktivácia()
	{
		priehľadnosť(1.0);
	}

	@Override public void deaktivácia()
	{
		priehľadnosť(0.25);
	}

	@Override public void mimoHraníc()
	{
		// Pri kontakte s hranicou (pravou alebo ľavou, keďže sa pohybujeme
		// len doprava a doľava) sa upraví rýchlosť posunu a zmení (obráti)
		// smer pohybu plošinky.

		rýchlosťPosunu(-rýchlosťPosunu() *
			Svet.náhodnéReálneČíslo(.75, 1.5));

		if (rýchlosťPosunu() > 0)
		{
			if (rýchlosťPosunu() > 6) rýchlosťPosunu(6);
			else if (rýchlosťPosunu() < 2) rýchlosťPosunu(2);
		}
		else
		{
			if (rýchlosťPosunu() < -6) rýchlosťPosunu(-6);
			else if (rýchlosťPosunu() > -2) rýchlosťPosunu(-2);
		}
	}
}

 

obrázok 
Ukážka „hry“ po spustení.