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

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

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

Dátum: 23. 7. 2020, pred štyrmi rokmi

Tento projekt pôvodne pochádza z roku 2016. Jeho zdrojový kód je aktualizovaný tak, aby fungoval s verziou programovacieho rámca 2.0. Pôvodne z neho mal byť vytvorený krátky tutoriál, avšak keď ani po štyroch rokoch nevzniklo dostatočne veľké časové okno na jeho vytvorenie, bol publikovaný v podobe projektu bez podrobného opisu a komentárov (ktoré by boli v tutoriáli).

  
obrázok 
Ukážka hry po spustení (po použití „čítov“ C – zmena farby pozadia a T – zmena vzhľadu mesta). 
 

Balíček s projektom na prevzatie:

 

~

import knižnica.Farba;
import knižnica.GRobot;
import knižnica.Kláves;
import knižnica.ObsluhaUdalostí;
import knižnica.Svet;
import knižnica.ÚdajeUdalostí;
import knižnica.Zoznam;

public class Bombardér extends GRobot
{
	private final static Zoznam<Farba> farby = new Zoznam<Farba>(
		svetlotyrkysová, svetložltá, svetlooranžová, svetlozelená,
		tmavomodrá, čierna);

	private final Loď loď = new Loď();
	private boolean reaktivujLoď = true;
	private int tvar = Nastavenia.TVAR_MESTA;

	private Bombardér()
	{
		Svet.farbaPozadia(farby.ďalší());
		skry();

		for (int i = 0; i < Nastavenia.POČET_BÔMB; ++i) new Bomba();
		for (int i = 0; i < Nastavenia.POČET_BLOKOV; ++i) new BlokMesta();

		BlokMesta.usporiadajBloky();
		BlokMesta.tvarujBloky(tvar);
		Svet.spustiČasovač();

		new ObsluhaUdalostí()
		{
			@Override public void tik()
			{
				if (Svet.neboloPrekreslené())
					Svet.prekresli();
			}

			@Override public void stlačenieKlávesu()
			{
				boolean vpravo = ÚdajeUdalostí.kláves(Kláves.VPRAVO);
				if (vpravo || ÚdajeUdalostí.kláves(Kláves.VĽAVO))
					Bomba.vyhoď(loď, vpravo);
				/* číty – začiatok */
				else if (ÚdajeUdalostí.kláves(Kláves.VK_S))
				{
					loď.zmeňStav(Loď.ČAKÁ);
					loď.zmeňStav(Loď.FUNGUJE);
				}
				else if (ÚdajeUdalostí.kláves(Kláves.VK_Z))
					loď.zmeňStav(Loď.ZNIČENÁ);
				else if (ÚdajeUdalostí.kláves(Kláves.VK_X))
					BlokMesta.prerieď();
				else if (ÚdajeUdalostí.kláves(Kláves.VK_V)) // -MEDZERA-
					loď.zmeňStav(Loď.HOTOVO);
				else if (ÚdajeUdalostí.kláves(Kláves.VK_R))
					loď.skočNa(Svet.najväčšieX(), loď.polohaY());
				else if (ÚdajeUdalostí.kláves(Kláves.VK_O))
					BlokMesta.obnovBloky();
				else if (ÚdajeUdalostí.kláves(Kláves.VK_C))
					Svet.farbaPozadia(farby.ďalší());
				else if (ÚdajeUdalostí.kláves(Kláves.VK_T))
					BlokMesta.tvarujBloky(++tvar);
				else if (ÚdajeUdalostí.kláves(Kláves.VK_H))
				{
					if (loď.viditeľný())
						loď.skry();
					else
						loď.zobraz();
				}
				/* číty – koniec */
				else if (ÚdajeUdalostí.kláves(Kláves.VK_P))
				{
					if (Svet.časovačAktívny())
						Svet.zastavČasovač();
					else
						Svet.spustiČasovač();
				}

				if (!Svet.časovačAktívny()) Svet.prekresli();
			}

			@Override public void klik()
			{
				boolean vpravo = ÚdajeUdalostí.tlačidloMyši(PRAVÉ);
				if (vpravo || ÚdajeUdalostí.tlačidloMyši(ĽAVÉ))
					Bomba.vyhoď(loď, vpravo);
			}
		};

		aktivuj();
	}

