J'ai mis au point une génération aléatoire de map, qui ressemblent un peu à celles de terraria ou autres jeux utilisant des fractales à multiples dimension compliquées pour générer leur mondes (évidement, moi j'ai trouvé plus simple et assez potable quand même).
Je poste ça ici parce que la probabilité que j'en fasse quelque chose est quasi-nulle et parce que cela pourrait être utile à d'autres.
- Code: Tout sélectionner
local rand = math.random
local floor = math.floor
local abs = math.abs
local pow = math.pow
local sqrt = math.sqrt
local biomesList = {
{.1, 8, 32, 8}
, {1, 4, 8, 4}
}
function on.resize (ww, hh)
width, height = ww, hh
w, h = width, height/2
mat = gen()
map = convertMat (mat)
end
function dist2 (x1, y1, x2, y2)
return pow(x1-x2, 2)+pow(y1-y2, 2)
end
function gen ()
local m = genMat()
local biomes = genBiomes(24, 32)
genSphericalNoise (m, biomes)
genLeveling (m, 255)
genSmoothCorner (m, 2)
return m
end
function genBiomes (min, max)
local biomes = {}
local a = 1
while a < w do
local r = rand(min, max)
local b = rand(#biomesList)
biomes[#biomes+1] = {type=b, x1=a, x2 = a+r, size = r}
a = a+r
end
biomes[#biomes].x2 = w
return biomes
end
function genLeveling (m, tol)
for a = 1, w do
local n = 0
for b = 1, h do
n=n+m[a][b]
end
n = math.floor(n/tol)
for b = 1, h do
if n > 0 then m[a][b] = tol
else m[a][b] = 0 end
n = n-1
end
end
end
function genSphericalNoise(m, biomes)
for _, bio in pairs (biomes) do
local n, min, max, v = unpack (biomesList[bio.type])
for i = 1, n*bio.size do
local r = rand (min, max)
local r2 = r*r
local x = rand (bio.x1, bio.x2)
local y = rand (h)
for a = x-r, x+r do
for b = y-r, y+r do
local d = dist2(a, b, x, y)
if d <=r2 then
pcall (function () m[a][b] = sqrt(d)*v end)
end
end
end
end
end
end
function genSmoothCorner (m, tol)
local he = {}
for a = 1, w do
he[a] = 0
for b = 1, h do
he[a] = he[a]+m[a][b]/255
end
end
for a = 2, w-1 do
local med = floor((he[a-1]+he[a+1])/2)
if abs (med-he[a]) > tol then
for b = 1, h do
if med > 0 then m[a][b] = 255 else m[a][b] = 0 end
med = med-1
end
end
end
end
function genMat ()
local m = {}
for a = 1, w do
m[a] = {}
for b = 1, h do
m[a][b] = 0
end
end
return m
end
function convertMat (m)
local l = {}
for a = 1, w do
l[a] = 0
for b = 1, h do
if m[a][b] == 0 then l[a] = l[a]+1 end
end
end
return l
end
function on.paint (gc)
for a = 1, w do
gc: fillRect (a, height-map[a], 0, map[a])
end
end
La map consiste en une matrice bidimensionnelle dont deux valeurs sont possible: 255 (l'air en blanc) et 0 (le sol).
Au lieu d'utiliser des fractales très louches comme le fait terraria, je fait un bruit aléatoire consistant en des cercles dégradés de tailles différentes. La somme des cases de chaque colonne est ensuite convertie en hauteur, un petit dernier traitement est appliqué pour éliminer les pics moches et incongrus.
J'utilise une fonction qui créé une liste avec les hauteurs pour les afficher avec des rectangles de 1 de large parce que c'est (beaucoup) plus rapide à afficher.
Quelques images ainsi générées:
Encore une fois, si ce code intéresse quelqu'un (tout est possible de nos jours ), je donne tous les droits pour l'implémenter dans n'importe quel programme. Ma seule condition est de mettre dans les crédits de ce programme "Gloire à technolapin, qui m'oblige à mettre cette phrase à la noix dans les crédits pour que je puisse utiliser sa génération de map foireuse" (mot pour mot )