Forums Développement Multimédia

Aller au contenu

[exercice] Le Rogue-Like - partie 1 : générer les environnements

CODE

8 réponses à ce sujet

#1 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 01 March 2013 - 22:59 PM

Hello les gens,

J'ai envie de m'attaquer à un Rogue-Like parce que ça va solutionner la méga flemme que j'ai de construire minutieusement à la main chaque environnement à chaque fois que je monte un jeu .

Du coup j'en fait aussi des exercices mais cette fois en plusieurs parties, voici la partie 1, les générateurs d'environnements.

C'est par ici : http://forums.mediab...uelike_partie_1

Si vous connaissez des techniques et algos abordables qui peuvent m'aider à améliorer le résultat n'hésitez pas, ça va me servir.

Pour informations, vous pouvez retrouver les différentes réflexions, avancées, et tests autour de cet exercice en plus de ceux qui sont sur ce sujet, ici : http://forums.mediab...portes-et-cles/

#2 lilive

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2993 messages

Posté 02 March 2013 - 12:09 PM

Salut Mister Spi,

Très sympa de voir ces méthodes, merci.

Pour la génération du labyrinthe je n'ai pas compris l'explication, c'est en lisant le code que j'ai compris.
C'est vrai que c'est facile à faire, j'aurais pas cru.

Et la caverne c'est une vraie découverte. Comme c'est malin !
Ça m'a rappelé cette fascinante conférence: http://lille1tv.univ...8f-b839300b6cc9

Quelques remarques sur le labyrinthe:

- Expliques-tu dans un exercice précédent l'intérêt d'éviter les tableaux à 2 dimensions ?
Dans des cas comme celui-ci je n'y vois qu'une source de difficulté à la lecture du code, et une source d'erreurs possibles, puisque chaque fois qu'on fait une conversion X,Y <-> index on peut se tromper.
La preuve dans ton code:
Au début de la fonction creeLabyrinthe:
mouvements =     [X+Y*C];
et plus tard:
mouvements.push(Y+X*C);
Une chance que tes x et y de départ soient égaux, et que tes L et C soient égaux, sinon tu aurais eu un bug ;) !


- Petite erreur ici, il y a inversion de L et C:
if (X+pas<L && grille[X+pas+Y*C])        directions.push("W");
if (Y+pas<C && grille[X+(Y+pas)*C])      directions.push("N");


- Ça gêne pas comme tu fais, mais habituellement quand on dit nord on parle d'aller vers le haut de la case, donc diminuer les Y. Toi tu fais l'inverse.


- J'ai fait une version qui utilise un tableau à 2 dimensions, et qui évite le switch.
La plus compacte et lisible au niveau code:
Fichier joint  labyrinthe_mb_cs5_2.fla   8.18 Ko   82 téléchargement(s)
Même chose, plus rapide à l'exécution mais moins compacte, et moins lisible à mon avis:
Fichier joint  labyrinthe_mb_cs5_3.fla   8.19 Ko   91 téléchargement(s)

Au final, une page bien intéressante à mon goût :)

#3 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 02 March 2013 - 14:35 PM

Hello Lilive,

Merci de ces retours ;-)

Citation

Pour la génération du labyrinthe je n'ai pas compris l'explication, c'est en lisant le code que j'ai compris.
Je vais essayer de voir si je peux améliorer, j'ai écrit ça à l'arrache hier après les derniers tests sur la répartition des clés, j'ai peut être été un peu vite.

Citation

- Expliques-tu dans un exercice précédent l'intérêt d'éviter les tableaux à 2 dimensions ?
Yep, c'est même la base par laquelle je commence avec le Taquin, aucun de mes exercices (sauf 1) n'utilise de tableaux à deux dimensions, je reconnais que c'est moins simple à aborder, mais c'est beaucoup plus pratique à mon goût et au final selon les besoins beaucoup plus optimisé.

Citation

puisque chaque fois qu'on fait une conversion X,Y <-> index on peut se tromper.
Alors en fait ce n'est pas la conversion qui est trompeuse, une fois qu'on connait la formule c'est toujours la même, je me trompe tout autant avec des doubles boucles et tableaux à multiples dimensions, ça fait partie des choses qui n'arrivent pas à rentrer, il m'arrive très souvent de confondre X et Y dans une grille, généralement je m'en rend compte à un moment donné et je corrige mais là à première vue j'en ai laissé passer (encore essayé d'aller trop vite), merci de l'avoir remarqué je vais corriger, heureusement que tu es là pour me relire ;-)

Merci pour tes versions, je vais regarder ça et m'en inspirer si besoin pour la suite, aujourd'hui j'attaque la répartition cohérente des objets et si j'ai le temps la spécialisation des items, ennemis, pnj.


EDIT : je viens de lire ta version compacte, elle est bien mieux merci, je vais la reprendre pour la suite et citer ton message en modif dans l'exercice pour ne pas perdre le lecteur entre les différentes étapes (je ne vais pas réécrire l'exercice je pense, ce sera un bon exemple de modification avantageuse du code)

#4 lilive

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2993 messages

Posté 02 March 2013 - 18:48 PM

Voir le messageMonsieur Spi, le 02 March 2013 - 14:35 PM, dit :