	@Override public void aktivita()
	{
		if (BlokMesta.nastalaZmena())
		{
			if (BlokMesta.hotovo())
			{
				deaktivuj();
				loď.zmeňStav(Loď.HOTOVO);
			}
			else
				BlokMesta.usporiadajBloky();
		}

		if (reaktivujLoď && !BlokMesta.
			vPohybe() && !Bomba.vPohybe())
		{
			loď.zmeňStav(Loď.ČAKÁ);
			loď.zmeňStav(Loď.FUNGUJE);
			reaktivujLoď = false;
		}
	}

	@Override public void pasivita()
	{
		if (BlokMesta.nastalaZmena())
		{
			BlokMesta.usporiadajBloky();
			BlokMesta.tvarujBloky(tvar);

			if (!BlokMesta.hotovo())
			{
				reaktivujLoď = true;
				aktivuj();
			}
		}
	}

	public static void main(String... args)
	{
		Svet.použiKonfiguráciu();
		Svet.nekresli();
		new Bombardér();
	}
}

~

import knižnica.GRobot;
import knižnica.Svet;
import knižnica.Zoznam;

import java.util.Arrays;
import java.util.Comparator;

public class BlokMesta extends GRobot
{
	private final static Zoznam<BlokMesta> bloky = new Zoznam<BlokMesta>();
	private final static SériaZvukov zvukZničenia = new SériaZvukov("bomb-hit.wav");
	private final static BlokMesta štvrť[][] = new BlokMesta[100][100];
	private final static int výška[] = new int[100];
	private final static int VEĽKOSŤ_MREŽE = 20;
	private static boolean nastalaZmena = false;


	public static boolean vPohybe()
	{
		for (BlokMesta blok : bloky)
			if (blok.viditeľný() && blok.aktívny())
				return true;
		return false;
	}

	public static boolean hotovo()
	{
		for (BlokMesta blok : bloky)
			if (blok.viditeľný())
				return false;
		return true;
	}

	public static boolean nastalaZmena()
	{
		return nastalaZmena;
	}

	public static void bombarduj(Bomba bomba)
	{
		if (bomba.viditeľný())
			for (BlokMesta blok : bloky)
				if (blok.viditeľný() && bomba.koliduje(blok))
				{
					zvukZničenia.prehraj();
					bomba.opotrebuj();
					blok.skry();
					return;
				}
	}

	public static void prerieď()
	{
		int i = 0;
		for (BlokMesta blok : bloky)
			if (blok.viditeľný())
			{
				zvukZničenia.prehraj();
				blok.skry();
				if (++i >= 10) break;
			}
	}

	public static boolean havaruj(Loď loď)
	{
		for (BlokMesta blok : bloky)
			if (blok.viditeľný() && loď.bodVElipse(blok, 0.5))
				return true;
		return false;
	}

	public static void obnovBloky()
	{
		for (BlokMesta blok : bloky)
			if (blok.skrytý())
				blok.domov();
	}

	public static void usporiadajBloky()
	{
		if (nastalaZmena)
		{
			for (BlokMesta[] panelák : štvrť)
				Arrays.fill(panelák, null);

			Arrays.fill(výška, 0);

			for (BlokMesta blok : bloky)
				if (blok.viditeľný())
				{
					double mrežaX = (blok.polohaX() - Svet.najmenšieX()) /
						VEĽKOSŤ_MREŽE;
					double mrežaY = (blok.polohaY() - Svet.najmenšieY()) /
						VEĽKOSŤ_MREŽE;

					int indexX = (int)mrežaX;
					int indexY = (int)mrežaY;

					if (indexX >= 0 && indexX < štvrť.length &&
						indexY >= 0 && indexY < štvrť[indexX].length)
					{
						// blok.vložBlok(štvrť[indexX]);
						blok.vložBlok(štvrť[indexX], výška[indexX]++);
					}
				}

			for (int x = 0; x < štvrť.length; ++x)
				for (int y = 0; y < štvrť[x].length; ++y)
				{
					BlokMesta blok = štvrť[x][y];
					if (null != blok)
						blok.cieľ(Svet.najmenšieX() + x * VEĽKOSŤ_MREŽE +
							VEĽKOSŤ_MREŽE / 2,
							Svet.najmenšieY() + y * VEĽKOSŤ_MREŽE +
							VEĽKOSŤ_MREŽE / 2);
				}

			nastalaZmena = false;
		}
	}

