Hiradorable utilise witches.town. Vous pouvez læ suivre et interagir si vous possédez un compte quelque part dans le "fediverse".

Tien, vu que ça avait l'air d'impression certaines personnes mon fabuleux générateur aléatoire de cartes de jeu vidéo je vais tenter de faire un "mini" tuto pas à pas sur comment j'ai fait ça parce qu'en fait c'est vraiment simple (c'est la base de la génération aléatoire de carte).

C'est en python avec pillow (anciennement PIL) dans jupyter notebook (anciennement ipython notebook).

Pour rappel ça ressemble à ça à la fin :

Pour commencer par la base, on va générer une image depuis rien avec PIL, une image en RGB (parce que j'ai la flemme de faire du HSV).

Une image en RGB c'est bêtement un tableau (une matrice) de points où chaque point représente une couleur.

RGB c'est "red, green, blue", une couleur encodé sur 3 valeurs (la première c'est le rouge, puis verts, puis bleu) allant de 0 à 255.

Genre:
(255, 0, 0) c'est rouge
(0, 0, 0) noir
(255, 255, 255) blanc
(0, 255, 0) vert

etc...

Cette image en montre plein

Donc, faire une image toute noir (donc avec que des points contenant la valeur "0, 0, 0") ça se fait comme ça dans pillow:

On fait une nouvelle image de 200x200 et pour chaque point on met la valeur à (0, 0, 0)

Maitenant on a envie de faire un générateur aléatoire, donc il faut faire de l'aléatoire pour ça.

La solution la plus simple c'est d'utiliser "randint" de la librairie random qui nous donne un nombre sans chiffres après la virgule de 0 à ce-qu'on-veut non inclue.

Ici: randint(0, 256) donnera un nombre netre 0 et 256 non inclu.

Ici, on a uniquement générer un seul nombre par point et le mettre dans toutes les valeurs du point, ça nous laisse en noir et blanc.

Résultat :

Si jamais vous êtes curieux·ses ça ressemble à ça si on met un nombre aléatoire différent pour chacune des couleurs:

(mais on va pas s'en servir ici)

Maintenant le problème de l'aléatoire qu'on a, c'est qu'il ... trop alétoire 😕

On peut pas l'utiliser comme ça car il varie trop, c'est ce qu'on appelle du bruit. Il nous faut un truc qui varie aléatoirement mais dans une certaine continuité.

Y a un truc qui existe pour ça (et que tout le monde utilise) qui s'appelle "le bruit de perlin" qui varie par rapport aux précédentes entrées.

Y a ce graph (trouvé au pif) qui montre la différence de variation (perlin à gauche vs pure alétoire à droite)

Donc, comme on est en python et qu'on est des fleimasses et que coder le bruit de perlin à la main c'est chiant car c'est plein de math et les maths c'est chiant, on utilise une librairie qui fait déjà tout pour nous 😋

La librairie s'appelle "noise" (le "import noise").

Malheureusement elle a une API très moche et une doc pas facile à comprendre.

Ici j'ai suivit un exemple trouvé dans la librairie, on utilise "snoise2" qui prend 2 coordonnées en entrée (les i et j de notre image):

Quelques explications en plus: la librairie va toujours renvoyer la même valeur pour les mêmes "i et j" en entrée.

Ici j'ai mis "43" et "13" au pif pour donner un exemple.

"octaves" c'est un paramètre qu'on va faire varier sans trop se préoccuper de ce que ça signifie vraiment mais ça change le résultat et on va juste changer ça pour en avoir un qu'on aime.

Problème ici: le nombre est compris entre -1 et 1 et on en veut un entre 0 et 255, donc on doit quand même faire un peu de maths :oh_no:

Donc maintenant qu'on a notre formule magique trouvé dans l'exemple de la librairie ("bibliothèque" :blobcat:) que tout le monde utilise (les gens codent comme ça hein, vous faites pas d'illusions 😋) on remple notre "randint" par ça pour avoir un joli résultat :blobcat:

"Mais c'est tout aussi aléatoire que avant !" Vous allez me répondre.

Et bien : presque oui, en fait il faut encore un peu tweaker tout ça car l'aléatoire c'est 3 tonnes de tweakage.

Heureusement la réponse est déjà dans l'exemple (moche) de la librairie (qui se trouve ici github.com/caseman/noise/blob/) : il faut diviser i et j par une "fréquence" pour réduire l'aléatoire.

Et boum: on vient de refaire le filtre photoshop "nuages" \o/

Et pour l'example, avec 4 variations différentes d'octaves pour vous donner une idée:

Maintenant : comment on transforme ça en carte aléatoire de jeux vidéo ?

Et ben en fait c'est super simple (la partie difficile est finite) : chaque point de l'image est une valeur entre 0 et 255, il suffit de se dire qu'en fait, ça représente l'altitude de notre carte.

Par exemple : si on décide qu'entre 0 et 100 c'est le fond de la mer, on peut remplacer tous ces points par du bleu foncé et ça donne ça:

(j'ai du un peut changé le code pour avoir un variable color)

Il suffit maintenant de définir des couleurs pour chaque niveaux qu'on veut dans notre carte 😋

Là c'est la partie où vous vous amusez et vous définissez ce que vous voulez :)

J'ai rajouté:

- de l'eau moins profonde
- une plage
- des plaines (vertes)
- de la forêt
- des montagnes
- des sommets eneigés

À vous de faire comme vous voulez \o/

Et le code si vous voulez jouer avec : gist.github.com/Psycojoker/e28

Jupyter notebook, l'util en ligne que j'ai utilisé pour ça jupyter.org/

La librairie noise: github.com/caseman/noise (normalement c'est "pip install noise" dans un virtualenv mais la distribution en python :/)

Pillow pillow.readthedocs.io/en/lates

Pour donner quelques informations en plus : c'est un peu la base de la génération aléatoire, à partir de ça tout est énormément une question de tweakage, de trouver les nouveaux algos, les nouvelles fractals et co pour bien s'amuser, c'est un domaine très vaste que je connais mal, en tout cas c'est très marrant :)

Dans les trucs rigolo à faire en plus y a : la formation des rivières.

Un algo du genre c'est de partir des points localements les plus hauts au dessus d'un certain seuil (genre là où y de la neige) puis de faire couler l'eau où à chaque point où on est, on regarde lequel est le plus bas autour de nous et s'arrêter quand on touche la mer.

Résultat ça peut faire des lacs aussi :)

Un autre algo super connu que j'ai pas encore utilisé c'est le "diamond square" que j'ai pas taffé assez pour expliquer correctement mais ça donne des résultats rigolo aussi :

(il est pas super compliqué, je l'ai juste plus en tête)

Et un dernier truc pour vous donner une idée : je sais que les jeux avancés à ce niveau là (genre Dwarf Fortress) génère 3 bruit de perlin différents (en simplifié) et les superposent.

1 pour l'altitude, 1 pour la température et 1 pour l'humidité.

Résultat on a une combinaison super varié de terrains (je vais pas tous les faire) :

- altitude moyenne, humide, chaud : jungle
- haute altitude, pas d'humidité, froid : sommet rocheux

Je vous laisse deviner pour le désert, la plaine, etc ... :)

(ah, j'espère que c'était compréhensible, plus que les détails exacte du code je voulais surtout montrer l'idée de comment ça se fait, la partie "bruit de perlin" étant un peu chiante à vulgariser :x) (si vous avez pas capté un truc hésitez pas)

J'aurais probablement dû foutre un hashtag pour mute aussi remarque 😅

@Hiraelle j'adore aussi, quand j'étias petit je passais ma vie à regarder des screensavers qui généraient des maps aléatoires, ça me fascinait :blobcat:

@bram trop bien :blobcat:

moi j'avais juste un screensaver "galaxie" genre je me disais que le pc contrôlait un vaisseau spatial et qu'on voyageait :blobcat:

Hiradorable @Hiraelle

@bram (c'était juste des points blancs qui bougeaient hein ! mais bon x))

@Hiraelle (ouin, je retrouve plus le mien, je voulais te le montrer ._.)