Yep, c'est même la base par laquelle je commence avec le Taquin, aucun de mes exercices (sauf 1) n'utilise de tableaux à deux dimensions, je reconnais que c'est moins simple à aborder, mais c'est beaucoup plus pratique à mon goût et au final selon les besoins beaucoup plus optimisé.
Je viens de lire ce que tu en dis dans le Taquin.

Je partage ton avis sur l'économie des boucles. C'est pénible de taper ces 2 boucles à chaque fois.

Pour moi c'est plus facile de me représenter la chose avec des tableaux en 2D [X][Y] car c'est visuellement la même chose que les x,y des coordonnées d'affichage. Cela me demande une petite réflexion au moment de l'initialisation du tableau, pour me souvenir que c'est un tableau de colonnes que je dois créer, mais ensuite je n'ai plus à réfléchir du tout. Mais je comprends qu'on peut intégrer également l'automatisme de faire X+Y*C. Par contre pour la conversion inverse X=i%C, Y=i/C je trouve ça mal pratique.

Je trouve franchement plus lisible tab[X][Y-1] que tab[X+(Y-1)*C]



Question optimisation, puisque tu ne cites pas tes sources ( :P ) et par simple plaisir de faire ch curiosité, je viens de faire quatre tests que je te montre, ça pourra t'intéresser:
1000 générations de labyrinthe avec

labyrinthe_mb_1D_1.fla - tableau à 1 dimension - instanciation du tableau comprise - 816 ms
labyrinthe_mb_2D_1.fla - tableau à 2 dimensions - instanciation du tableau comprise - 973 ms

labyrinthe_mb_1D_2.fla- tableau à 1 dimension - initialisation mais pas instanciation du tableau - 625 ms
labyrinthe_mb_2D_2.fla- tableau à 2 dimensions - initialisation mais pas instanciation du tableau - 655 ms

Si l'avantage au tableau 1D est très sensible quand on instancie le tableau, ce gain disparait quasiment quand on se contente de l'initialiser.

Fichier(s) joint(s)



#5 lilive

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2993 messages

Posté 02 March 2013 - 19:02 PM

Je viens de tester avec des Vector. L'écart se creuse de nouveau en faveur du Vector 1D. Curieusement il semble ne pas y avoir de gain de vitesse entre Array 2D et Vector 2D.

Fichier(s) joint(s)



#6 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 02 March 2013 - 19:21 PM

Yop,

Merci pour les bench ;-)

Par contre il faut prendre en compte une autre donnée, l'objectif de travailler avec une liste c'est de la transformer ensuite en entier 32 bits non signé pour la stocker facilement et travailler au niveau du bit, j'avoue c'est pas pour demain dans les exercices moi même ayant encore du mal avec le binaire, mais je préfères prendre l'habitude dès maintenant.

Tu as quelques tests intéressants ici : http://alecmce.com/as3/fast-2d-arrays
Et plein de pistes d'optimisations là : http://alexgblog.com/?p=392
Tu as aussi ça mais le document n'est pas terminé : http://je2050.de/files/misc/as3opt.pdf



EDIT : ça me fait penser que ce serait intéressant de mettre ces tests dans le tuto de Nataly sur les tableaux, genre à la fin plusieurs méthodes pour écrire et parcourir un tableau avec les bench

#7 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 7017 messages

Posté 02 March 2013 - 22:42 PM

Tient je viens de tomber sur une méthode qui a l'air encore plus simple que celle que j'ai choisi, avec un arbre BSP : http://roguebasin.ro...geon_generation

#8 lilive

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2993 messages

Posté 02 March 2013 - 23:55 PM

1001 recettes de donjons :)
Le résultat semble moins intéressant quand même...

#9 lilive

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2993 messages

Posté 20 March 2013 - 15:13 PM

A la demande de M.Spi, je rajoute ce que j'ai fabriqué: Il s'agit des quelques classes permettant de créer des labyrinthes de formes différentes, pas forcément du genre grille rectangulaire en 2D.

Utilisation:

- Il faut d'abord créer des cellules (classe LabCell). Ce sont les unités de base du labyrinthe. L'explorateur qui parcourt le labyrinthe se déplacera de cellule en cellule. Les cellules peuvent être de formes différentes, régulières ou pas, en 2D comme en 3D.

- Il faut ensuite créer des bords (classe LabEdge). Il faut indiquer à chaque bord les cellules qui le touche avec sa méthode addCell(). En effet chaque cellule est entourée de plusieurs bords. Par exemple des cellules carrées ont 4 bords, des hexagonales en ont 6, des cubiques en ont 6 aussi, etc. Un bord peut être commun à deux cellules. Dans ce cas il sera susceptible de devenir une porte reliant ces 2 cellules.

- Il faut finalement appeler LabBuilder.createLab() en lui passant les bords en paramètres.
A partir de là le labyrinthe est créé, et on peut consulter chaque bord pour savoir s'il est un mur ou une porte. On peut également consulter chaque cellule pour connaitre ses murs, ses portes, et les cellules qu'on peut atteindre en la quittant par une porte.

Il sera souvent utile d'étendre les classes LabCell et LabEdge pour que ces objets contiennent d'autres informations. Par exemple des informations sur leur emplacement géométrique, leur aspect, etc.

Fichier(s) joint(s)





1 utilisateur(s) li(sen)t ce sujet

0 membre(s), 1 invité(s), 0 utilisateur(s) anonyme(s)