	public static void tvarujBloky(int tvar)
	{
		tvar = Math.abs(tvar) % 6;

		for (int x = 0; x < štvrť.length; ++x)
		{
			double v = (double)výška[x];
			for (int y = 0; y < štvrť[x].length; ++y)
			{
				BlokMesta blok = štvrť[x][y];
				if (null == blok) break; else switch (tvar)
				{
				case 0:
					blok.šírka = Math.max(0.1, 1.0 - ((double)y / v));
					break;

				case 1:
					// blok.šírka = Math.max(0.1, (double)y / v);
					blok.šírka = Svet.náhodnéReálneČíslo(0.2, 0.8);
					break;

				case 2:
					blok.šírka = Svet.náhodnéReálneČíslo(0.3, 1.5);
					break;

				case 3:
					blok.šírka = Svet.náhodnéReálneČíslo(0.5, 2.0);
					break;

				case 4:
					blok.šírka = 1.0;
					break;

				case 5:
					blok.šírka = Math.max(0.8, 1.0 - (((double)y / v) / 5));
					break;
				}
			}
		}
	}


	private double šírka = 1.0;

	private void vložBlok(BlokMesta[] panelák)
	{
		double polohaY = polohaY();
		int kde = panelák.length - 1;
		int j = kde;

		for (int i = 0; i < panelák.length; ++i)
		{
			BlokMesta blok = panelák[i];
			if (null == blok || polohaY < blok.polohaY())
			{
				kde = i;
				break;
			}
		}

		while (j > kde && null == panelák[j - 1]) --j;
		for (; j > kde; --j) panelák[j] = panelák[j - 1];
		panelák[j] = this;
	}


	// Porovnávač mestských blokov
	private static Comparator<BlokMesta> porovnajBloky =
		new Comparator<BlokMesta>()
		{
			public int compare(BlokMesta blok1, BlokMesta blok2)
			{ return (int)(blok1.polohaY() - blok2.polohaY()); }
		};

	// Ďalší pokus o využitie binárneho vkladania – vyžaduje zadanie výšky
	// paneláka
	private void vložBlok(BlokMesta[] panelák, int výška)
	{
		// http://codereview.stackexchange.com/questions/36221/binary-search-
		// for-inserting-in-array

		int j = Arrays.binarySearch(panelák, 0, výška, this, porovnajBloky);

		// Keď vkladáme úplne novú (unikátnu) hodnotu, tak musíme upraviť
		// nájdený index, pretože je záporný:
		if (j < 0) j = -(++j);

		// Posunieme prvky poľa a vložíme blok
		System.arraycopy(panelák, j, panelák, j + 1, výška - j);
		panelák[j] = this;
	}


	public BlokMesta()
	{
		bloky.add(this);

		zdvihniPero();
		farba(tmavošedá);
		hrúbkaČiary(2);
		uhol(270);
		veľkosť(VEĽKOSŤ_MREŽE / 2);
		zobrazDoma();
		domov();

		rýchlosť(3);
	}


	@Override public void domov()
	{
		nastalaZmena = true;
		super.domov();
		náhodnáPoloha();
		aktivuj();
	}

	@Override public void skry()
	{
		nastalaZmena = true;
		super.skry();
	}

	@Override public void dosiahnutieCieľa()
	{
		uhol(270);
	}

	@Override public void kresliTvar()
	{
		vyplňObdĺžnik(šírka);
		// štvorec();
	}
}

~

import knižnica.GRobot;
import knižnica.Svet;
import knižnica.Zoznam;

public class Bomba extends GRobot
{
	private final static Zoznam<Bomba> bomby = new Zoznam<Bomba>();
	private final static SériaZvukov zvukZhodenia =
		new SériaZvukov("drop-bomb.wav");
	private final static SériaZvukov zvukPrepadu =
		new SériaZvukov("bomb-lost.wav");

