Implementation of the Perlin Noise Algorithm
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

356 lines
7.9 KiB

var water = "#1E90FF";
var beach = "#ffff00";
var grass = "#008000";
var maxValue = 30;
var minValue = -30;
var tilesColor = [water,beach,grass]
var board_numbers = [];
var cycle = 50;
var tile_width=32;
var tile_height=32;
var width = Math.floor(640 / tile_width);
var height = Math.floor(640 / tile_height);
var current_noise = [];
var currentBoardArray = [];
var clickCounter = 0;
var startx = 0;
var starty = 0;
var endx = 0;
var endy = 0;
function findHeighestNumber(array){
var heighest = Number.MIN_VALUE;
for(var i = 0; i < array.length; i++){
var row = array[i];
for(var j = 0; j < row.length; j++){
if(row[j] > heighest){
heighest = row[j];
}
}
}
return heighest;
}
function findSmallestNumber(array){
var smallest = Number.MAX_VALUE;
for(var i = 0; i < array.length; i++){
var row = array[i];
for(var j = 0; j < row.length; j++){
if(row[j] < smallest){
smallest = row[j];
}
}
}
return smallest;
}
/*
* The representation of a tile
*
* color value between 0,1,2
*/
class Tile {
constructor(x,y,color){
this.x = x;
this.y = y;
this.color = color;
if(color === 0){
this.accessible = true;
} else {
this.accessible = false;
}
}
}
class Ship{
constructor(x,y,speed){
this.x = x;
this.y = y;
this.speed = speed;
this.dx = 1*speed;
this.dy = 1*speed;
}
draw(context){
var img = new Image();
img.src = "ship.png";
img.height = "16";
img.width = "16";
context.drawImage(img,this.x,this.y);
}
update(){
this.x += dx;
this.y += dy;
this.draw(context);
}
}
function createBoard(height, width, array){
var board = document.getElementById("can");
var context = board.getContext("2d");
////console.log(array);
for(var i = 0; i < height; i++){
for(var j = 0; j < width; j++){
var color = array[i][j].color;
context.fillStyle = tilesColor[color];
context.fillRect(i*tile_height, j*tile_width, tile_width, tile_height);
}
}
}
/**
* This function interpolates values in a Array
*/
function interpolate(startValue, endValue,y){
var m = (endValue - startValue)/(y);
var result = [];
result.push(startValue);
for(var i = 1; i < y; i++){
result[i] = m * i + startValue;
}
result.push(endValue);
return result;
}
function generate_perlin_noise(rounds,height,width){
var result = [];
var points_width = width;
var points_height = height;
for(var r = 0; r < rounds; r++){
var tmp_array = [];
////console.log("------------------ Step "+r+" --------------");
// Interpolation für Reihen. Imprinzip ist das ganzschön ineffizient, da manche Reihen wieder überschrieben werden aber kein bock das zu ändern.
for(var i = 0; i < height; i++){
var row = [];
var startValue = Math.random() * (maxValue - minValue) + minValue; //Stupid, but i always forgot, how to set the boundries
var counter = 0;
for(var j = 0; j < width; j++){
////console.log(counter);
////console.log("Step "+i+"+"+j+":");
////console.log("counter: "+counter);
if (j % (points_width - 1) === 0 && !(j === 0) || j === (width - 1)){
////console.log(counter);
let endValue = Math.random() * (maxValue - minValue) + minValue; //Stupid, but i always forgot, how to set the boundries
interpolate(startValue, endValue, counter);
row = row.concat(interpolate(startValue, endValue, counter));
startValue = endValue;
counter = 0;
} else {
counter++;
}
}
////console.log(row);
tmp_array.push(row);
}
// Spalten interpolation
for(var i = 0; i < width; i++){
var startValue = tmp_array[0][i];
var counter = 0;
for(var j = 0; j < height; j++){
if(j % (height-1) === 0 && !(j === 0) || j === (height - 1)){
var endValue = tmp_array[j][i];
var tmp_interpolate = interpolate(startValue, endValue, counter);
startValue = endValue;
for(var k = 0; k < counter; k++){
tmp_array[j-counter][i] = tmp_interpolate[k];
}
counter = 0;
} else {
counter++;
}
}
}
result.push(tmp_array)
points_width = Math.floor(points_width / 2)+1;
points_height = Math.floor(points_height / 2)+1;
}
//console.log(result);
//return result;
var combi = [];
for (var i = 0; i < height; i++){
var rows = [];
for (var j = 0; j < width; j++){
rows[j] = 0;
}
combi.push(rows);
}
//console.log("------------- Ergebnisse ----------- Ergebnisse -------------");
//console.log(combi);
// adding all array to one array
for(var r = 0; r < rounds; r++){
var tmp = result.pop();
for (var i = 0; i < height; i++){
for (var j = 0; j < width; j++){
combi[i][j] = combi[i][j] + tmp[i][j];
}
}
}
var smallest = findSmallestNumber(combi);
for (var i = 0; i < height; i++){
for (var j = 0; j < width; j++){
combi[i][j] = combi[i][j] - smallest;
}
}
//Adding smallest Element to Noise_Array
// ???? Anomalie ????
//console.log(result);
//console.log(combi);
return combi;
}
/**
* This function starts the perlin noise generation process
* */
function run_perlin_noise(){
var noise_array = generate_perlin_noise(cycle,width,height);
//console.log(noise_array);
current_noise = noise_array;
currentBoardArray = createBoardArray(current_noise, height, width);
createBoard(height,width,currentBoardArray);
//currentBoardArray = createBoardArray(current_noise, height, width);
//dijkstra(currentBoardArray,startx,15,15,30,30);
}
function createBoardArray(array,height,width){
var result = [];
var heighestNumber = findHeighestNumber(array);
for(var i = 0; i < height; i++){
var row = [];
for(var j = 0; j < width; j++){
var x = (array[i][j]/ heighestNumber)*100;
var color = 0;
if(x <= 100.00 && x >= 70.00){
color = 1;
}
if(x <= 69.00 && x >= 65.00){
color = 1;
}
if(x <= 65.00 && x >= 0){
color = 0;
}
var tmp_tile = new Tile(j, i, color);
row.push(tmp_tile);
}
result.push(row);
}
return result;
}
function moveShip(canvas, e){
var rect = canvas.getBoundingClientRect();
var x = Math.floor(e.clientX - rect.left);
var y = Math.floor(e.clientY - rect.top);
var ship = new Ship(x,y,5);
ship.draw(canvas.getContext("2d"));
console.log("x: "+x+" y: "+y);
}
function paintPath(path){
console.log("hier passiert was");
//var board = document.getElementById("can");
//context = board.getContext("2d");
var can2 = document.getElementById("can2");
var context = can2.getContext("2d");
var can3 = document.getElementById("can3");
var context3 = can2.getContext("2d");
//context.beginPath();
for(var i = 0; i < path.length; i++){
var split = path[i].split("$");
// console.log(split);
var row = Number(split[0]);
var col = Number(split[1]);
context.fillStyle = "#82b74b";
context.fillRect(row*tile_height, col*tile_width, tile_width, tile_height);
//var ship = new Ship(row,col,5);
//context3.clearRect(0, 0, 640, 640);
//ship.draw(can3.getContext("2d"));
//context.fillStyle = "red";
//context.fillRect(0, 0, 1000, 1000);
//context.clearRect(0, 0, board.width, board.height);
//context.clearRect(row*tile_height, col*tile_width, tile_width, tile_height);
//context.beginPath();
//context.clearRect(0, 0, 1000, 1000);
//console.log("ende");
}
}
window.onload = (function(){
var can = document.getElementById("can");
var can2 = document.getElementById("can2");
var can3 = document.getElementById("can3");
rect = can3.getBoundingClientRect();
can3.addEventListener('click', function(e){
var x = Math.floor((e.clientX - rect.left)/tile_width);
var y = Math.floor((e.clientY - rect.top )/tile_height);
if(clickCounter === 2){
clickcounter = 1;
endx = x;
endy = y;
console.log(startx+" "+starty+" : "+endx+" "+endy);
currentBoardArray = createBoardArray(current_noise, height, width);
var path = dijkstra(currentBoardArray, startx, starty,endx,endy);
paintPath(path);
//moveShip(can, e);
} else {
clickCounter++;
startx = x;
starty = y;
}
createBoard(height,width,currentBoardArray);
moveShip(can, e);
});
run_perlin_noise();
});