所以我正在为使用lua api的factorio制作一个mod。我需要Perlin噪声发生器,因此我使用网站上的指南进行了编码:https://flafla2.github.io/2014/08/09/perlinnoise.html 我首先用javascript编码,因为我比较擅长js。工作正常。但是当我将其移植到lua时,它会生成这些奇怪的块和线。
黑色表示低值,而白色表示高值
我花了最后5个小时来浏览代码,但没有任何反应。请帮忙。
下面是lua中的代码。我在每个磁贴处都叫pn.p2D(x,y)
。由于我已经多次测试,因此正确输入了x和y。 LuaRandomGenerator是一个随机数生成器,它给出随机数。
--note: pn.ran_gen is a LuaRandomGenerator which should be created
-- when pn was init
--local vals
--local functions
local sudoR = function(seed,rs,rm,gs,rg)
seed = seed%rs
rg.re_seed(seed+gs)
return rg(rm-1)
end
local lerp = function(v0,v1,t)
return v0+t*(v1-v0)
end
local fade = function(t)
return t*t*t*(t*(6*t-15)+10) -- 6t^5-15t^4+10t^3
end
local inc = function(num,rm)
return (num+1)%rm
end
local grad = function(hash,x,y,z)
local case = hash%16
if (case==0 ) then return x+y
elseif (case==1 ) then return -x+y
elseif (case==2 ) then return x-y
elseif (case==3 ) then return -x-y
elseif (case==4 ) then return x+z
elseif (case==5 ) then return -x+z
elseif (case==6 ) then return x-z
elseif (case==7 ) then return -x-z
elseif (case==8 ) then return y+z
elseif (case==9 ) then return -y+z
elseif (case==10) then return y-z
elseif (case==11) then return -y-z
elseif (case==12) then return y+x
elseif (case==13) then return -y+z
elseif (case==14) then return y-x
elseif (case==15) then return -y-z
else error("How val%16 end up being larger then 15? I guess val is not int.")
end
end
local perlin_noise = function(x,y,z,rs,rm,gs,rg)
--game.players[1].print(x)
local xi = math.floor(x) % rs
local yi = math.floor(y) % rs
local zi = math.floor(z) % rs
local xf = x - math.floor(x)
local yf = y - math.floor(y)
local zf = z - math.floor(z)
local xg = fade(xf)
local yg = fade(yf)
local zg = fade(zf)
--hashing
local aaa = sudoR(sudoR(sudoR( xi ,rs,rm,gs,rg)+ yi ,rs,rm,gs,rg)+ zi ,rs,rm,gs,rg)
local aba = sudoR(sudoR(sudoR( xi ,rs,rm,gs,rg)+inc(yi,rm),rs,rm,gs,rg)+ zi ,rs,rm,gs,rg)
local aab = sudoR(sudoR(sudoR( xi ,rs,rm,gs,rg)+ yi ,rs,rm,gs,rg)+inc(zi,rm),rs,rm,gs,rg)
local abb = sudoR(sudoR(sudoR( xi ,rs,rm,gs,rg)+inc(yi,rm),rs,rm,gs,rg)+inc(zi,rm),rs,rm,gs,rg)
local baa = sudoR(sudoR(sudoR(inc(xi,rm),rs,rm,gs,rg)+ yi ,rs,rm,gs,rg)+ zi ,rs,rm,gs,rg)
local bba = sudoR(sudoR(sudoR(inc(xi,rm),rs,rm,gs,rg)+inc(yi,rm),rs,rm,gs,rg)+ zi ,rs,rm,gs,rg)
local bab = sudoR(sudoR(sudoR(inc(xi,rm),rs,rm,gs,rg)+ yi ,rs,rm,gs,rg)+inc(zi,rm),rs,rm,gs,rg)
local bbb = sudoR(sudoR(sudoR(inc(xi,rm),rs,rm,gs,rg)+inc(yi,rm),rs,rm,gs,rg)+inc(zi,rm),rs,rm,gs,rg)
--gen result
local x1 = lerp(grad (aaa, xf , yf , zf),
grad (baa, xf-1, yf , zf),
xg)
local x2 = lerp(grad (aba, xf , yf-1, zf),
grad (bba, xf-1, yf-1, zf),
xg)
local y1 = lerp(x1, x2, yg)
x1 = lerp(grad (aab, xf , yf , zf-1),
grad (bab, xf-1, yf , zf-1),
xg)
x2 = lerp(grad (abb, xf , yf-1, zf-1),
grad (bbb, xf-1, yf-1, zf-1),
xg)
local y2 = lerp(x1, x2, yg)
local z1 = lerp(y1, y2, zg)
return (z1+1)/2
end
local octave_perlin = function(x,y,z,octaves,persistence,rs,rm,gs,rg)
local total = 0
local fre = 1
local amp = 1
local maxValue = 0
for i=1, octaves do
total = total+perlin_noise(x*fre,y*fre,z*fre,rs,rm,gs,rg)*amp
maxValue = maxValue+amp
amp = amp*persistence
fre = fre*2
end
return total/maxValue
end
--useable functions/vals
local pn = {}
pn.ran_max = 256
pn.ran_size = 256
pn.default_z = 4
pn.seed = 0--nil
pn.octaves = 8
pn.persistence = 0.5
pn.scale = 64
pn.ran_gen = nil
pn.init = function()
--pn.ran_max = settings
--pn.seed = game.default_map_gen_settings.seed
pn.ran_gen = game.create_random_generator()
end
pn.p3D = function(x,y,z)
return fade(octave_perlin(x/pn.scale,y/pn.scale,z/pn.scale,pn.octaves,pn.persistence,pn.ran_size,pn.ran_max,pn.seed,pn.ran_gen))
end
pn.p2D = function(x,y)
return pn.p3D(x,y,pn.default_z)
end
pn.simple3D = function(x,y,z)
return fade(perlin_noise(x/pn.scale,y/pn.scale,z/pn.scale,pn.ran_size,pn.ran_max,pn.seed,pn.ran_gen))
end
pn.simple2D = function(x,y)
return pn.simple3D(x,y,pn.default_z)
end
return pn
下一个代码块是使用p5.js在javascript中工作的代码块。您可以将其复制到https://editor.p5js.org/中以查看弹出结果。
grid = [];
w = 2;
g = 400/w-1;
ran = [];
ran_num = 256;
ran_seed = 51;
p = [];
psize = 64;
function setup() {
noStroke();
createCanvas(400, 400);
randomSeed(ran_seed);
perlin_setup();
pDetails = 8; //int
pDetailsWeight = 0.5; //between 0 and 0.5
for (x=0;x<g;x++) {
grid[x] = [];
for (y=0;y<g;y++) {
//grid[x][y] = perlin_noise(x/16,y/16,0)*256;
grid[x][y] = fade(octave_perlin(x/psize,y/psize,0,pDetails,pDetailsWeight))*256;
}
}
}
function inc(num) {
num++;
num = num%ran_num;
return num;
}
function fade(t) {
return t*t*t*(t*(6*t-15)+10); //6t^5-15t^4+10t^3
}
function grad(hash,x,y,z) {
switch(hash%16) {
case 0: return x + y;
case 1: return -x + y;
case 2: return x - y;
case 3: return -x - y;
case 4: return x + z;
case 5: return -x + z;
case 6: return x - z;
case 7: return -x - z;
case 8: return y + z;
case 9: return -y + z;
case 10: return y - z;
case 11: return -y - z;
case 12: return y + x;
case 13: return -y + z;
case 14: return y - x;
case 15: return -y - z;
default: return 0; // never happens
}
}
function perlin_setup() {
for (i=0;i<ran_num;i++) {
ran[i] = floor(random(256));
p[i] = ran[i];
p[i+ran_num] = ran[i];
}
}
function perlin_noise(x,y,z) {
xi = floor(x)%ran_num;
yi = floor(y)%ran_num;
zi = floor(z)%ran_num;
xf = x-floor(x);
yf = y-floor(y);
zf = z-floor(z);
u = fade(xf);
v = fade(yf);
h = fade(zf);
//console.log(" "+h);
//hashing
aaa = p[p[p[ xi ]+ yi ]+ zi ];
aba = p[p[p[ xi ]+inc(yi)]+ zi ];
aab = p[p[p[ xi ]+ yi ]+inc(zi)];
abb = p[p[p[ xi ]+inc(yi)]+inc(zi)];
baa = p[p[p[inc(xi)]+ yi ]+ zi ];
bba = p[p[p[inc(xi)]+inc(yi)]+ zi ];
bab = p[p[p[inc(xi)]+ yi ]+inc(zi)];
bbb = p[p[p[inc(xi)]+inc(yi)]+inc(zi)];
//gen result
x1 = lerp(grad (aaa, xf , yf , zf),
grad (baa, xf-1, yf , zf),
u);
x2 = lerp(grad (aba, xf , yf-1, zf),
grad (bba, xf-1, yf-1, zf),
u);
y1 = lerp(x1, x2, v);
x1 = lerp(grad (aab, xf , yf , zf-1),
grad (bab, xf-1, yf , zf-1),
u);
x2 = lerp(grad (abb, xf , yf-1, zf-1),
grad (bbb, xf-1, yf-1, zf-1),
u);
y2 = lerp(x1, x2, v);
z1 = lerp(y1, y2, h);
return (z1+1)/2;
}
function octave_perlin(x,y,z,octaves,persistence) {
total = 0;
fre = 1;
amp = 1;
maxValue = 0;
for(i=0;i<octaves;i++) {
total += perlin_noise(x*fre,y*fre,z*fre)*amp;
maxValue += amp;
amp *= persistence;
fre *= 2;
}
return total/maxValue;
}
function draw() {
background(220);
for (x=0;x<g;x++) {
for (y=0;y<g;y++) {
fill(0,0,255);
if (x==0) {
fill(255, 125, 0);
} else if (y==0) {
fill(0,255,255);
} else {
fill(grid[x][y]);
}
rect(x*w+w/2, y*w+w/2, w, w);
}
}
noLoop();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.js"></script>