	private boolean vpravo = true;
	private int výdrž = 0;


	public static boolean vPohybe()
	{
		for (Bomba bomba : bomby)
			if (bomba.viditeľný() && bomba.aktívny())
				return true;
		return false;
	}

	public static boolean vyhoď(Loď loď, boolean vpravo)
	{
		for (Bomba bomba : bomby)
			if (bomba.skúsVyhodiť(loď, vpravo))
			{
				zvukZhodenia.prehraj();
				return true;
			}
		return false;
	}


	public Bomba()
	{
		bomby.add(this);

		farba(svetlomodrá);
		zdvihniPero();
		veľkosť(5);
		uhol(270);

		rýchlosť(4, false);
		skry();
	}

	private boolean skúsVyhodiť(Loď loď, boolean vpravo)
	{
		if (loď.aktívny() && !viditeľný())
		{
			this.vpravo = vpravo;
			skočNa(loď);
			aktivuj();
			return true;
		}
		return false;
	}

	public void opotrebuj()
	{
		if (výdrž > 0) --výdrž;
		else skry();
	}

	@Override public void aktivita()
	{
		if (polohaX() < Svet.najmenšieX() - (veľkosť() * 2.0) ||
			polohaX() > Svet.najväčšieX() + (veľkosť() * 2.0)) deaktivuj();
		else if (polohaY() < Svet.najmenšieY() + (veľkosť() * 2.0))
		{
			zvukPrepadu.prehraj();
			deaktivuj();
		}
		else
		{
			BlokMesta.bombarduj(this);
			if (uhol() < 265 || uhol() > 275)
				vpravo(vpravo ? 1 : -1);
		}
	}

	@Override public void aktivácia()
	{
		výdrž = (int)Svet.náhodnéCeléČíslo(
			Nastavenia.NAJMENŠIA_VÝDRŽ_BÔMB, Nastavenia.NAJVÄČŠIA_VÝDRŽ_BÔMB);
		smer(vpravo ? 0 : 180);
		zobraz();
	}

	@Override public void deaktivácia()
	{
		skry();
	}

	@Override public void kresliTvar()
	{
		vyplňElipsu(0.8);
	}
}

~

import knižnica.GRobot;

public class StavovýObjekt extends GRobot
{
	private int stav = 0;

	public void nastavStav(int stav)
	{
		this.stav = stav;
	}

	public void zmeňStav(int stav)
	{
		if (this.stav != stav && zmenaStavu(this.stav, stav))
			this.stav = stav;
	}

	public int stav()
	{
		return stav;
	}

	public boolean stav(int porovnaj)
	{
		return stav == porovnaj;
	}

	public boolean zmenaStavu(int starý, int nový)
	{
		return true;
	}
}

~

import knižnica.Svet;

public class Loď extends StavovýObjekt
{
	public final static int ČAKÁ = -1;
	public final static int ZNIČENÁ = 0;
	public final static int FUNGUJE = 1;
	public final static int HOTOVO = 2;

	public Loď()
	{
		veľkosť(30);
		domov(Svet.najmenšieX() - veľkosť(),
			Svet.najväčšieY() - veľkosť(), 0);

		zdvihniPero();
		hrúbkaČiary(2.6);

		maximálnaRýchlosťOtáčania(3);
		maximálnaRýchlosť(13);
		rýchlosť(3, false);
		zmeňStav(ČAKÁ);
	}

	@Override public void aktivita()
	{
		if (stav(HOTOVO))
		{
			if (polohaY() > Svet.najväčšieY() + (veľkosť() * 1.5))
			{
				zrušCieľ();
				deaktivuj();
				dosiahnutieCieľa();
			}
		}
		else
		{
			if (polohaX() > Svet.najväčšieX() - veľkosť())
			{
				if (polohaY() > Svet.najmenšieY() + (veľkosť() * 1.5))
					skoč(
						2 * (Svet.najmenšieX() + veľkosť()),
						-veľkosť() * 1.5);
				else
				{
					if (BlokMesta.hotovo())
						zmeňStav(HOTOVO);
					else
						zmeňStav(ZNIČENÁ);
				}
			}

			if (BlokMesta.havaruj(this)) zmeňStav(ZNIČENÁ);
		}
	}

