Plošné rozmístění potvor – .NET – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Plošné rozmístění potvor – .NET – Fórum – Programujte.comPlošné rozmístění potvor – .NET – Fórum – Programujte.com

 

Matěj Andrle+1
Grafoman
14. 7. 2014   #1
-
0
-

Dobrý den,
v následujícím algoritmu potřebuji nasadit do bludiště i monstra:

public static Maze Generate(int width, int height, int monstersCount)
{
	bool enableChange = true;
	bool[,] tile = new bool[width, height];
	Maze output = new Maze() { Monsters = new Monster[monstersCount] };

	int

		index, x1, y1, x2, y2,
		gateX = numberGenerator.Next(width),
		gateY = numberGenerator.Next(height);
	sbyte
		
		differenceX = 0,
		differenceY = 0;
	List<Point> path = new List<Point>()
	{
		new Point(gateX, gateY)
	};

	tile[gateX, gateY] = true;

	while(path.Count > 0)
	{
		Point currentPath = path[index = numberGenerator.Next(path.Count)];

		differenceX = 2;
		enableChange = true;

		if(TestOfTile(tile, width, height, currentPath.X, currentPath.Y + 2))
		{
			differenceX = 0;
			differenceY = 1;
			enableChange = numberGenerator.Next(2) == 1;
		}

		if(enableChange && TestOfTile(tile, width, height, currentPath.X, currentPath.Y - 2))
		{
			differenceX = 0;
			differenceY = -1;
			enableChange = numberGenerator.Next(2) == 1;
		}

		if(enableChange && TestOfTile(tile, width, height, currentPath.X + 2, currentPath.Y))
		{
			differenceX = 1;
			differenceY = 0;
			enableChange = numberGenerator.Next(2) == 1;
		}

		if(enableChange && TestOfTile(tile, width, height, currentPath.X - 2, currentPath.Y))
		{
			differenceX = -1;
			differenceY = 0;
			enableChange = numberGenerator.Next(2) == 1;
		}

		if(differenceX == 2)
			path.RemoveAt(index);
		else
		{
			x1 = currentPath.X + differenceX;
			y1 = currentPath.Y + differenceY;
			tile[x1, y1] = true;

			x2 = x1 + differenceX;
			y2 = y1 + differenceY;
			x1 = x2 + differenceX;
			y1 = y2 + differenceY;

			if
			(
				x1 < 0 || x1 == width ||
				y1 < 0 || y1 == height ||
				!tile[x1, y1]
			)
			{
				tile[x2, y2] = true;
				path.Add(new Point(x2, y2));
			}
		}
	}

	output.Path = tile;
	output.Exit = new Gate(GateType.Gate1Right, gateX, gateY);
	output.Hero = new Monster(MonsterType.Hero, gateX, gateY, width, height, tile);

	return output;
}

static bool TestOfTile(bool[,] tile, int width, int height, int x, int y)
{
	return

		x >= 0 && x < width &&
		y >= 0 && y < height &&
		!tile[x, y];
}

Hlavním výstupem je pole příznaků - kde se má vykreslit textura cesty. Můj problém - potvory musí být rozmístěny rovnoměrně, musím znát jejich výchozí směr a bylo by vcelku přívětivé, kdyby hrdina byl co nejdál od brány - hlavního cíle levelu. Algoritmus bych popsal stylem - jdi od výchozího bodu všemi směry, kterými to jde - bez zkřížení s jinými cestami... Napadá mne jediné, avšak složité řešení - dát všem monstrum pevnou počáteční pozici a všechny budou chodit po bludišti, dokud nesplní propracovanou podmínku - načež se zastaví...
Děkuji.

Výsledek zde:

https://www.facebook.com/photo.php?fbid=756237081086851&set=gm.654374731305325&type=1

Nahlásit jako SPAM
IP: 78.136.142.–
Satik0
Stálý člen
14. 7. 2014   #2
-
0
-

Můžeš si celou plochu obodovat třeba algoritmem vlny (na políčko si ukládat, v které vlně se nachází) a hrdinu pak umístit na pole s nejvyšší hodnotou.

Nepřátele můžeš rozmístit třeba hrubou silou - pro každého nepřítele vygenerovat náhodnou pozici, ověřit, jestli není v okolí už vygenerovaný jiný a přidat ho. Pokud nevyhovuje, tak celý proces opakovat, pokud hustota těch nepřátel nebude tak vysoká, aby docházelo při generování k příliš mnoha kolizím.

Nahlásit jako SPAM
IP: 46.255.9.–
RomanZ
~ Anonymní uživatel
272 příspěvků
15. 7. 2014   #3
-
0
-

