Tilemap - "Biome"?

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Pyanfänger
User
Beiträge: 99
Registriert: Mittwoch 28. Dezember 2011, 12:50

Hallo an alle :)

ich würde in meiner TileMap gerne sowas wie "Biome" generieren, denn wenn ich einfach per Zufallssystem die verschiedenen Tiles anzeigen lasse, erstellt es ja was kunterbuntes, aber wenn man es nicht per zufallsystem macht ist es ja keine Zufalls generation!

So sieht es per Zufallsgenerator aus:

Bild
Daher habe ich gedacht man könnte einfach noch eine List erstellen, welches eben nur bestimmte Tiles per Zufall zusammensteckt, und dann in einer anderen Schleife diese Biome per Zufall zusammenwürfeln...
Mein erster Versuch hat aber nicht so ganz geklappt :

Hier die Liste für ein Biom

Code: Alles auswählen

self.__biome = list()
Dann in das Biom tiles generieren

Code: Alles auswählen



        for zxz in range(0, self.__height / 3):
            self.__biome.append(list())
            for xzx in range(0, self.__width / 3):
                g = random.randint(0, 2)

                if g == 0:
                    self.__biome[zxz].append("grass")
                if g == 1:
                    self.__biome[zxz].append("grass_fluss_ecke")
                if g == 2:
                    self.__biome[zxz].append("see_in_grass")
und dann im Zufallsgenerator

Code: Alles auswählen


                if x == 0:
                    self.__tiles[i].append(self.__biome[])
natürlich funktionniert das nicht, aber ich habe echt nich viel Ahnung wie ichs anders machen soll :o (bzw sindalles ausschnitte, also das if x == 0 is in der zufallforschleife drin, habs aber rausgeschnitten
-
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Sieht doch schon mal nett aus :-)

Du musst uns mehr Infos zu dem eigentlichen Anforderungen geben! Was ist denn bei Dir ein Biom? Welche passen denn zusammen und wieso? Wie willst Du sie platzieren?

Mir ist das alles noch ziemlich unklar!

Geht es darum, dass nur bestimmte Typen zusammenpassen? So a la Carcassone (dem Brettspiel), wo man eine Wiese nur an eine Wiese, eine Stadt nur an eine Stadt usw. legen darf? Wenn ja, brauchst Du Informationen zu jedem Tile, wie eine Kante beschaffen ist bzw. welche Schnittstellen eine Kante bietet. Anhand dieser Infos kann man dann testen, welche Typen überhaupt in Frage kämen, an einer bestimmten Kante angelegt zu werden.

Kurz noch zum Code:

- Unterlasse es, Namen mit zwei Unterstrichen zu benutzen!

- dieses Konstrukt ist ziemlich umständlich:

Code: Alles auswählen

              if g == 0:
                    self.__biome[zxz].append("grass")
                if g == 1:
                    self.__biome[zxz].append("grass_fluss_ecke")
                if g == 2:
                    self.__biome[zxz].append("see_in_grass")
Du kannst das doch auch per Liste / Tupel und einem *Index* lösen, ganz ohne `if`:

Code: Alles auswählen

tile_types = ("grass", "grass_fluss_ecke", "see_in_grass")
self.biome[zxz].append(tile_types[g])
Ist doch viel einfacher zu lesen und auch in Hinblick auf Erweiterungen Deiner Typen - damit musst Du *nichts* an diesem Code ändern, auch wenn Du noch 1000 neue Typen definierst.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Pyanfänger
User
Beiträge: 99
Registriert: Mittwoch 28. Dezember 2011, 12:50

Danke für die Antowrt :D !

ja, ich will halt machen dass sich die verschiedenen Typen(Gras , sand stein usw) eher in Gruppen Generieren mit den "Ecken" am besten außen :) (Ja, so ähnlich wie Crcassone :D )

Und wie mache ich diese Infos zum Tile :O

Ok werde die Namen gleich mal ändern :wink: ^^

