Développer un moteur capable de créer un univers isométrique infini, cohérent et entièrement dynamique représente un défi passionnant. Ce projet explore une approche où chaque tuile, chaque décor et chaque élément du terrain est généré en temps réel, sans aucune carte préchargée ni tableau de données.
Le monde n’existe que lorsqu’il est rendu à l’écran.
Architecture du moteur
Un espace infini basé sur des coordonnées
Le joueur évolue dans un monde théoriquement illimité.
Chaque tuile est calculée à partir de sa position (gx, gy) et projetée en isométrie via une transformation simple :
- (rX - rY) * 24 pour l’axe horizontal
- (rX + rY) * 12 pour l’axe vertical
Cette méthode garantit un rendu fluide, même lors de déplacements rapides.
Génération procédurale du sol
Le terrain repose sur des règles mathématiques :
- Herbe par défaut
- Chemins lorsque nx mod 14 = 0 ou ny mod 14 = 0
- Eau via une formule organique : (nx 3 + ny 2) mod 31 < 2
Ces règles créent un monde structuré, avec des routes régulières et des rivières naturelles.
Rendu isométrique avec relief
Chaque tuile est composée de :
- une tranche 3D pour le volume
- un losange supérieur pour la surface
Le résultat : un style isométrique propre, lisible et immersif.
Décors procéduraux
Un hash mathématique détermine la présence d’éléments naturels ou architecturaux :
- arbres
- rochers
- maisons
Chaque décor est dessiné via des polygones et formes géométriques, ce qui donne une identité visuelle unique.
Déplacements et collisions
Les déplacements (ZQSD) sont validés par une vérification procédurale :
- type de sol futur
- type de décor futur
Impossible d’entrer dans l’eau ou dans une maison : la logique reste cohérente partout dans le monde, sans tableau de collision.
Intérêt du projet
Monde infini sans stockage
- Performances optimisées : seules les tuiles visibles sont calculées
- Simplicité d’extension : nouveaux biomes, décors, règles
- Approche pédagogique pour comprendre la génération procédurale
Conclusion
Ce projet démontre qu’un monde infini, cohérent et vivant peut émerger uniquement de règles mathématiques. La génération procédurale ouvre des perspectives fascinantes pour la création d’univers interactifs.
Programme :
@ Carte Isométrique Infinie et Dynamique avec Génération Procédurale
toile1 est une toile
dimension(toile1, 500, 450)
// Position du joueur dans le monde infini
jX est un nombre
jY est un nombre
jX vaut 0
jY vaut 0
action est un nombre
@ Boucle principale
tant que vrai
effacer(toile1)
remplir(toile1, #111923)
// Balayage du champ de vision (rayon autour du joueur)
rY est un nombre
rX est un nombre
pour rY de - 10 à 10
pour rX de - 10 à 10
gx est un nombre
gy est un nombre
gx vaut jX + rX
gy vaut jY + rY
// Coordonnées écran relatives au centre (200, 200)
cx est un nombre
cy est un nombre
cx vaut 200 + (rX - rY) * 24
cy vaut 200 + (rX + rY) * 12
// Culling : Rendu uniquement si la tuile touche la toile 400x400
si cx >= - 60 et cx <= 460 et cy >= - 60 et cy <= 460 alors
// Offsets positifs pour le calcul procédural
nx est un nombre
ny est un nombre
nx vaut gx + 50000
ny vaut gy + 50000
// 1. Génération procédurale du Sol (sans tableau)
typeSol est un nombre
typeSol vaut 0 // 0 = Herbe
// Réseau de routes infini
si nx mod 14 = 0 ou ny mod 14 = 0 alors
typeSol vaut 1 // Chemin
// Rivières organiques procédurales
sinon si (nx * 3 + ny * 2) mod 31 < 2 alors
typeSol vaut 2 // Eau
fin si
// Tranche 3D (épais/relief du sol)
ptsBord est un tableau
ptsBord ajoute cx - 24
ptsBord ajoute cy
ptsBord ajoute cx
ptsBord ajoute cy + 12
ptsBord ajoute cx + 24
ptsBord ajoute cy
ptsBord ajoute cx + 24
ptsBord ajoute cy + 4
ptsBord ajoute cx
ptsBord ajoute cy + 16
ptsBord ajoute cx - 24
ptsBord ajoute cy + 4
polygone(toile1, ptsBord, #16222d)
// Face supérieure de la tuile (Losange 48x24)
ptsSol est un tableau
ptsSol ajoute cx
ptsSol ajoute cy - 12
ptsSol ajoute cx + 24
ptsSol ajoute cy
ptsSol ajoute cx
ptsSol ajoute cy + 12
ptsSol ajoute cx - 24
ptsSol ajoute cy
si typeSol = 0 alors
polygone(toile1, ptsSol, #27ae60)
sinon si typeSol = 1 alors
polygone(toile1, ptsSol, #d35400)
sinon
polygone(toile1, ptsSol, #2980b9)
fin si
contour(toile1, #1a252f, 1)
// 2. Génération procédurale du Décor
typeDecor est un nombre
typeDecor vaut 0
si typeSol = 0 alors
hash est un nombre
hash vaut (nx * 17 + ny * 37) mod 100
si hash < 10 alors
typeDecor vaut 1 // Arbre
sinon si hash < 14 alors
typeDecor vaut 2 // Rocher
sinon si hash = 15 alors
typeDecor vaut 3 // Maison
fin si
fin si
// Dessin des décors
si typeDecor = 1 alors
rectangle(toile1, cx - 2, cy - 18, 4, 12, #5d4037)
cercle(toile1, cx, cy - 22, 10, #2e7d32)
cercle(toile1, cx - 3, cy - 25, 6, #388e3c)
sinon si typeDecor = 2 alors
cercle(toile1, cx, cy - 4, 7, #7f8c8d)
cercle(toile1, cx - 2, cy - 6, 4, #95a5a6)
sinon si typeDecor = 3 alors
fGauche est un tableau
fGauche ajoute cx - 12
fGauche ajoute cy
fGauche ajoute cx
fGauche ajoute cy + 6
fGauche ajoute cx
fGauche ajoute cy - 18
fGauche ajoute cx - 12
fGauche ajoute cy - 24
polygone(toile1, fGauche, #bdc3c7)
fDroite est un tableau
fDroite ajoute cx
fDroite ajoute cy + 6
fDroite ajoute cx + 12
fDroite ajoute cy
fDroite ajoute cx + 12
fDroite ajoute cy - 24
fDroite ajoute cx
fDroite ajoute cy - 18
polygone(toile1, fDroite, #95a5a6)
toit est un tableau
toit ajoute cx - 12
toit ajoute cy - 24
toit ajoute cx
toit ajoute cy - 32
toit ajoute cx + 12
toit ajoute cy - 24
toit ajoute cx
toit ajoute cy - 18
polygone(toile1, toit, #c0392b)
rectangle(toile1, cx - 3, cy - 2, 5, 7, #5d4037)
fin si
// 3. Personnage principal (centré)
si rX = 0 et rY = 0 alors
ellipse(toile1, cx, cy + 3, 9, 4, #0a0f14)
rectangle(toile1, cx - 3, cy - 14, 6, 12, #e74c3c)
cercle(toile1, cx, cy - 18, 5, #f1c40f)
fin si
fin si
fin pour
fin pour
// Interface HUD & Coordonnées GPS
contour(toile1, #0)
rectangle(toile1, 0, 0, 400, 45, rgba(17, 17, 17, 0.2))
label(toile1, 10, 18, "Monde Isométrique Infini", #ffffff, 13)
txtCoords est un texte
txtCoords vaut "Position X : " + jX + " | Y : " + jY
label(toile1, 10, 35, txtCoords, #f1c40f, 11)
affiche toile1
appuyer ["z", "s", "q", "d"] dans action
nouvX est un nombre
nouvY est un nombre
nouvX vaut jX
nouvY vaut jY
si action = 1 alors
nouvY vaut jY - 1
sinon si action = 2 alors
nouvY vaut jY + 1
sinon si action = 3 alors
nouvX vaut jX - 1
sinon si action = 4 alors
nouvX vaut jX + 1
fin si
// Verification des collisions procédurales à la volée
chkX est un nombre
chkY est un nombre
chkX vaut nouvX + 50000
chkY vaut nouvY + 50000
solFutur est un nombre
solFutur vaut 0
si chkX mod 14 = 0 ou chkY mod 14 = 0 alors
solFutur vaut 1
sinon si (chkX * 3 + chkY * 2) mod 31 < 2 alors
solFutur vaut 2
fin si
decorFutur est un nombre
decorFutur vaut 0
si solFutur = 0 alors
hFutur est un nombre
hFutur vaut (chkX * 17 + chkY * 37) mod 100
si hFutur = 15 alors
decorFutur vaut 3
fin si
fin si
// Collision avec l'eau et les bâtiments
si solFutur <> 2 et decorFutur <> 3 alors
jX vaut nouvX
jY vaut nouvY
fin si
fin tant que