Řešil jsem podobný problém jako máš s rozmístěním příšer. Potřeboval jsem náhodně vybrat testové otázky. Žádná nesměla být vybraná dvakrát. Při kolizi jsem další výskyt nehledal náhodně, jak doporučuje Satik, protože by to mohlo vést k další kolizi. Místo toho jsem vybral další výskyt tak, že jsem našel nejbližší další možné řešení.

Kdybych měl rozmisťovat příšery, vygeneroval bych náhodně pozici a tam se pokusil příšeru umístit. V případě, že je pole už obsazené, pokusil bych se příšeru umístit na některé sousední pole - prohledával bych blízké okolí a postupně prohledávání rozšiřoval, dokud bych nenašel volné místo.

Satikův postup je jednodušší a je rychlejší v případě, že příšery jsou rozmístěné řídce (třeba 4 duchové v pacmanovi, kdyby nezačínali v komůrce). Můj postup je rychlejší v případě, že příšery jsou ve výsledku rozmístěné hustě - pak dochází při náhodném generování k mnoha opakovaným kolizím. V extrémním případě, kdybys měl na mapě jedno poslední volné místo, tak se na něj náhodnými výstřely nemusíš nikdy trefit a program může pořád generovat náhodné pozice, které kolidují.

----------------------------

Příšera v bludišti, to je klišé. Co to něčím ozvláštnit? Budou po tom bludišti chodit? Když potká příšera příšeráka, tak by na to mohli skočit a příšera by snesla vejce, ze kterého by se časem něco vylíhlo :) A tam co se příšera vyvenčí, tak bude úrodná půda, na které vyroste lysohlávka a po jejím požití bude moct hlavní hrdina létat :) Případně by šlo vydráždit příšeru rudým hadrem a rozeběhnutá příšera by měla sílu prorazit zeď :)

Nahlásit jako SPAM
IP: 89.24.105.–
Matěj Andrle+1
Grafoman
15. 7. 2014   #4
-
0
-

#3 RomanZ
Jen tak rozházet příšery po poli - bez kolize, to bych dokázal mnohem lépe. Stačilo by projít celé pole cyklem a na každé nové políčko hodit nějakou pravděpodobnost. (tak aby se alespoň každé Xté políčko objevila potvora) Řeším však to, že nechci mít v jednom rohu 20 příšer a v ostatních nic... Totiž - bludiště není souvislá plocha, načež by mnou zmíněný postup musel brát v úvahu to, že bludiště nemá rovnoměrně rozložené zasaditelné plochy. Někde může být více cest, méně mezer, jinde méně cest, více mezer... Zkrátka z pohledu plochy by příšery skutečně byly rozmístěny rovnoměrně, ale při procházení bludištěm by se někdy objevovaly shluky. Nyní zkouším další svůj postup - vzal jsem bludiště jako plochu, ze které ukrajuji. Nejprve ukrajuji mezery (to mezi cestami), následně ukrajuji mřížky, dokud zbylé body nebudou tvořit přibližný počet potvor... (určený pro každý level) Uvidím, zda to dám do kupy... (cyklus se mi nedaří zakončit)

Nahlásit jako SPAM
IP: 78.136.142.–
RomanZ
~ Anonymní uživatel
272 příspěvků
15. 7. 2014   #5
-
0
-

Na rovnoměrnější rozdělení mám takovou fintu. Množinu rozdělit na podmnožiny a teprve na nich rozmisťovat náhodně.

Dám příklad - mějme šachovnici 8x8 polí a chtějme rozmístit 8 figur. Při náhodném rozmístění by se mohlo stát, že budou všechny v jednom rohu. Rozdělím tedy šachovnici pomyslně na čtyři kvadranty (každý o velikosti 4x4 pole) a pak v každém kvadrantu náhodně rozmístím 2 figury (na kolik dílů jsem rozdělil pole, na tolik skupin rozdělím figury). Aplikováno na Tvé potřeby, pokud by některá pole na šachovnici reprezentovala moře a pevniny bylo v kvadrantu méně, upravil bych počet figur podle počtu polí s pevninou.

To s tím ukrajováním, jak popisuješ, bych řekl, že možná povede k rovnoměrné (ne náhodné) distribuci potvor. Nevím jak máš vymyšlený gameplay, ale menší shluky potvor by třeba nemusely být na škodu.

Nahlásit jako SPAM
IP: 89.24.105.–
Matěj Andrle+1
Grafoman
15. 7. 2014   #6
-
0
-

#5 RomanZ
No nemusely, jenže zkrátka jsem se ani nedostal k funkčnímu modelu... Tvůj návrh si umím dokonale představit na rovině, jakou je šachovnice. Jenže já mám cedník, ne plochu... Když ukrojím kus bludiště a stejný o kus dál, pak se četnost cest nebude rovnat... (viz. obrázek - některá X/Y nemusejí mít ani 20% cest...)