ps: und wenn ic hes so generieren will, also mit biome, kommt die fehlermeldung list objects are unhashable :(
-
BlackJack

Leute, lasst unnötige Indizes weg — random.choice() existiert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Pyanfänger hat geschrieben: Und wie mache ich diese Infos zum Tile :O
Naja, dafür musst Du Dir eben etwas passendes ausdenken. Es kommt dabei ja immer auf Deine Anforderungen an.

Du musst ja irgend wo eine Definition eines solchen "Bioms" haben, also nehmen wir mal dieses vereinfachte Beispiel:

Code: Alles auswählen

Tile: A
###
...
###

Tile: B
###
#..
#.#

Tile: C
###
###
###
Du kannst doch nun die Kanten leicht bestimmen. Du hast ja pro Makrotile immer vier Kanten: Oben, unten, rechts, links. Diese kannst Du leicht aus dem Makrotile auslesen.

Nehmen wir nun an, Du hast Tile A "gelegt". Nun willst Du links daneben ein Tile platzieren. Man sieht selber intuitiv schon, dass A und B passen und C nicht. Algorithmisch vergleichst Du einfach nur die linke Kante des betrachteten Tiles A und der jeweiligen rechten Kanten der anderen Tiles. Aus den passenden kannst Du dann per Zufall eines auswählen und bist dennoch sicher, dass die Übergänge passen.

Das wäre ein Weg.

Du kannst je nach Komplexität oder wenn Du unterschiedliche Symbole verwendest, die dennoch zusammen passen sollen, eine "neutrale", also von der Symbolen unabhängige, Kantenbeschreibung etablieren.

Analog zum Carcassonne Beispiel wäre das z.B. so denkbar:

Code: Alles auswählen

Tile A:
Kante links:
- Wiese
- Weg
- Wiese

Kante oben:
- Wiese

Kante rechts:
- Wiese
- Weg
- Wiese

Kante unten:
- Wiese
Man kann sich überlegen, ob man eine fixe Anzahl an Verbindungs-"Ports" haben will, oder lieber beliebig lange Sequenzen. Ob ich nun drei mal "Wiese" schreibe oder einmal ändert ja eigentlich nichts am Informationsgehalt. Evtl. ist es aber einfacher, sich auf eine fixe Anzahl an Ports festzulegen und man erspart sich unnötige Komplexität.

Nun kann ich ein Makrotile bauen, welches ein anderes Symbol für eine Wieso verwendet aber dennoch eine Verbindung herleiten.

Man könnte nun sogar mit Wildcards arbeiten, also Angaben, dass eine Kante beliebig besetzt werden kann. Z.B. wenn man eine Stadt rechts an den "Weg durch die Wiese" legen will:

Code: Alles auswählen

Tile A:
Kante rechts:
- Wiese
- Weg
- Wiese

Tile Stadteingang:
Kante links:
- Mauer
- Weg # Stadttor als Symbol
- Mauer
Bei diesen Angaben würde ein "steifer" Algo scheitern, da:

Code: Alles auswählen

Wiese != Mauer
Weg == Weg
Wiese != Mauer
zu einer Ablehnung führte. Man könnte nun also statt der Wiese und Mauer auch einen "*" nehmen und damit zeigen, dass es einem egal ist, was dort drankommt. Mir fiel aber mittlerweile auf, dass das keine tolle Idee ist.

Besser ist es, dieses zu lassen, aber eine Art "Äquivalenzklassen"-Definition für solche Verbindungen zu schaffen. Also etwa so:

Code: Alles auswählen

combinables = (
    ("wall", "meadow", "forest"),
    ("way", "gate"),
    ...
)
Die Struktur ist aber noch ungünstig, da man nun alles durchsuchen müsste, um für die Wiese zu gucken, ob eine Mauer dran passt. Wie man das gut lösen kann, fällt mir grad nicht wirklich ein. Vermutlich läuft es darauf hinaus, für jedes Element (Key) eine Liste mit kompatiblen Elementen (Value) in einem Dictionary abzulegen. Damit könnte man bei einem Vergleich so vorgehen:

Code: Alles auswählen

def is_combineable(first, second):
    return second in combinables[first]

is combinable("meadow", "wall")
>>> True
Da das ganze ja vermutlich symmetrisch ist, würde ich dieses Dictionary aus den oben zunächst von mir angedachten Tupeln generieren.

So, das war nun genug Sermon von mir :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BlackJack hat geschrieben:Leute, lasst unnötige Indizes weg — random.choice() existiert.
Oops, da habe ich das Ausgangsproblem aus den Augen verloren :oops: Aber ohne diesen Kontext habe ich dem OP ja doch etwas sinnvolles gezeigt :-D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Pyanfänger
User
Beiträge: 99
Registriert: Mittwoch 28. Dezember 2011, 12:50

Wow thx :D

Das muss ich jetzt erst mal abarbeiten bzw verdauen :O

Das dumme ist ja dass die Teils schon gesetzt sind - also müsste man theoretisch vor dem rendern der tiles dass alles abprüfen :?:
-
Antworten