猫史档案馆


【教程】模板太单一?教你自己生成山水图!

用户:萌新大佬萌新大佬查看:15 回复:11 评论:15 创建时间:2022-04-08T17:02:55


今天想做个图(虽然我也不知道想做什么),但是觉得官方的模板肯定没前途,所以自己写了个随机山水生成。

 

1.建个图

不用多说了吧!这里说明一下,我的图是128*128*128的,如果你的图是256*256*256,请把代码中的127全部改成255。

 

2.把地面换成水

简单速建

for (let i = 0; i < 127; i++) {
    for (let j = 0; j < 127; j++) {
        voxels.setVoxel(i, 8, j, 'water');
    }
}

 

3.定好顶峰的坐标

function mountain() {//写个函数封装
    var x = Math.floor(Math.random() * 127);//随机x坐标
    var z = Math.floor(Math.random() * 127);//随机z坐标
    //不写y坐标是因为山肯定在地上
}

 

4.建立一个函数

这个函数只是方便而已,个人习惯,也可以直接放在mountain里。

function column(x, z, heigth) {//这个函数能建立一个顶为喵的泥柱子
    for (let y = 8; y <= heigth + 6; y++) {//除最高的块以外都是泥,y从水面遍历到山顶-1
        voxels.setVoxel(x, y, z, 'dirt');
    }
    voxels.setVoxel(x, heigth + 7, z, 'grass');//最后在顶上放一块喵
}

 

5.开始灌水

所谓灌水,就是在模拟水从高处往下流的过程,向前后左右扩散。

首先建立一个vis数组

function mountain() {//写个函数封装
    var x = Math.floor(Math.random() * 127);//随机x坐标
    var z = Math.floor(Math.random() * 127);//随机z坐标
    //不写y坐标是因为山肯定在地上
    var vis = [];//建立visit数组记录是否在此已经有山了
    for (let i = 0; i < 127; i++) {
        var k = [];//k只是一个工具数组
        for (let j = 0; j < 127; j++) {
            k.push(false);//把每一行是否经过都设成false
        }
        vis.push(k);//把这一行挤进vis里
    }
}

然后再创建一个递归数组

function dfs(x, z, heigth, vis) {
    if (x < 0 || x >= 127 || z < 0 || z >= 127) return;//到边界退出
    if (heigth <= 0) return;//高度减没了也退出
    if (vis[x][z]) return;//如果这个点建过了也退出
    vis[x][z] = true;
    column(x, z, heigth);//在这个位置建个柱子
    if (Math.random() > 0.4)//只有一定概率延伸,否则不延伸,防止满地都是山
        dfs(x + 1, z, heigth + Math.floor(Math.random() * 10 - 6)/*高度在3~-7间随机波动,大概率最终降为零*/, vis);
    if (Math.random() > 0.4)
        dfs(x - 1, z, heigth + Math.floor(Math.random() * 10 - 6), vis);
    if (Math.random() > 0.4)
        dfs(x, z - 1, heigth + Math.floor(Math.random() * 10 - 6), vis);
    if (Math.random() > 0.4)
        dfs(x, z + 1, heigth + Math.floor(Math.random() * 10 - 6), vis);//分别向四个方向延伸
}

最后以主峰为起点灌水

function mountain() {//写个函数封装
    var x = Math.floor(Math.random() * 127);//随机x坐标
    var z = Math.floor(Math.random() * 127);//随机z坐标
    //不写y坐标是因为山肯定在地上
    var vis = [];//建立visit数组记录是否在此已经有山了
    for (let i = 0; i < 127; i++) {
        var k = [];//k只是一个工具数组
        for (let j = 0; j < 127; j++) {
            k.push(false);//把每一行是否经过都设成false
        }
        vis.push(k);//把这一行挤进vis里
    }
    dfs(x, z, Math.floor(Math.random() * 10 + 45)/*主峰高度在45~55之间随机*/, vis);
}

 

6.别忘了调用

mountain();
mountain();
mountain();
mountain();
mountain();
mountain();
mountain();//多建几座山

 

 

运行效果:

center_image

 

 

 

 

完整代码:

for (let i = 0; i < 127; i++) {
    for (let j = 0; j < 127; j++) {
        voxels.setVoxel(i, 8, j, 'water');
    }
}
function mountain() {//写个函数封装
    var x = Math.floor(Math.random() * 127);//随机x坐标
    var z = Math.floor(Math.random() * 127);//随机z坐标
    //不写y坐标是因为山肯定在地上
    var vis = [];//建立visit数组记录是否在此已经有山了
    for (let i = 0; i < 127; i++) {
        var k = [];//k只是一个工具数组
        for (let j = 0; j < 127; j++) {
            k.push(false);//把每一行是否经过都设成false
        }
        vis.push(k);//把这一行挤进vis里
    }
    dfs(x, z, Math.floor(Math.random() * 10 + 45)/*主峰高度在45~55之间随机*/, vis);
}
function column(x, z, heigth) {//这个函数能建立一个顶为喵的泥柱子
    for (let y = 8; y <= heigth + 6; y++) {//除最高的块以外都是泥,y从水面遍历到山顶-1
        voxels.setVoxel(x, y, z, 'dirt');
    }
    voxels.setVoxel(x, heigth + 7, z, 'grass');//最后在顶上放一块喵
}
function dfs(x, z, heigth, vis) {
    if (x < 0 || x >= 127 || z < 0 || z >= 127) return;//到边界退出
    if (heigth <= 0) return;//高度减没了也退出
    if (vis[x][z]) return;//如果这个点建过了也退出
    vis[x][z] = true;
    column(x, z, heigth);//在这个位置建个柱子
    if (Math.random() > 0.4)//只有一定概率延伸,否则不延伸,防止满地都是山
        dfs(x + 1, z, heigth + Math.floor(Math.random() * 10 - 6)/*高度在3~-7间随机波动,大概率最终降为零*/, vis);
    if (Math.random() > 0.4)
        dfs(x - 1, z, heigth + Math.floor(Math.random() * 10 - 6), vis);
    if (Math.random() > 0.4)
        dfs(x, z - 1, heigth + Math.floor(Math.random() * 10 - 6), vis);
    if (Math.random() > 0.4)
        dfs(x, z + 1, heigth + Math.floor(Math.random() * 10 - 6), vis);//分别向四个方向延伸
}
mountain();
mountain();
mountain();
mountain();
mountain();
mountain();
mountain();//多建几座山


回复

上一页1 页 / 共 1下一页
萌新大佬萌新大佬

顶顶顶顶顶

点赞1


评论


萌新大佬萌新大佬

 没有注释版本,放控制台粘这个

for (let i = 0; i < 127; i++) {
    for (let j = 0; j < 127; j++) {
        voxels.setVoxel(i, 8, j, 'water');
    }
}
function mountain() {
    var x = Math.floor(Math.random() * 127);
    var z = Math.floor(Math.random() * 127);
    var vis = [];
    for (let i = 0; i < 127; i++) {
        var k = [];
        for (let j = 0; j < 127; j++) {
            k.push(false);
        }
        vis.push(k);
    }
    dfs(x, z, Math.floor(Math.random() * 10 + 45), vis);
}
function column(x, z, heigth) {
    for (let y = 8; y <= heigth + 6; y++) {
        voxels.setVoxel(x, y, z, 'dirt');
    }
    voxels.setVoxel(x, heigth + 7, z, 'grass');
}
function dfs(x, z, heigth, vis) {
    if (x < 0 || x >= 127 || z < 0 || z >= 127) return;
    if (heigth <= 0) return;
    if (vis[x][z]) return;
    vis[x][z] = true;
    column(x, z, heigth);
    if (Math.random() > 0.4)
        dfs(x + 1, z, heigth + Math.floor(Math.random() * 10 - 6), vis);
    if (Math.random() > 0.4)
        dfs(x - 1, z, heigth + Math.floor(Math.random() * 10 - 6), vis);
    if (Math.random() > 0.4)
        dfs(x, z - 1, heigth + Math.floor(Math.random() * 10 - 6), vis);
    if (Math.random() > 0.4)
        dfs(x, z + 1, heigth + Math.floor(Math.random() * 10 - 6), vis);
}
mountain();
mountain();
mountain();
mountain();
mountain();
mountain();
mountain();

点赞1


评论


卑微OIer卑微OIer

最好平整化一下

点赞0


评论


赤道宇宙赤道宇宙

点赞0


评论


JSR代码喵JSR代码喵

这高度

点赞0


评论


灵清帝王吃爆一切厕所灵清帝王吃爆一切厕所

收藏

点赞0


评论


yee089yee089

(虽然我也写过())

点赞0


评论


神岛吉吉喵神岛吉吉喵

有点意思~

点赞0


评论


星辰_零柒星辰_零柒

收藏

点赞0


评论


alopdopsalopdops

收了

点赞0


评论


yee089yee089

多传一个参数,就可以做到平整化,信不信?()

点赞0


评论