Nahlásit jako SPAM
IP: 78.136.142.–
peter
~ Anonymní uživatel
4014 příspěvků
15. 7. 2014   #7
-
0
-

Zkusil bych do google: rovnomerne rozmisteni v prostoru algoritmus
Z toho vypadne treba https://cent.felk.cvut.cz/…9/kap09.html

Obvykle to resim takto...

Hraci plocha
- seznam volnych policek ulozim do pole
- nahodne vyberu policko random(pocet)
- smazu policko z pole obsazenych (push, pop, nebo cyklem)
Plocha jako obrazek
- urcim volna policka jako kruhy v obrazku (tady se da vyuzit setiuhelnikove hledani; a nebo v dokonalejsim systemu hledani po kruhove draze od stredu v r+r/2 a tam hledat, zda lze umistit kruh)
- ulozim do pole volnych typu random a take ulozim take seznam sousedu (tim se mi zjednodusi random na pole a nemusim porad testovat, zda se do obrazku vejde ci nevejde potvora)
- pak si urcim, zda ta potvora ma letat nebo je zemni  a udelam si pro kazdy typ potvor vlastni seznam volnych policek odkazujicich na id z uplneho seznamu (u pozemniho typu je nesmysl umistovat potvoru na pole ktere je ze vsech stran uzavrene a potvora se nemuze nikam hnout)

A pokud chces rozmistovat rovnomerne, tak bych prochazel pole volnych od 0 do max (postupoval bych podle sousedu daneho policka okolo) a nahodne vybral umistit ano/ne. Po rekneme 10 polickach bych spocital pocet obsazenych a volnych a podle toho pomeru pak vypnul obsazovani nebo vyrazne snizil pravdepodobnost.

0 1 2 3
4 5 x x
8 9 x x
// sousedy (prakticky treba herni planek http://mlich.zam.slu.cz/…rd/jbird.htm)
all[0] = [-1,-1,1,4,0] //vlevo nic, nahore nic, vpravo 1, dole 4, typ policka (zem, more, vzduch)
all[1] = [0,-1,2,5,0]
all[1] = [0,-1,2,5,1] ...
zem[0] = 0 (id z all)
zem[1] = 1
more[0] = 2
V tom prikladu to mam bez hledani, zda policko s nekym sousedi.
 V te hre je to tahle cast kodu
 

f.all[l] = {char:d[k],coords:{x:x,y:y}};
if (d[k]==type[1])
	{
	f.space[f.space.length] = l;
	}
else {if (d[k]==type[2])
	{
	f.space[f.space.length] = l;
	f.wings[f.wings.length] = l;
	}
else {if (d[k]==type[3])
	{
	f.ground[f.ground.length] = l;
	}
else {if (d[k]==type[4])
	{
	f.space[f.space.length] = l;
	f.wings[f.wings.length] = l;
	f.monster[1][f.monster[1].length] = l;	//ball
	}
else {if (d[k]==type[5])
	{
	f.space[f.space.length] = l;
	f.wings[f.wings.length] = l;
	f.monster[1][f.monster[1].length] = l;	//ball
	f.monster[0][f.monster[0].length] = l;	//snake_egg
	f.monster[2][f.monster[2].length] = l;	//unused
	}
else {if (d[k]==type[6])
	{
	f.ground[f.ground.length] = l;
	f.monster[3][f.monster[3].length] = l;	//snake mutate
	}
else {if (d[k]==type[7])
	{
	f.ground[f.ground.length] = l;
	f.player[f.player.length] = l;
	}
else {if (d[k]==type[8])
	{
	f.monster[4][f.monster[4].length] = l;	//cat
	}}}}}}}}
l++;
}}
Nahlásit jako SPAM
IP: 2001:718:2601:258:ad37:cc...–
Matěj Andrle+1
Grafoman
15. 7. 2014   #8
-
0
-

Co byste řekli na toto?:

Po vykreslení výřezu z bludiště projíždím v cyklu všechna monstra - zda se nachází v daném výřezu. Procházím však všechny. Pročež mne napadá zcela náhodně vygenerovat pozice monster. A ve zmíněném cyklu se budou náhodně pohybovat, dokud se neobjeví v onom výřezu - kdy už na ně bude platit UI model. (model umělé inteligence) Tak občas dorazím ke shluku, občas k jednomu... Navíc hodlám zavést subquesty, aby se pořád jen nechodilo ke dveřím. A pokud by byl quest na lov - bylo by zajímavé honit potvory po celém bludišti - ne-li?

Nahlásit jako SPAM
IP: 78.136.142.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 59 hostů

Podobná vlákna

Rozmistění ikon na form — založil Borisek

Mechanizmus pohybu potvor — založil Jakub Vojáček

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý