Algorithme pour carte 2D procédurale avec chemins connectés

26

Problème à résoudre: Générez une carte de donjon 2D aléatoire pour un jeu basé sur des tuiles où toutes les pièces sont connectées.

Je recherche de meilleures solutions que celles que j'ai actuellement.

Ma solution actuelle consiste à exécuter deux algorithmes. Le premier génère le donjon avec ses chambres. Les seconds s'assurent que toutes les pièces sont connectées. Je suis curieux de savoir quelles autres solutions peuvent exister. Plus rapide et / ou plus facile, etc. La vitesse n'est pas vraiment un problème, mais si la vitesse peut être gagnée sans réel coût, eh bien, c'est une bonne chose. Le plus important est que moi, et d'autres qui lisons, apprenions différentes façons d'aborder et de résoudre le problème.

Voici ma mise en œuvre actuelle. Les chambres n'ont actuellement aucune sortie ou sortie dans 2, 3 ou 4 directions.

Génération des salles de donjon

Configuration: définissez la pièce actuelle sur la pièce en haut à gauche.

  1. Obtenez un type de chambre valide pour la chambre (où le type de chambre valide est un type sans sortie du donjon et dont les sorties correspondent aux sorties de la salle au-dessus et de la salle à gauche. Il suffit de vérifier ci-dessus et vers le gauche en raison de l'étape 2 ci-dessous).
  2. Baissez la pièce et avancez d'un pas la coordonnée x. Si la coordonnée x dépasse la largeur du donjon, définissez la coordonnée x sur 0 et avancez la coordonnée y d'un pas. Si la coordonnée y dépasse la hauteur du donjon, nous avons terminé.
  3. Répétez à partir de # 1.

Je vérifie ensuite si toutes les pièces sont connectées.Si elles ne sont pas toutes connectées, je lance un deuxième algorithme qui, d'une manière non sexy mais certainement assez bonne en termes de disposition de donjon, parcourt les pièces et les change pour que tout finisse jusqu'à être connecté.

Vérification pour voir si toutes les chambres sont connectées

Configuration: créez une carte 2D d'entiers représentant des chemins et initialisez les entrées à une valeur "non traitée" (pas encore traversée), -1. Définissez un entier d'index de chemin de départ qui garde la trace du chemin actuel sur 1. Définissez la pièce actuelle dans la pièce en haut à gauche en l'ajoutant à une pile de pièces à vérifier.

  1. Si la pile contient des pièces à vérifier, ouvrez-la pour définir l'index de chemin de la pièce sur l'index de chemin actuel. Si la pile ne contient aucune pièce, augmentez l'index du chemin et essayez d'obtenir une pièce en avançant colonne par colonne, ligne par ligne, jusqu'à ce que nous obtenions une pièce qui n'a pas encore été traitée. Si aucune pièce ne peut être trouvée, nous avons terminé.
  2. Vérifiez si la pièce a une sortie à gauche. S'il a ajouté la pièce de gauche à la pile si elle n'y est pas déjà.
  3. Répétez l'étape 2 pour les directions vers le bas, la droite et le haut (puisque nous utilisons une pile qui signifie que les pièces sont traversées dans le sens des aiguilles d'une montre, en commençant par la direction du haut).
  4. Répétez à partir de l'étape 1.
  5. Si le nombre d'indices de chemin est supérieur à un, il y a des salles déconnectées.

S'il y a des pièces déconnectées, je regroupe les pièces par leur indice de chemin, récupère l'index du plus grand chemin et connecte toutes les autres pièces à ces pièces. Il s'agit d'un travail en cours, mais mon plan (actuel, "brutal") consiste à parcourir chaque pièce d'un groupe de pièces (sauf la première) pour vérifier s'il y a un chemin horizontal ou vertical vers le groupe de pièces biggeset, et si c'est le cas, créez-y un chemin horizontal / vertical en injectant / mettant à jour les pièces entre elles. Rincez et répétez. Moche, oui, mais c'est quelque chose qui ne sera pas perceptible en termes de modèle visuel, donc cela fonctionne dans ce sens.

user1323245
la source
1
Avez-vous vérifié "Dungeon Generation" sur le wiki PCG ? Répond-il à vos questions?
congusbongus
@congusbongus Une lecture utile à coup sûr. Ce générateur de donjon lié sur cette page est génial. Merci.
user1323245

Réponses:

33

L'un des algorithmes les meilleurs et les plus utilisés que j'ai vu est la génération de donjons à l'aide du partitionnement d'espace binaire.

La meilleure explication générale que j'ai lue est celle trouvée dans The Chronicles of Doryen (jointe à la fin à des fins de sauvegarde) car elle explique la procédure sans entrer dans le code, laissant ainsi l'implémentation au lecteur.

Deux autres didacticiels sur le même sujet, avec code, sont disponibles sur


Construire l'arborescence BSP

Nous commençons par un donjon rectangulaire rempli de cellules murales. Nous allons diviser ce donjon de manière récursive jusqu'à ce que chaque sous-donjon ait approximativement la taille d'une pièce. Le fractionnement de donjon utilise cette opération:

  • Choisissez une direction aléatoire: fractionnement horizontal ou vertical
  • Choisissez une position aléatoire (x pour vertical, y pour horizontal)
  • Divisez le donjon en deux sous-donjons

entrez la description de l'image ici

