Hello I have this code:
<!DOCTYPE html>
<html>
<head>
<title>3D Minecraft</title>
<style type="text/css">
body {
margin : 0;
}
#cursor {
position : absolute;
width : 3%;
}
</style>
</head>
<body>
<script src = "three.js"></script>
<script src = "perlin.js"></script>
<script src = "PointerLockControls.js"></script>
<script src = "stats.js"></script>
<img src = "cursor.png" id = "cursor">
<script type="text/javascript">
// Cursor
var cursor = document.getElementById("cursor");
cursor.style.left = ((0.5 * window.innerWidth) - (0.5 * cursor.width)).toString() + "px";
cursor.style.top = ((0.5 * window.innerHeight) - (0.5 * cursor.height)).toString() + "px";
// Performance Stats
var stats = new Stats();
stats.showPanel(0); // 0:fps, 1:ms, 2:mb, 3+:custom
document.body.appendChild(stats.dom);
function animate(){
stats.begin();
// monitored code goes between this called functions
stats.end();
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
noise.seed(Math.random());
var scene = new THREE.Scene();
scene.background = new THREE.Color(0x00ffff);
scene.fog = new THREE.Fog(0x00ffff, 10, 650);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
/*
var groundBox = new THREE.BoxBufferGeometry(25, 1, 50);
var groundMesh = new THREE.MeshBasicMaterial({color : 0x00ff00});
var ground = new THREE.Mesh(groundBox, groundMesh);
scene.add(ground);
ground.position.y = -5;
// Creating the border lines for ground
var edges = new THREE.EdgesGeometry(groundBox);
var line = new THREE.LineSegments(edges, new THREE.LineBasicMaterial({color : 0x000000}));
scene.add(line);
line.position.y = -5;
*/
var faces = [
{ // left
dir: [ -5, 0, 0, "left"],
},
{ // right
dir: [ 5, 0, 0, "right"],
},
{ // bottom
dir: [ 0, -5, 0, "bottom"],
},
{ // top
dir: [ 0, 5, 0, "top"],
},
{ // back
dir: [ 0, 0, -5, "back"],
},
{ // front
dir: [ 0, 0, 5, "front"],
},
];
function Block(x, y, z, placed, blockType){
this.x = x;
this.y = y;
this.z = z;
this.placed = placed;
this.blockType = blockType;
}
var blocks = {
grass : {
color : new THREE.Color("rgb(0, 200, 0)"),
name : "grass",
},
dirt : {
color : new THREE.Color("rgb(115, 90, 53)"),
name : "dirt",
},
cobblestone : {
color : new THREE.Color("rgb(90, 90, 90)"),
name : "cobblestone"
}
};
// var axesHelper = new THREE.AxesHelper( 5 );
// scene.add( axesHelper );
/*
var blocks = [];
var xoff = 0;
var zoff = 0;
var inc = 0.05;
var amplitude = 50;
for(var x = 0; x < 20; x++){
xoff = 0;
for(var z = 0; z < 20; z++){
var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5) * 5;
blocks.push(new Block(x * 5, v, z * 5));
xoff = xoff + inc;
}
zoff = zoff + inc;
}
*/
var chunks = [];
var xoff = 0;
var zoff = 0;
var inc = 0.05;
var amplitude = 30 + (Math.random() * 70);
var renderDistance = 5;
var chunkSize = 10;
camera.position.x = renderDistance * chunkSize / 2 * 5;
camera.position.z = renderDistance * chunkSize / 2 * 5;
camera.position.y = 50;
var loader = new THREE.TextureLoader();
var materialArray = [
new THREE.MeshBasicMaterial({map : loader.load("texture/texture.png")}),
new THREE.MeshBasicMaterial({map : loader.load("texture/texture.png")}),
new THREE.MeshBasicMaterial({map : loader.load("texture/texture.png")}),
new THREE.MeshBasicMaterial({map : loader.load("texture/texture.png")}),
new THREE.MeshBasicMaterial({map : loader.load("texture/texture.png")}),
new THREE.MeshBasicMaterial({map : loader.load("texture/texture.png")}),
];
var depth = 5; // keeps track of the depth of the world (in terms of blocks)
var minWorldY = -250; // the minimum y coordinate of a block
var blockBox = new THREE.BoxGeometry(5, 5, 5)
var instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, renderDistance * renderDistance * chunkSize * chunkSize * depth);
var count = 0;
for(var i = 0; i < renderDistance; i++){
for(j = 0; j < renderDistance; j++){
var chunk = [];
for(var x = i * chunkSize; x < (i * chunkSize) + chunkSize; x++){
for(var z = j * chunkSize; z < (j * chunkSize) + chunkSize; z++){
xoff = inc * x;
zoff = inc * z;
var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5) * 5;
for(var d = 0; d < depth; d++){
if(v - (d * 5) < minWorldY){
continue;
}
let matrix = new THREE.Matrix4().makeTranslation(
x * 5,
v - (d * 5),
z * 5
);
instancedChunk.setMatrixAt(count, matrix);
var color = null;
var blockType = null;
if(d == 0){
color = blocks.grass.color;
blockType = blocks.grass.name;
} else if(d == 1 || d == 2 || d == 3){
color = blocks.dirt.color;
blockType = blocks.dirt.name;
} else if(d > 3){
color = blocks.cobblestone.color;
blockType = blocks.cobblestone.name;
}
instancedChunk.setColorAt(count, color);
count++;
chunk.push(new Block(x * 5, v - (d * 5), z * 5, false, blockType));
}
}
}
chunks.push(chunk);
}
}
scene.add(instancedChunk);
var keys = [];
var canJump = true;
var controlOptions = {
forward : "w",
backward : "s",
right : "d",
left : "a",
jump : " ", // " " = space
placeBlock : "q"
};
var placedBlocks = [];
var chunkMap = [];
for(var x = 0; x < renderDistance; x++){
for(var z = 0; z < renderDistance; z++){
chunkMap.push({x : x, z : z});
}
}
function identifyChunk(x, z){
var lowestX = lowestXBlock();
var lowestZ = lowestZBlock();
var difX = x - lowestX;
var difZ = z - lowestZ;
var divX = Math.floor(difX / (chunkSize * 5));
var divZ = Math.floor(difZ / (chunkSize * 5));
var index = undefined;
for(var i = 0; i < chunkMap.length; i++){
if(chunkMap[i].x == divX && chunkMap[i].z == divZ){
index = i;
break;
}
}
return index; // Identified the chunks!!!
}
var start = 0;
var sprint = false;
document.addEventListener("keydown", function(e){
if(e.key == "w") {
var elapsed = new Date().getTime();
if(elapsed - start <= 300){
sprint = true;
}
start = elapsed;
}
keys.push(e.key);
if(e.key == controlOptions.jump && canJump == true){
ySpeed = -1;
canJump = false;
}
if(e.key == controlOptions.placeBlock){
const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();
pointer.x = (0.5) * 2 - 1;
pointer.y = -1 * (0.5) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
var intersection = raycaster.intersectObject(instancedChunk);
if(intersection[0] != undefined && intersection[0].distance < 40){
console.log(intersection[0]);
var materialIndex = intersection[0].face.materialIndex;
var position = intersection[0].point; // object with x, y and z coords
var x = 0;
var y = 0;
var z = 0;
const inc = 2.5;
switch(materialIndex){
case 0: // right
x = position.x + inc;
y = Math.round(position.y / 5) * 5;
z = Math.round(position.z / 5) * 5;
break;
case 1: // left
x = position.x - inc;
y = Math.round(position.y / 5) * 5;
z = Math.round(position.z / 5) * 5;
break;
case 2: // top
x = Math.round(position.x / 5) * 5;
y = position.y + inc;
z = Math.round(position.z / 5) * 5;
break;
case 3: // bottom
x = Math.round(position.x / 5) * 5;
y = position.y - inc;
z = Math.round(position.z / 5) * 5;
break;
case 4: // front
x = Math.round(position.x / 5) * 5;
y = Math.round(position.y / 5) * 5;
z = position.z + inc;
break;
case 5: // back
x = Math.round(position.x / 5) * 5;
y = Math.round(position.y / 5) * 5;
z = position.z - inc;
break;
}
y = Math.round(y); // sometimes, y is for some reason e.g 4.999999999999
if(y > minWorldY){
var blockToBePlaced = "cobblestone";
var b = new Block(x, y, z, true, blockToBePlaced);
if(!intersect(b.x, b.y, b.z, 5, 5, 5, player.x, player.y, player.z, player.w, player.h, player.d)){
chunks[identifyChunk(x, z)].push(new Block(x, y, z, true, blockToBePlaced));
placedBlocks.push(b);
scene.remove(instancedChunk);
instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, (renderDistance * renderDistance * chunkSize * chunkSize * depth) + placedBlocks.length);
var count = 0;
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
let matrix = new THREE.Matrix4().makeTranslation(
chunks[i][j].x,
chunks[i][j].y,
chunks[i][j].z
);
instancedChunk.setMatrixAt(count, matrix);
var color = null;
if(chunks[i][j].blockType == "grass"){
color = blocks.grass.color;
} else if(chunks[i][j].blockType == "dirt"){
color = blocks.dirt.color;
} else if(chunks[i][j].blockType == "cobblestone"){
color = blocks.cobblestone.color;
}
instancedChunk.setColorAt(count, color);
count++;
}
}
scene.add(instancedChunk);
}
}
}
}
});
document.addEventListener("keyup", function(e){
var newArr = [];
for(var i = 0; i < keys.length; i++){
if(keys[i] != e.key){
newArr.push(keys[i]);
}
}
keys = newArr;
if(!keys.includes("w")){
sprint = false;
}
});
var controls = new THREE.PointerLockControls(camera, document.body);
var brokenBlocks = [];
document.body.addEventListener("click", function(){
controls.lock();
// Breaking blocks
if(controls.isLocked){
// Shooting a ray
const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();
pointer.x = (0.5) * 2 - 1;
pointer.y = -1 * (0.5) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
var intersection = raycaster.intersectObject(instancedChunk);
if(intersection[0] != undefined && intersection[0].distance < 40){
// finding x, y, z positions of that
console.log(intersection[0].point);
var materialIndex = intersection[0].face.materialIndex;
var position = intersection[0].point; // object with x, y and z coords
var x = 0;
var y = 0;
var z = 0;
const inc = 2.5;
switch(materialIndex){ // finding x, y, z positions of block
case 0: // right
x = position.x - inc;
y = Math.round(position.y / 5) * 5;
z = Math.round(position.z / 5) * 5;
break;
case 1: // left
x = position.x + inc;
y = Math.round(position.y / 5) * 5;
z = Math.round(position.z / 5) * 5;
break;
case 2: // top
x = Math.round(position.x / 5) * 5;
y = position.y - inc;
z = Math.round(position.z / 5) * 5;
break;
case 3: // bottom
x = Math.round(position.x / 5) * 5;
y = position.y + inc;
z = Math.round(position.z / 5) * 5;
break;
case 4: // front
x = Math.round(position.x / 5) * 5;
y = Math.round(position.y / 5) * 5;
z = position.z - inc;
break;
case 5: // back
x = Math.round(position.x / 5) * 5;
y = Math.round(position.y / 5) * 5;
z = position.z + inc;
break;
}
// Find block with those x, y, z positions
// More efficient by finding it inside it's chunk
var index1 = identifyChunk(x, z);
var chunk = chunks[index1];
y = Math.round(y); // sometimes, y is for some reason e.g 4.999999999999
for(var i = 0; i < chunk.length; i++){
if(chunk[i].x == x && chunk[i].y == y && chunk[i].z == z){
// Found the block!
if(chunk[i].placed){
// find the placedBlock and remove it
for(var j = 0; j < placedBlocks.length; j++){
if(placedBlocks[j].x == x && placedBlocks[j].y == y && placedBlocks[j].z == z){
placedBlocks.splice(j, 1);
break;
}
}
} else { // if it is a normal block
brokenBlocks.push(new Block(x, y, z, false, chunk[i].blockType));
}
chunks[index1].splice(i, 1); // block is removed from chunks variable
break;
}
}
// update chunks, array.splice(index, 1);
scene.remove(instancedChunk);
instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, (renderDistance * renderDistance * chunkSize * chunkSize * depth) + placedBlocks.length);
var count = 0;
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
let matrix = new THREE.Matrix4().makeTranslation(
chunks[i][j].x,
chunks[i][j].y,
chunks[i][j].z
);
instancedChunk.setMatrixAt(count, matrix);
var color;
if(chunks[i][j].blockType == "grass"){
color = blocks.grass.color;
} else if(chunks[i][j].blockType == "dirt"){
color = blocks.dirt.color;
} else if(chunks[i][j].blockType == "cobblestone"){
color = blocks.cobblestone.color;
}
instancedChunk.setColorAt(count, color);
count++;
}
}
scene.add(instancedChunk);
}
}
});
controls.addEventListener("lock", function(){
});
controls.addEventListener("unlock", function(){
keys = [];
});
var movingSpeed = 0.5;
var ySpeed = 0;
var acc = 0.065;
var player = {
w : 0.6, // width
h : 8, // height
d : 0.5, // depth
x : camera.position.x,
y : camera.position.y,
z : camera.position.z,
forward : function(speed){
controls.moveForward(speed);
this.updatePosition();
},
backward : function(speed){
controls.moveForward(-1 * speed);
this.updatePosition();
},
right : function(speed){
controls.moveRight(speed);
this.updatePosition();
},
left : function(speed){
controls.moveRight(-1 * speed);
this.updatePosition();
},
updatePosition : function(){
this.x = camera.position.x;
this.y = camera.position.y - (this.h / 2);
this.z = camera.position.z;
}
};
function intersect(x1, y1, z1, w1, h1, d1, x2, y2, z2, w2, h2, d2){
var a = {
minX : x1 - (w1/2),
maxX : x1 + (w1/2),
minZ : z1 - (d1/2),
maxZ : z1 + (d1/2),
minY : y1 - (h1/2),
maxY : y1 + (h1/2),
};
var b = {
minX : x2 - (w2/2),
maxX : x2 + (w2/2),
minZ : z2 - (d2/2),
maxZ : z2 + (d2/2),
minY : y2 - (h2/2),
maxY : y2 + (h2/2),
};
return (a.minX <= b.maxX && a.maxX >= b.minX) &&
(a.minY <= b.maxY && a.maxY >= b.minY) &&
(a.minZ <= b.maxZ && a.maxZ >= b.minZ);
}
var deceleration = 1.35;
var forback = 0; // 1 = forward, -1 = backward
var rightleft = 0; // 1 = right, -1 = left
var sprintSpeedInc = 1.6; // 30% faster than walking
function update(){
player.updatePosition();
if(keys.includes(controlOptions.forward)){
player.forward(movingSpeed * (sprint ? sprintSpeedInc : 1));
forback = 1 * movingSpeed;
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
var b = chunks[i][j];
var c = intersect(b.x, b.y, b.z, 5, 5, 5, player.x, player.y, player.z, player.w, player.h, player.d);
if(c && (b.y - 2.5 < player.y + (player.h / 2) && b.y + 2.5 > player.y - (player.h / 2))){
player.backward((movingSpeed * (sprint ? sprintSpeedInc : 1)));
forback = 0;
rightleft = 0;
sprint = false;
}
}
}
}
if(keys.includes(controlOptions.backward)){
player.backward(movingSpeed * (sprint ? sprintSpeedInc : 1));
forback = -1 * movingSpeed;
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
var b = chunks[i][j];
var c = intersect(b.x, b.y, b.z, 5, 5, 5, player.x, player.y, player.z, player.w, player.h, player.d);
if(c && (b.y - 2.5 < player.y + (player.h / 2) && b.y + 2.5 > player.y - (player.h / 2))){
player.forward(movingSpeed * (sprint ? sprintSpeedInc : 1));
forback = 0;
rightleft = 0;
sprint = false;
}
}
}
}
if(keys.includes(controlOptions.right)){
player.right(movingSpeed * (sprint ? sprintSpeedInc : 1));
rightleft = 1 * movingSpeed;
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
var b = chunks[i][j];
var c = intersect(b.x, b.y, b.z, 5, 5, 5, player.x, player.y, player.z, player.w, player.h, player.d);
if(c && (b.y - 2.5 < player.y + (player.h / 2) && b.y + 2.5 > player.y - (player.h / 2))){
player.left(movingSpeed * (sprint ? sprintSpeedInc : 1));
forback = 0;
rightleft = 0;
sprint = false;
}
}
}
}
if(keys.includes(controlOptions.left)){
player.left(movingSpeed * (sprint ? sprintSpeedInc : 1));
rightleft = -1 * movingSpeed;
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
var b = chunks[i][j];
var c = intersect(b.x, b.y, b.z, 5, 5, 5, player.x, player.y, player.z, player.w, player.h, player.d);
if(c && (b.y - 2.5 < player.y + (player.h / 2) && b.y + 2.5 > player.y - (player.h / 2))){
player.right(movingSpeed * (sprint ? sprintSpeedInc : 1));
forback = 0;
rightleft = 0;
sprint = false;
}
}
}
}
// Decceleration part
if(!keys.includes(controlOptions.forward) && !keys.includes(controlOptions.backward) && !keys.includes(controlOptions.right) && !keys.includes(controlOptions.left)){
forback /= deceleration;
rightleft /= deceleration;
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
var b = chunks[i][j];
var c = intersect(b.x, b.y, b.z, 5, 5, 5, player.x, player.y, player.z, player.w, player.h, player.d);
if(c && (b.y - 2.5 < player.y + (player.h / 2) && b.y + 2.5 > player.y - (player.h / 2))){
var br = true;
forback /= -deceleration;
rightleft /= -deceleration;
sprint = false;
break;
}
}
if(br){
break;
}
}
player.forward(forback * (sprint ? sprintSpeedInc : 1));
player.right(rightleft * (sprint ? sprintSpeedInc : 1));
}
camera.position.y = camera.position.y - ySpeed;
ySpeed = ySpeed + acc;
// Not falling through a block or above a block (above collision)
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
var b = chunks[i][j];
var c = intersect(b.x, b.y + 10, b.z, 5, 5, 5, player.x, player.y, player.z, player.w, player.h, player.d);
if(c && camera.position.y <= chunks[i][j].y + 2.5 + player.h && camera.position.y >= chunks[i][j].y){
camera.position.y = chunks[i][j].y + 2.5 + player.h;
ySpeed = 0;
canJump = true;
}
var c = intersect(b.x, b.y, b.z, 5, 5, 5, player.x, player.y, player.z, player.w, player.h, player.d); // this one doesn't have a + 10 in the b.y
if(c && camera.position.y >= chunks[i][j].y - 2.5 && camera.position.y <= chunks[i][j].y){
ySpeed = 0.5;
}
}
}
// INFINITE TERRAIN GENERATION PART!
var worldSize = chunkSize * renderDistance * 5;
var ratio = 0.4;
if(camera.position.z < lowestZBlock() + (worldSize * ratio)){ // 20 is 4 blocks
/*
[0], [3], [6],
[1], [x], [7],
[2], [5], [8],
*/
var newChunks = [];
for(var i = 0; i < chunks.length; i++){
if((i + 1) % renderDistance != 0){
newChunks.push(chunks[i]);
}
}
// add blocks
var lowestX = lowestXBlock();
var lowestZ = lowestZBlock();
for(var i = 0; i < renderDistance; i++){
var chunk = [];
for(var x = lowestX + (i * chunkSize * 5); x < lowestX + (i * chunkSize * 5) + (chunkSize * 5); x = x + 5){
for(var z = lowestZ - (chunkSize * 5); z < lowestZ; z = z + 5){
xoff = inc * x / 5;
zoff = inc * z / 5;
var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5) * 5;
for(var e = 0; e < depth; e++){
if(v - (e * 5) < minWorldY){
continue;
}
// Try to find a broken block in that position
var blockIsDestroyed = false;
for(var d = 0; d < brokenBlocks.length; d++){
if(brokenBlocks[d].x == x && brokenBlocks[d].y == v - (e * 5) && brokenBlocks[d].z == z){
blockIsDestroyed = true;
break;
}
}
if(!blockIsDestroyed){
var blockType = null;
if(e == 0){
blockType = blocks.grass.name;
} else if(e == 1 || e == 2 || e == 3){
blockType = blocks.dirt.name;
} else if(e > 3){
blockType = blocks.cobblestone.name;
}
chunk.push(new Block(x, v - (e * 5), z, false, blockType));
}
}
// Check if there is also placed blocks there
for(var b = 0; b < placedBlocks.length; b++){
if(placedBlocks[b].x == x && placedBlocks[b].z == z){
chunk.push(new Block(placedBlocks[b].x, placedBlocks[b].y, placedBlocks[b].z, true, placedBlocks[b].blockType));
}
}
}
}
newChunks.splice(i * renderDistance, 0, chunk);
}
chunks = newChunks;
scene.remove(instancedChunk);
instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, (renderDistance * renderDistance * chunkSize * chunkSize * depth) + placedBlocks.length);
var count = 0;
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
let matrix = new THREE.Matrix4().makeTranslation(
chunks[i][j].x,
chunks[i][j].y,
chunks[i][j].z
);
instancedChunk.setMatrixAt(count, matrix);
var color = null;
if(chunks[i][j].blockType == "grass"){
color = blocks.grass.color;
} else if(chunks[i][j].blockType == "dirt"){
color = blocks.dirt.color;
} else if(chunks[i][j].blockType == "cobblestone"){
color = blocks.cobblestone.color;
}
instancedChunk.setColorAt(count, color);
count++;
}
}
scene.add(instancedChunk);
}
if(camera.position.z > highestZBlock() - (worldSize * ratio)){ // 20 is 4 blocks
/*
[0], [3], [6],
[1], [x], [7],
[2], [5], [8],
*/
var newChunks = [];
for(var i = 0; i < chunks.length; i++){
if(i % renderDistance != 0){
newChunks.push(chunks[i]);
}
}
// add blocks
var lowestX = lowestXBlock();
var highestZ = highestZBlock();
for(var i = 0; i < renderDistance; i++){
var chunk = [];
for(var x = lowestX + (i * chunkSize * 5); x < lowestX + (i * chunkSize * 5) + (chunkSize * 5); x = x + 5){
for(var z = highestZ + 5; z < (highestZ + 5) + (chunkSize * 5); z = z + 5){
xoff = inc * x / 5;
zoff = inc * z / 5;
var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5) * 5;
for(var e = 0; e < depth; e++){
if(v - (e * 5) < minWorldY){
continue;
}
// Try to find a broken block in that position
var blockIsDestroyed = false;
for(var d = 0; d < brokenBlocks.length; d++){
if(brokenBlocks[d].x == x && brokenBlocks[d].y == v - (e * 5) && brokenBlocks[d].z == z){
blockIsDestroyed = true;
break;
}
}
if(!blockIsDestroyed){
var blockType = null;
if(e == 0){
blockType = blocks.grass.name;
} else if(e == 1 || e == 2 || e == 3){
blockType = blocks.dirt.name;
} else if(e > 3){
blockType = blocks.cobblestone.name;
}
chunk.push(new Block(x, v - (e * 5), z, false, blockType));
}
}
// Check if there is also placed blocks there
for(var b = 0; b < placedBlocks.length; b++){
if(placedBlocks[b].x == x && placedBlocks[b].z == z){
chunk.push(new Block(placedBlocks[b].x, placedBlocks[b].y, placedBlocks[b].z, true, placedBlocks[b].blockType));
}
}
}
}
newChunks.splice(((i + 1) * renderDistance) - 1, 0, chunk);
}
chunks = newChunks;
scene.remove(instancedChunk);
instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, (renderDistance * renderDistance * chunkSize * chunkSize * depth) + placedBlocks.length);
var count = 0;
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
let matrix = new THREE.Matrix4().makeTranslation(
chunks[i][j].x,
chunks[i][j].y,
chunks[i][j].z
);
instancedChunk.setMatrixAt(count, matrix);
var color = null;
if(chunks[i][j].blockType == "grass"){
color = blocks.grass.color;
} else if(chunks[i][j].blockType == "dirt"){
color = blocks.dirt.color;
} else if(chunks[i][j].blockType == "cobblestone"){
color = blocks.cobblestone.color;
}
instancedChunk.setColorAt(count, color);
count++;
}
}
scene.add(instancedChunk);
}
if(camera.position.x > highestXBlock() - (worldSize * ratio)){ // 20 is 4 blocks
/*
[0], [3], [6],
[1], [x], [7],
[2], [5], [8],
*/
var newChunks = [];
for(var i = renderDistance; i < chunks.length; i++){
newChunks.push(chunks[i]);
}
// add blocks
var highestX = highestXBlock();
var lowestZ = lowestZBlock();
for(var i = 0; i < renderDistance; i++){
var chunk = [];
for(var z = lowestZ + (i * chunkSize * 5); z < lowestZ + (i * chunkSize * 5) + (chunkSize * 5); z = z + 5){
for(var x = highestX + 5; x < highestX + 5 + (chunkSize * 5); x = x + 5){
xoff = inc * x / 5;
zoff = inc * z / 5;
var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5) * 5;
for(var e = 0; e < depth; e++){
if(v - (e * 5) < minWorldY){
continue;
}
// Try to find a broken block in that position
var blockIsDestroyed = false;
for(var d = 0; d < brokenBlocks.length; d++){
if(brokenBlocks[d].x == x && brokenBlocks[d].y == v - (e * 5) && brokenBlocks[d].z == z){
blockIsDestroyed = true;
break;
}
}
if(!blockIsDestroyed){
var blockType = null;
if(e == 0){
blockType = blocks.grass.name;
} else if(e == 1 || e == 2 || e == 3){
blockType = blocks.dirt.name;
} else if(e > 3){
blockType = blocks.cobblestone.name;
}
chunk.push(new Block(x, v - (e * 5), z, false, blockType));
}
}
// Check if there is also placed blocks there
for(var b = 0; b < placedBlocks.length; b++){
if(placedBlocks[b].x == x && placedBlocks[b].z == z){
chunk.push(new Block(placedBlocks[b].x, placedBlocks[b].y, placedBlocks[b].z, true, placedBlocks[b].blockType));
}
}
}
}
newChunks.splice(chunks.length - (renderDistance - i), 0, chunk);
}
chunks = newChunks;
scene.remove(instancedChunk);
instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, (renderDistance * renderDistance * chunkSize * chunkSize * depth) + placedBlocks.length);
var count = 0;
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
let matrix = new THREE.Matrix4().makeTranslation(
chunks[i][j].x,
chunks[i][j].y,
chunks[i][j].z
);
instancedChunk.setMatrixAt(count, matrix);
var color = null;
if(chunks[i][j].blockType == "grass"){
color = blocks.grass.color;
} else if(chunks[i][j].blockType == "dirt"){
color = blocks.dirt.color;
} else if(chunks[i][j].blockType == "cobblestone"){
color = blocks.cobblestone.color;
}
instancedChunk.setColorAt(count, color);
count++;
}
}
scene.add(instancedChunk);
}
if(camera.position.x < lowestXBlock() + (worldSize * ratio)){ // 20 is 4 blocks
/*
[0], [3], [6],
[1], [x], [7],
[2], [5], [8],
*/
var newChunks = [];
for(var i = 0; i < chunks.length - renderDistance; i++){
newChunks.push(chunks[i]);
}
// add blocks
var lowestX = lowestXBlock();
var lowestZ = lowestZBlock();
for(var i = 0; i < renderDistance; i++){
var chunk = [];
for(var z = lowestZ + (i * chunkSize * 5); z < lowestZ + (i * chunkSize * 5) + (chunkSize * 5); z = z + 5){
for(var x = lowestX - (chunkSize * 5); x < lowestX; x = x + 5){
xoff = inc * x / 5;
zoff = inc * z / 5;
var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5) * 5;
for(var e = 0; e < depth; e++){
if(v - (e * 5) < minWorldY){
continue;
}
// Try to find a broken block in that position
var blockIsDestroyed = false;
for(var d = 0; d < brokenBlocks.length; d++){
if(brokenBlocks[d].x == x && brokenBlocks[d].y == v - (e * 5) && brokenBlocks[d].z == z){
blockIsDestroyed = true;
break;
}
}
if(!blockIsDestroyed){
var blockType = null;
if(e == 0){
blockType = blocks.grass.name;
} else if(e == 1 || e == 2 || e == 3){
blockType = blocks.dirt.name;
} else if(e > 3){
blockType = blocks.cobblestone.name;
}
chunk.push(new Block(x, v - (e * 5), z, false, blockType));
}
}
// Check if there is also placed blocks there
for(var b = 0; b < placedBlocks.length; b++){
if(placedBlocks[b].x == x && placedBlocks[b].z == z){
chunk.push(new Block(placedBlocks[b].x, placedBlocks[b].y, placedBlocks[b].z, true, placedBlocks[b].blockType));
}
}
}
}
newChunks.splice(i, 0, chunk);
}
chunks = newChunks;
scene.remove(instancedChunk);
instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, (renderDistance * renderDistance * chunkSize * chunkSize * depth) + placedBlocks.length);
var count = 0;
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
let matrix = new THREE.Matrix4().makeTranslation(
chunks[i][j].x,
chunks[i][j].y,
chunks[i][j].z
);
instancedChunk.setMatrixAt(count, matrix);
var color = null;
if(chunks[i][j].blockType == "grass"){
color = blocks.grass.color;
} else if(chunks[i][j].blockType == "dirt"){
color = blocks.dirt.color;
} else if(chunks[i][j].blockType == "cobblestone"){
color = blocks.cobblestone.color;
}
instancedChunk.setColorAt(count, color);
count++;
}
}
scene.add(instancedChunk);
}
}
function lowestXBlock(){
var xPosArray = [];
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
xPosArray.push(chunks[i][j].x);
}
}
return Math.min.apply(null, xPosArray);
}
function highestXBlock(){
var xPosArray = [];
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
xPosArray.push(chunks[i][j].x);
}
}
return Math.max.apply(null, xPosArray);
}
function lowestZBlock(){
var zPosArray = [];
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
zPosArray.push(chunks[i][j].z);
}
}
return Math.min.apply(null, zPosArray);
}
function highestZBlock(){
var zPosArray = [];
for(var i = 0; i < chunks.length; i++){
for(var j = 0; j < chunks[i].length; j++){
zPosArray.push(chunks[i][j].z);
}
}
return Math.max.apply(null, zPosArray);
}
// Resize Window
window.addEventListener("resize", function(){
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
cursor.style.left = ((0.5 * window.innerWidth) - (0.5 * cursor.width)).toString() + "px";
cursor.style.top = ((0.5 * window.innerHeight) - (0.5 * cursor.height)).toString() + "px";
});
const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();
pointer.x = (0.5) * 2 - 1;
pointer.y = -1 * (0.5) * 2 + 1;
var plane;
function render(){
raycaster.setFromCamera(pointer, camera);
var intersection = raycaster.intersectObject(instancedChunk);
if(intersection[0] != undefined && intersection[0].distance < 40){
//console.log(intersection[0]);
if(!scene.children.includes(plane)){
var planeG = new THREE.PlaneGeometry(5, 5);
var planeM = new THREE.MeshBasicMaterial({color : 0xffffff, side : THREE.DoubleSide});
planeM.transparent = true;
planeM.opacity = 0.5;
plane = new THREE.Mesh(planeG, planeM);
scene.add(plane);
} else {
plane.visible = true;
var materialIndex = intersection[0].face.materialIndex;
var position = intersection[0].point; // object with x, y and z coords
var x = 0;
var y = 0;
var z = 0;
const inc = 0.1;
switch(materialIndex){
case 0: // right
plane.rotation.x = 0;
plane.rotation.y = (Math.PI / 2);
plane.rotation.z = 0;
x = position.x + inc;
y = Math.round(position.y / 5) * 5;
z = Math.round(position.z / 5) * 5;
break;
case 1: // left
plane.rotation.x = 0;
plane.rotation.y = (Math.PI / 2);
plane.rotation.z = 0;
x = position.x - inc;
y = Math.round(position.y / 5) * 5;
z = Math.round(position.z / 5) * 5;
break;
case 2: // top
plane.rotation.x = (Math.PI / 2);
plane.rotation.y = 0;
plane.rotation.z = 0;
x = Math.round(position.x / 5) * 5;
y = position.y + inc;
z = Math.round(position.z / 5) * 5;
break;
case 3: // bottom
plane.rotation.x = (Math.PI / 2);
plane.rotation.y = 0;
plane.rotation.z = 0;
x = Math.round(position.x / 5) * 5;
y = position.y - inc;
z = Math.round(position.z / 5) * 5;
break;
case 4: // front
plane.rotation.x = 0;
plane.rotation.y = 0;
plane.rotation.z = 0;
x = Math.round(position.x / 5) * 5;
y = Math.round(position.y / 5) * 5;
z = position.z + inc;
break;
case 5: // back
plane.rotation.x = 0;
plane.rotation.y = 0;
plane.rotation.z = 0;
x = Math.round(position.x / 5) * 5;
y = Math.round(position.y / 5) * 5;
z = position.z - inc;
break;
}
plane.position.x = x;
plane.position.y = y;
plane.position.z = z;
}
} else {
if(plane){
plane.visible = false;
}
}
renderer.render(scene, camera);
}
function GameLoop(){
requestAnimationFrame(GameLoop);
update();
render();
}
GameLoop();
</script>
</body>
</html>
And this is generation me this terrain:
And my question is:
If there is a function to change the color of an specific block of the chunk called setColorAt(), there is another function which could be used to change the material array of the block to another material array in a specific block of the chunk? And… how to implement that and get my game with the new textures? Thanks for helping anyway.
