Laden...

Zufallsgenerierte endlose 2D Map: Erst oben dann links != Erst nach links & dann nach oben

Erstellt von Shaddow30 vor 6 Jahren Letzter Beitrag vor 6 Jahren 2.557 Views
S
Shaddow30 Themenstarter:in
6 Beiträge seit 2017
vor 6 Jahren
Zufallsgenerierte endlose 2D Map: Erst oben dann links != Erst nach links & dann nach oben

Hi,

ich habe vor kurzem C# gelernt, und erweitere mein Wissen dabei sehr gerne mit kniffligen dingen. Nun habe ich mir die Herausforderung gestellt, ein Minispiel zu entwickeln, das auf Zufallswerten aufbaut. Nach viel rumprobieren habe ich eine Map, die zufallsgeneriert wird und endlos sein soll, erschaffen können. Jedoch war mein Plan das alles über einen Seed zu machen. Was nicht ganz so funktioniert wie ich's gern hätte. Und zwar war meine Lösung zuerst viele Wege in verschiedene Richtungen zu machen, und das alles über einen Random-Generator zufallsgenerieren zu lassen. Die Map wird um 1 "Block" in die Richtung in die der Spieler geht erweitert (maximale Sichtweite).
Dabei ist das Problem leider, dass wenn der Spieler zuerst nach links geht und anschließend nach oben, die Map ganz anders generiert wird als wenn dieser zuerst nach oben und danach nach links geht. Ich habe ungefähr 2 Tage verschiedene Möglichkeiten durchprobiert, bin leider jedoch immer auf ähnliche Ergebnisse gekommen, aber es lässt mir keine Ruhe, deswegen wende ich mich nun an Euch.

Das ganze wird als ConsoleApp erstellt und dient wie gesagt rein zum erweitern meines derzeitigen Wissens.

Ich wäre für jeden Tipp, Angehensweise, oder Verlinkung zu etwas nützlichem (und eher noch auf Anfänger-Niveau) sehr dankbar!

Freundliche Grüße

6.911 Beiträge seit 2009
vor 6 Jahren

Hallo Shaddow30,

als Idee: generiere von der aktuellen Positionen aus die Map in allen Richtungen (oben, rechts, unten, links) und speichere diese ab (-> eine geeignete Datenstruktur kannst du da als Übung gleich mitüberlegen). Je nachdem in welche Richtung dann gegangen wird, kannst du die (vorberechnete) Map einblenden. Somit ist es egal ob links+oben od. oben+links.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

S
Shaddow30 Themenstarter:in
6 Beiträge seit 2017
vor 6 Jahren

Hallo!

Vielen Dank schon mal für die freundliche Antwort.

Leider habe ich etwas sehr wichtiges vergessen zu erwähnen, unzwar ist die Map endlos in alle Richtungen. Gerade deswegen ist es eine Herausforderung für mich.

Durch eine Endlosegenerierung in alle Richtungen bekomme ich eine Fehlermeldung, deshalb die Sichtweitenbegrenzung und erst wenn man sich bewegt werden neue Objekte gespawned. Ähnlich wie in Minecraft nur eben 2D.

Ich werde das oben editieren.
Danke nochmals und Lg

6.911 Beiträge seit 2009
vor 6 Jahren

Hallo Shaddow30,

wenn du eine Fehlermeldung bekommst, so gib diese bitte mit an. Dann braucht ein Helfer nicht raten welche es sein könnte.

die Map endlos in alle Richtungen

Du brauchst von der aktuellen Position aus ja nur das nähere Umfeld generieren in alle Richtungen (wo es halt noch nicht schon generiert wurde). Dadurch wird die Bedingung "endlos" nicht verletzt.

Damit die Map "stetig" ist, kannst du auch zu jeder Positionen den "Seed" mitspeichern, damit für die nächsten Generierung(en) entsprechend weiter gerechnet werden kann.

Ev. hilft aber auch ein wenig Code um dir beim Problem besser zu helfen. Du kannst hier ja zeigen wo du hängst.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

5.657 Beiträge seit 2006
vor 6 Jahren

Hi Shaddow30,

für die Speicherung der bisher generierten Teile einer "unendliche" Map kannst du auch eine Datei verwenden.

Ansonsten kannst du dir Eigenschaften eines Tiles auch (wie von gfoidl bereits angedeutet) berechnen lassen, so daß die Zwischenspeicherung wegfällt. Dazu kann man z.B. die Random-Klasse verwenden, z.B. so etwa:


byte GetTileNumber(int x, int y)
{
  int seed = x ^ ~y;
  Random rnd = new Random(seed);
  return (byte)rnd.GetNext(0, 256);
}

Diese Methode gibt einen Wert für das Tile zwischen 0 und 255 zurück, je nach Position des Tiles. Und es wird bei jedem Aufruf mit den gleichen Parametern immer auch der gleiche Wert zurückgegeben.

Weeks of programming can save you hours of planning

S
Shaddow30 Themenstarter:in
6 Beiträge seit 2017
vor 6 Jahren

Hallo!

vielen Dank euch, das hat mir schon mal etwas weitergeholfen.