Nous avons maintenant deux sous-donjons A et B. Nous pouvons appliquer la même opération à chacun d'eux.

entrez la description de l'image ici

Lors du choix de la position de séparation, nous devons veiller à ne pas être trop près de la frontière du donjon. Nous devons pouvoir placer une pièce à l'intérieur de chaque sous-donjon généré. Nous répétons jusqu'à ce que les sous-donjons les plus bas aient approximativement la taille des pièces que nous voulons générer.

entrez la description de l'image ici

Construire le donjon

Maintenant, nous créons une pièce de taille aléatoire dans chaque feuille de l'arbre. Bien sûr, la salle doit être contenue à l'intérieur du sous-donjon correspondant. Grâce à l'arborescence BSP, nous ne pouvons pas avoir deux salles qui se chevauchent.

entrez la description de l'image ici

Pour construire des couloirs, nous parcourons toutes les feuilles de l'arbre, reliant chaque feuille à sa sœur. Si les deux pièces ont des murs face à face, nous pouvons utiliser un couloir droit. Sinon, nous devons utiliser un couloir en forme de Z.

entrez la description de l'image ici

Maintenant, nous montons d'un niveau dans l'arbre et répétons le processus pour les sous-régions du père. Maintenant, nous pouvons relier deux sous-régions avec un lien entre deux pièces, ou un couloir et une pièce ou deux couloirs.

entrez la description de l'image ici

Nous répétons le processus jusqu'à ce que nous ayons connecté les deux premiers sous-donjons A et B

entrez la description de l'image ici

reefaktor
la source
Cela ne vaut peut-être rien que cette technique ne crée jamais de boucles, mais je ne suis pas sûr qu'il existe un moyen de contourner cela sans ajouter plus de couloirs aléatoires. Encore une très bonne réponse, +1
Vality
C'est un début prometteur. Il suffit de trouver un moyen d'y ajouter des boucles, mais je préfère travailler sur ce problème plutôt que de continuer sur la voie où je suis actuellement. Merci.
user1323245
2
Agréable ! J'étais intéressé par l'id alors j'ai fait une petite tentative. Vous devez être prudent lorsque vous utilisez des résultats aléatoires, sinon trop étranges suivront. Et je me demande si les couloirs ne devraient pas être traités correctement pendant la division récursive, car je ne vois pas de moyen facile de construire des couloirs à partir de l'arbre. Quoi qu'il en soit pour toute personne intéressée, le violon est ici: jsfiddle.net/gamealchemist/xt57zwb8
GameAlchemist
Bien que je trouve cela quelque peu problématique dans la procéduralisation prédéfinie reproductible sur de grands environnements. C'est probablement l'une des meilleures méthodes que j'ai jamais vues pour ce type de génération à condition que vous génériez tout votre niveau à la fois. Je attribue +1 à ce
Ce type sans-abri
4

La méthode BSP est apparemment la méthode la plus populaire pour générer des donjons, mais ce n'est pas la seule.

Pour être complet, je vais vous expliquer le générateur qui a fonctionné pour moi . Je dois admettre que je ne me souviens pas où j'ai lu à ce sujet, donc je dirai simplement que ce n'est pas mon invention (un vieil article de Jamis Buck semble très familier).

Un labyrinthe avec des chambres

L'idée de base est qu'un donjon est un labyrinthe avec des pièces, en quelque sorte. La première étape de cet algorithme est donc de générer un labyrinthe :

Labyrinthe généré avec une variation de l'algorithme Eller

L'étape suivante consiste à le rendre clairsemé (éliminer les impasses):

Rendre clairsemé: éliminer les impasses

L'étape numéro 3 consiste à ajouter des boucles (les rendre non parfaites ) mais je vais sauter l'image car elle est à peine perceptible (je n'avais pas besoin d'un labyrinthe parfait, j'ai donc pris quelques raccourcis sur l'algorithme de génération de labyrinthe, donc il a déjà avait des boucles par ce point).

Ensuite, pour l'étape 4, nous devons supprimer les cellules isolées:

Supprimer les cellules isolées

À ce stade, nous avons terminé avec les couloirs et nous sommes prêts à ajouter des chambres. Pour cela, nous procédons comme suit:

  1. Générer un ensemble de pièces (largeur et hauteur)
  2. Pour chaque pièce, nous parcourons tous les emplacements possibles et décidons du meilleur emplacement.
    • Le meilleur emplacement est calculé en ajoutant un poids aux conditions (telles que la contiguïté d'un couloir).
  3. Nous plaçons les chambres.

Jusqu'à présent, notre donjon ressemblera à ceci: Chambres ajoutées

La dernière étape consiste à ajouter des décorations.

Dessinez les portes et les numéros de pièce

Quelques réflexions finales

  • J'ai utilisé une version allégée de l' algorithme Eller .
  • Différents algorithmes de labyrinthe peuvent entraîner des textures différentes. Vous préférerez peut-être un autre algorithme. Par exemple, l'image suivante montre différentes textures résultant de «l'arbre binaire» (biais diagonal) et une variation des algorithmes de «division récursive» (longs couloirs): Arbre binaire vs division pseudo-récursive
Roflo
la source
2
Bon produit. J'ai cherché différentes façons de le faire, car l'utilisation d'algorithmes différents pour différents niveaux peut rendre le jeu encore plus polyvalent.
user1323245