	@Override public void pasivita()
	{
		if (stav(ZNIČENÁ))
		{
			if (!BlokMesta.havaruj(this) &&
				polohaY() > Svet.najmenšieY())
				skoč(0, -2);
		}
	}

	@Override public boolean zmenaStavu(int starý, int nový)
	{
		switch (nový)
		{
		case FUNGUJE:
			farba(tmavotyrkysová);
			zrušCieľ();
			domov();
			zobraz();
			zrýchlenie(0, false);
			rýchlosť(3);
			break;

		case ZNIČENÁ:
			deaktivuj();
			farba(tmavočervená);
			Svet.pípni();
			náhodnýSmer();
			zobraz();
			break;

		case HOTOVO:
			if (ZNIČENÁ == starý) return false;
			farba(svetlomodrá);
			zobraz();
			zrýchlenie(0.25);
			zrýchlenieOtáčania(1);
			cieľ(polohaX(), Svet.najväčšieY() + (veľkosť() * 2.5));
			break;

		default:
			farba(šedá);
			deaktivuj();
			náhodnáPoloha();
			náhodnýSmer();
			zrýchlenie(0, false);
			rýchlosť(3, false);
			zrýchlenieOtáčania(0);
			rýchlosťOtáčania(0, false);
			skry();
		}

		return true;
	}

	@Override public void dosiahnutieCieľa()
	{
		zmeňStav(ČAKÁ);
	}

	@Override public void kresliTvar()
	{
		elipsa(0.5);
		double veľkosť = veľkosť();
		vyplňElipsu((veľkosť * 0.5) - 4, veľkosť - 4);
	}
}

Účelom tejto triedy je dynamicky vytvárať nové kópie rovnakého zvuku podľa potreby (podľa množstva požiadaviek na prehrávanie). Keby sme to nezabezpečili, tak by sa každý zvuk reštartoval pri každej novej požiadavke na jeho prehratie.

(Úloha: Metóda prehraj sa dá optimalizovať tak, aby nepotrebovala pomocnú premennú trebaNový (ktorá do nej bola vložená „násilne“ s cieľom zlepšenia čitateľnosti/zrozumiteľnosti kódu) a pritom plnila svoju úlohu úplne rovnako. Skúste optimalizáciu zrealizovať.)

~

import knižnica.Svet;
import knižnica.Zoznam;
import knižnica.Zvuk;

public class SériaZvukov
{
	private final Zoznam<Zvuk> zvuky = new Zoznam<Zvuk>();
	private final String súbor;

	public SériaZvukov(String súbor)
	{
		this.súbor = súbor;
	}

	public void prehraj()
	{
		boolean trebaNový = true;

		for (Zvuk zvuk : zvuky)
			if (!zvuk.prehrávaSa())
			{
				trebaNový = false;
				zvuk.prehraj();
				break;
			}

		if (trebaNový)
		{
			Zvuk zvuk = Zvuk.čítaj(súbor, true);
			zvuk.prehraj();
			zvuky.pridaj(zvuk);
		}
	}
}

~

public final class Nastavenia
{
	// public final static int NAJMENŠIA_VÝDRŽ_BÔMB = 5;
	// public final static int NAJMENŠIA_VÝDRŽ_BÔMB = 30;
	public final static int NAJMENŠIA_VÝDRŽ_BÔMB = 1;

	// public final static int NAJVÄČŠIA_VÝDRŽ_BÔMB = 5;
	// public final static int NAJVÄČŠIA_VÝDRŽ_BÔMB = 30;
	public final static int NAJVÄČŠIA_VÝDRŽ_BÔMB = 5;

	// public final static int POČET_BÔMB = 12;
	public final static int POČET_BÔMB = 7;
	// public final static int POČET_BÔMB = 32;

	// public final static int POČET_BLOKOV = 400;
	// public final static int POČET_BLOKOV = 650;
	public final static int POČET_BLOKOV = 450;

	// public final static int TVAR_MESTA = 1;
	// public final static int TVAR_MESTA = 2;
	public final static int TVAR_MESTA = 3;

	private Nastavenia() {}
}