Nun stellt sich mir noch die Frage, wie müsste ich die Sache angehen wenn ich die Wege etwas sinnvoller gestalten möchte. So dass wirkliche "Wege" existieren und nicht blos auf viel Glück ein Weg vorhanden ist, der dann aber irgendwann endet, und der Spieler dann keine Chance mehr hat sich weiter fortzubewegen. Mein derzeitiger Code zum testen:


    class Controller
    {
        private static int Seed = 1;

        private static int scale = 8;
        private static int density = 170;


        public static bool gameEnd = false;

        static byte GetTileNumber(int x, int y)
        {
            int seed = x ^ ~y;
            Random rnd = new Random(seed);
            return (byte)rnd.Next(0, 256);
        }


        static void Main()
        {
            int px = 0, py = 0;


            while (true)
            {
                Console.Clear();

                for (int x = 0; x < Console.WindowWidth / scale; x++)
                {
                    for (int y = 0; y < Console.WindowHeight / scale; y++)
                    {
                        if (GetTileNumber(x+px, y+py) < density)
                        {
                            for (int i = 0; i <= scale; i++)
                            {
                                Console.SetCursorPosition(x * scale, y * scale + i);
                                string text = "";
                                for (int j = 0; j < scale; j++)
                                {
                                    text += " ";
                                }
                                Console.Write(text);
                            }
                        }
                        else
                        {
                            for (int i = 0; i <= scale; i++)
                            {
                                Console.SetCursorPosition(x * scale, y * scale + i);
                                string text = "";
                                for (int j = 0; j < scale; j++)
                                {
                                    text += "#";
                                }
                                Console.Write(text);
                            }
                        }
                    }
                }
                ConsoleKeyInfo key = Console.ReadKey(true);
                if (key.Key.Equals(ConsoleKey.W))
                {
                    py--;

                }
                if (key.Key.Equals(ConsoleKey.S))
                {
                    py++;
                }
                if (key.Key.Equals(ConsoleKey.A))
                {
                    px--;
                }
                if (key.Key.Equals(ConsoleKey.D))
                {
                    px++;
                }

            }
        }

    }
5.657 Beiträge seit 2006
vor 6 Jahren

Da du für deine Zwecke nur 2 Zustände benötigst, würde hier reichen:

return rnd.Next(0, 2) == 0;

Und dann den Rückgabetyp der Methode von byte auf bool ändern.

Zu deiner neuen Frage: Was sind denn Wege? Die Leerzeichen? Im Quellcode finde ich jedenfalls keine Abfrage, ob sich der Benutzer auf einem Weg befindet, oder nicht.

Wenn du eine Art Straßennetzwerk planst, bei denen alle Wege irgendwie miteinander verbunden sein sollen, dann ist das ein wesentlich komplexeres Thema, was eine andere Herangehensweise erfordert.

Dann würde ich Wege wohl als Graphen oder Netzwerk betrachten, und das unabhängig von den Tiles generieren. Da kannst du dich ja auch von anderen Spielen inspirieren lassen, wo man den Quellcode im Netz (bzw. auf Github) einsehen kann.

Weeks of programming can save you hours of planning

S
Shaddow30 Themenstarter:in
6 Beiträge seit 2017
vor 6 Jahren

Mit dem zurückgeben mehrerer Werte kann ich die Dichte oder das Verhältnis bestimmen, bei 2 Werten ist die Chance immer bei 50%, aber vielen Dank für den Tipp.

Im Script habe ich derzeit die Leerzeichen als Weg bestimmt. Eine Abfrage für den Benutzer existiert noch nicht, da ich noch keinen Benutzer programmiert habe. Ich scrolle derzeit nur mit W A S D in die jeweilige Richtung um 1 Block.

Dein Satz zum Thema Straßennetzwerk ist eigentlich genau das was ich suche und wo mein Problem liegt. Ich schaffe es zwar Wege zu generieren, diese endlos lang zu machen, jedoch schaffe ich es nicht, diese Wege oder das Straßennetzwerk von jeder Richtung aus kommend gleichbleibend zu generieren. Wie im ersten Beitrag beschrieben, "Erst oben dann links != Erst nach links & dann nach oben" - das ist jedes mal mein Endergebnis. Leider.

Meine Angehensweise bisher war, vom x0, y0 Punkt aus Wege in alle Richtungen zu generieren, diese Wege haben dann eine gewisse Chance Verzweigungen, Enden oder Kurven zu bilden, dabei wird immer kontrolliert ob am nächsten Punkt bereits ein Weg existiert oder eben nicht. Jenachdem bricht er dann entweder ab oder geht weiter. Nur kann diese Angehensweise meiner Meinung nach nicht das gewünschte Ergebnis erbringen. Ich bin sehr erfreut über alle Infos die man mir dazu geben kann.

Freundliche Grüße

5.657 Beiträge seit 2006
vor 6 Jahren

Random world generation of streets
How to generate a city street network?

Das ist, wie schon gesagt, ein etwas komplizierteres Thema 😉

Weeks of programming can save you hours of planning

S
Shaddow30 Themenstarter:in
6 Beiträge seit 2017
vor 6 Jahren

Hallo!

Damit sind dann meine Fragen für's erste beantwortet. Vielen Dank euch beiden.

Dass es kompliziert ist wusste ich schon von vornehinein, aber gerade deswegen interessiert mich das Thema.

Grüße