# 03 获取方块

(点击->高清B站视频) (opens new window)


1.单个圆柱体生成

API: voxels.setVoxel()

function cylinder(cx,cy,cz,vox,radius,height){
  var xend = cx+radius
  var yend = cy+height
  var zend = cz+radius
  for(var x=cx-radius;x<=xend;x++){
    for(var z=cz-radius;z<=zend;z++){
      var dx = x-cx;
      var dz = z-cz;
      if(Math.round(Math.sqrt(dx*dx+dz*dz))<=radius){
        for(var y=cy;y<yend;y++){
          voxels.setVoxel(x,y,z,vox)
        }
      }
    }
  }
}

cylinder(63,9,63,'dirt',3,1)// 演示圆柱不同半径和高度

2.多个圆柱体随机生成复杂地形

API: voxels.setVoxel()

function cylinder(cx,cy,cz,vox,radius,height){
  var xend = cx+radius
  var yend = cy+height
  var zend = cz+radius
  for(var x=cx-radius;x<=xend;x++){
    for(var z=cz-radius;z<=zend;z++){
      var dx = x-cx;
      var dz = z-cz;
      if(Math.round(Math.sqrt(dx*dx+dz*dz))<=radius){
        for(var y=cy;y<yend;y++){
          voxels.setVoxel(x,y,z,vox)
        }
      }
    }
  }
}

for(var i=0;i<300;i++){ // 300个随机圆柱体构成场景
  let x = Math.random() * 125 // x坐标
  let z = Math.random() * 125 // z坐标
  let r = 2 + Math.random() * 5 //半径 2~7
  let h = Math.random() * 4 // 高 0~4
  cylinder(x,9,z,'dirt',r,h)
}

3.扫描检测地形表面 改成草地

API: voxels.getVoxel()

function cylinder(cx,cy,cz,vox,radius,height){
  var xend = cx+radius
  var yend = cy+height
  var zend = cz+radius
  for(var x=cx-radius;x<=xend;x++){
    for(var z=cz-radius;z<=zend;z++){
      var dx = x-cx;
      var dz = z-cz;
      if(Math.round(Math.sqrt(dx*dx+dz*dz))<=radius){
        for(var y=cy;y<yend;y++){
          voxels.setVoxel(x,y,z,vox)
        }
      }
    }
  }
}

for(var i=0;i<300;i++){ // 300个随机圆柱体构成场景
  let x = Math.random() * 125 // x坐标
  let z = Math.random() * 125 // z坐标
  let r = 2 + Math.random() * 5 //半径 2~7
  let h = Math.random() * 4 // 高 0~4
  cylinder(x,9,z,'dirt',r,h)
}

for(var y=9;y<13;y++){//扫描9~12层的格子
  for(var x=0;x<127;x++){
    for(var z=0;z<127;z++){
      if(voxels.getVoxel(x,y,z)!=0 && voxels.getVoxel(x,y+1,z)==0){// 如果当前格子不为空而它上面那格是空的, 则表示它是此地形的表面 
        voxels.setVoxel(x,y,z,'grass')// 土块替换成草地
      }
    }
  }
}

4.结合上个教程, 在复杂地形生成花草树木

API: world.createEntity()

function cylinder(cx,cy,cz,vox,radius,height){
  var xend = cx+radius
  var yend = cy+height
  var zend = cz+radius
  for(var x=cx-radius;x<=xend;x++){
    for(var z=cz-radius;z<=zend;z++){
      var dx = x-cx;
      var dz = z-cz;
      if(Math.round(Math.sqrt(dx*dx+dz*dz))<=radius){
        for(var y=cy;y<yend;y++){
          voxels.setVoxel(x,y,z,vox)
        }
      }
    }
  }
}

for(var i=0;i<300;i++){ // 300个随机圆柱体构成场景
  let x = Math.random() * 125 // x坐标
  let z = Math.random() * 125 // z坐标
  let h = Math.random() * 4 // 高 0~4
  let r = 2 + Math.random() * 5 //半径 2~7
  cylinder(x,9,z,'dirt',r,h)
}

for(var y=9;y<13;y++){//扫描9~12层的格子
  for(var x=0;x<127;x++){
    for(var z=0;z<127;z++){
      // 如果当前格子不为空而它上面那格是空的, 则表示它是复杂地形的表面 
      if(voxels.getVoxel(x,y,z)!=0 && voxels.getVoxel(x,y+1,z)==0){
        voxels.setVoxel(x,y,z,'grass')// 土块替换成草地
        
        // 在草地上以3%的几率生成3种植物的其中一种
        var rnd = Math.random()
        var cx = x+0.5 // 修正到方块中心的x坐标
        var cz = z+0.5 // 修正到方块中心的z坐标
        if(rnd<0.01){
          spawn(cx,y+1,cz,'mesh/树.vb',3+2.5*Math.random())
        }else if(rnd<0.02){
          spawn(cx,y+1,cz,'mesh/花.vb',0.8)
        }else if(rnd<0.03){
          spawn(cx,y+1,cz,'mesh/茂盛的草.vb',0.8)
        }
      }
    }
  }
}

async function correctY(entity){
  await sleep(1)//entity.bounds需要等到下一个tick才会变成真正的值
  entity.position.y += entity.bounds.y//bounds.y是中心点到模型顶部或底部的距离
}

function spawn(x,y,z,meshName,scale){
  const meshScale = scale/16 //默认模型方块大小倍数为地图方块的1/16
  const entity = world.createEntity({
    mesh:meshName,//模型名
    collides:false,//不能碰撞
    fixed:true,//固定
    gravity:false,// 不受重力影响
    meshScale:[meshScale,meshScale,meshScale],//xyz放大倍数
    position:[x,y,z],//位置坐标
  })
  correctY(entity)
  return entity
}