Follow

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)

@bram tu veux de l'aléatoire continue sur une fonction continue, comme en math.

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):

@bram C'est ce que j'allais dire, tu fais varier ta coordonnée y de +1 ou -1 aléatoirement. 😜

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 ... :)

@bram C'est franchement intéressant comme technique, merci !

@samis it's a bit more of work than my 1-2h playarround yes 😅

(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 😅

@bram (en espérant que ça n'ai été déjà dit)

L'auteur du bruit de Perlin a conçu une version "améliorée": le bruit de simplex
- Moins complexe (algorithmiquement parlant, d'un point de vue math ça se tape des délires de malades)
- capable de variations plus soudaines (ce qui fait qu'on a tendance à moins l'utiliser du coup)

@akkes nope, pas dit, j'ai pas trop fouillé je t'avoue :)

(je crois que c'est celui que j'utilise vu qu'il y a un "s" avant "noise")

@Lanza ce site marche pas sur ma machine car mes drivers gpu sont pétés :x

@bram Ah dommage. C'est tout plein de bruit de perlin.

Et moi j'aime bien les maths, quand c'est pour faire de cholies zimages.

@bram mais non les maths c'est pas chiant, juste mal expliqué !

@akkes ouais, le rant souvent là dessus, j'ai vraiment beaucoup beaucoup de mal avec la pédagogie des maths (et la syntaxe même qui réuni, pour moi, toutes les caractéristiques d'un ultra mal designé langage de programmation)

@bram t'es pas la seule. En cachette même les profs le font parfois

J'aimerai bien connaître tes reproches à la syntaxe des maths

@akkes je t'avoue que j'ai pas de liste exhaustive des reproches que j'ai à faire à la syntaxe, c'est beaucoup plus l'approche qui génère ces problèmes:

- c'est pensé pour être écrit rapidement, pas compris facilement
- donc le plus condensé possible et pas le plus compréhensible possible
- on a recours à énorméments de zymboles abscons qui ne parlent à personnes et ne sont pas intuitifs
- ça a évolué organiquement et y a peut de refactoring pour essayer de rendre l'ensemble plus cohérent :/

@akkes pour donner quelques examples que j'ai encore en tête:

- log et exponentiel (et je sais plus quoi) sont en fait hyper proches (genre la ~symétrie~ l'un·e de l'autre) pourtant leur syntaxe est super différente et a rien à voir (y a une proposition alternative qui traine même)

- la syntaxe des listes parle d'elle même quand elle est comparé à celle de python (et je t'ai mis celle d'haskell au milieu car ça se voit que c'est des mathématiciens qui ont fait un langage de programmation :p)

@akkes des 3 listes y en a une qui se lit naturellement, les 2 autres ...

@bram y a une section de la thèse d'Alexis Lemaire qui critique les notations mathématiques, j'essaierai de la retrouver :]

Alexis Lemaire Show more

Alexis Lemaire Show more

Alexis Lemaire Show more

Alexis Lemaire Show more

Sign in to participate in the conversation
Mastocafé

This is an open mastodon instance for social justice activists, LGBTQIA+ people, and people who are aware of such subjects and care about them.

See the Goals, rules, and technical details for more information