269 lines
10 KiB
HTML
269 lines
10 KiB
HTML
<html>
|
|
<head>
|
|
</head>
|
|
<body onmousemove="//mouseMove(canv, event)" onmousedown="mousePressed(event)">
|
|
<script type="text/javascript">
|
|
var WALL_CHANCE = 0.5;
|
|
|
|
function random(min, max) {
|
|
return Math.random()*(max-min)+min;
|
|
}
|
|
|
|
function dist(x, y, a, b) {
|
|
return Math.sqrt(Math.pow(x-a,2) + Math.pow(y-b,2));
|
|
}
|
|
|
|
function constrain(x, y, z) {
|
|
return ( x < y ) ? y : (( x > z ) ? z : x);
|
|
}
|
|
|
|
class Tile {
|
|
constructor(i, j) {
|
|
this.i = i;
|
|
this.j = j;
|
|
this.neighbors = [];
|
|
this.previous = undefined;
|
|
this.wall = (Math.random() <= WALL_CHANCE) ? true : false;
|
|
this.f = 0;
|
|
this.g = 0;
|
|
this.h = 0;
|
|
}
|
|
|
|
addNeighbors(g) {
|
|
for (var c = -1; c < 2; c++) {
|
|
for (var d = -1; d < 2; d++) {
|
|
var a = constrain(c+this.i,0,g.tiles.length-1);
|
|
var b = constrain(d+this.j,0,g.tiles[this.i].length-1);
|
|
var e = g.tiles[a][b];
|
|
if (!(a == this.i && b == this.j) && !this.neighbors.includes(e)) {
|
|
this.neighbors.push(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class Grid {
|
|
constructor(width, height) {
|
|
this.tiles = [];
|
|
for (var i = 0; i < width; i++) {
|
|
var row = [];
|
|
for (var j = 0; j < height; j++) {
|
|
row.push(new Tile(i, j));
|
|
}
|
|
this.tiles.push(row);
|
|
}
|
|
}
|
|
|
|
setup() {
|
|
for (var i = 0; i < this.tiles.length; i++) {
|
|
for (var j = 0; j < this.tiles[i].length; j++) {
|
|
this.tiles[i][j].addNeighbors(this);
|
|
}
|
|
}
|
|
var is = 0, js = 0, ie = 0, je = 0;
|
|
while (true) {
|
|
is = Math.floor(random(0,this.tiles.length));
|
|
js = Math.floor(random(0,this.tiles[is].length));
|
|
while (true) {
|
|
var x = Math.floor(random(0,this.tiles.length));
|
|
var y = Math.floor(random(0,this.tiles[x].length));
|
|
if (x != is && y != js) {
|
|
ie = x;
|
|
je = y;
|
|
break;
|
|
}
|
|
}
|
|
if (this.tiles[is][js].wall == false && !this.tiles[ie][je].wall == false) {
|
|
break;
|
|
}
|
|
}
|
|
this.start = this.tiles[is][js];
|
|
this.end = this.tiles[ie][je];
|
|
this.start.wall = false;
|
|
this.end.wall = false;
|
|
this.openSet = [this.start];
|
|
this.closedSet = [];
|
|
this.path = [];
|
|
this.finished = false;
|
|
}
|
|
|
|
gameOfLifeCheck(px, py) {
|
|
var al = 0;
|
|
var col = (this.tiles[px][py].wall)?1:0;
|
|
|
|
for (var i = -1; i < 2; i++) {
|
|
for (var j = -1; j < 2; j++) {
|
|
var pos = {x:(px+i+cols)%cols, y:(py+j+rows)%rows};
|
|
al += (this.tiles[Math.floor(pos.x)][Math.floor(pos.y)].wall)?1:0;
|
|
}
|
|
}
|
|
al -= col;
|
|
if (col == 0 && al == 3) {
|
|
return 1;
|
|
} else if (col == 1 && (al < 2 || al > 3)) {
|
|
return 0;
|
|
} else {
|
|
return col;
|
|
}
|
|
}
|
|
|
|
gameOfLifeStep() {
|
|
var newGrid = new Grid(cols, rows);
|
|
for (var i = 0; i < cols; i++) {
|
|
for (var j = 0; j < rows; j++) {
|
|
newGrid.tiles[i][j].wall = (this.gameOfLifeCheck(i, j))?true:false;
|
|
}
|
|
}
|
|
this.tiles = newGrid.tiles;
|
|
this.setup();
|
|
}
|
|
|
|
findPathAStar() {
|
|
if (this.openSet.length > 0) {
|
|
var winner = 0;
|
|
for (var i = 0; i < this.openSet.length; i++) {
|
|
if (this.openSet[i].f < this.openSet[winner].f) {
|
|
winner = i;
|
|
}
|
|
}
|
|
var current = this.openSet[winner];
|
|
|
|
if (current === this.end) {
|
|
this.finished = true;
|
|
console.log("Found Path!");
|
|
}
|
|
|
|
this.closedSet.push(
|
|
this.openSet.splice(
|
|
this.openSet.indexOf(current),
|
|
1
|
|
)[0]
|
|
);
|
|
|
|
var neighbors = current.neighbors;
|
|
for (var i = 0; i < neighbors.length; i++) {
|
|
var neighbor = neighbors[i];
|
|
|
|
if (!this.closedSet.includes(neighbor) && !neighbor.wall) {
|
|
var tempG = current.g + dist(neighbor.i, neighbor.j, current.i, current.j);
|
|
|
|
var newPath = false;
|
|
if (this.openSet.includes(neighbor)) {
|
|
if (tempG < neighbor.g) {
|
|
neighbor.g = tempG;
|
|
newPath = true;
|
|
}
|
|
} else {
|
|
neighbor.g = tempG;
|
|
newPath = true;
|
|
this.openSet.push(neighbor);
|
|
}
|
|
|
|
if (newPath) {
|
|
neighbor.h = dist(neighbor.i, neighbor.j, this.end.i, this.end.j);
|
|
neighbor.f = neighbor.g + neighbor.h;
|
|
neighbor.previous = current;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
this.finished = true;
|
|
console.log("No Path found!");
|
|
}
|
|
|
|
this.path = [];
|
|
var temp = current;
|
|
this.path.push(temp);
|
|
while (temp.previous) {
|
|
this.path.push(temp.previous);
|
|
temp = temp.previous;
|
|
}
|
|
}
|
|
}
|
|
|
|
var interv, frames = 30, canv, ctx/*, mouse = {x:0, y:0}*/;
|
|
var scl = 20, cols, rows, dead, alive, grid;
|
|
|
|
function setup() {
|
|
canv = document.createElement("canvas");
|
|
|
|
canv.style.position="fixed";
|
|
canv.style.top="0px";
|
|
canv.style.left="0px";
|
|
canv.style.zIndex="-1";
|
|
canv.width=window.innerWidth;
|
|
canv.height=window.innerHeight;
|
|
ctx=canv.getContext("2d");
|
|
document.body.appendChild(canv);
|
|
|
|
cols = Math.round(canv.width/scl);
|
|
rows = Math.round(canv.height/scl);
|
|
dead = "rgb(0,0,0)";
|
|
alive = "rgb(255,255,255)";
|
|
grid = new Grid(cols, rows);
|
|
grid.setup();
|
|
}
|
|
|
|
function draw() {
|
|
if (!grid.finished) {
|
|
grid.findPathAStar();
|
|
}
|
|
for (var i = 0; i < cols; i++) {
|
|
for (var j = 0; j < rows; j++) {
|
|
var c = grid.tiles[i][j];
|
|
ctx.strokeStyle = "black";
|
|
ctx.fillStyle = (grid.tiles[i][j].wall) ? alive : dead;
|
|
if (!grid.finished) {
|
|
if (grid.openSet.includes(c)) {
|
|
ctx.fillStyle = "blue";
|
|
}
|
|
if (grid.closedSet.includes(c)) {
|
|
ctx.fillStyle = "rgb(170, 0, 170)";
|
|
}
|
|
}
|
|
if (grid.path.includes(c)) {
|
|
ctx.fillStyle = "green";
|
|
}
|
|
if (c == grid.start) {
|
|
var g = 255*(7/8);
|
|
ctx.fillStyle = "rgb("+g+", "+g+", 0)";
|
|
}
|
|
if (c == grid.end) {
|
|
ctx.fillStyle = "red";
|
|
}
|
|
if (c.wall) {
|
|
ctx.fillStyle = "white";
|
|
}
|
|
ctx.fillRect(i*scl+1, j*scl+1, scl-2, scl-2);
|
|
ctx.beginPath();
|
|
ctx.rect(i*scl, j*scl, scl, scl);
|
|
ctx.stroke();
|
|
ctx.fill();
|
|
ctx.closePath();
|
|
}
|
|
}
|
|
}
|
|
|
|
function mousePressed(evt) {
|
|
// if (evt.button == 1) {
|
|
grid.gameOfLifeStep();
|
|
/* } else if (evt.button == 0) {
|
|
var x = Math.floor(mouse.x/scl), y = Math.floor(mouse.y/scl);
|
|
grid.tiles[x][y].wall = !grid.tiles[x][y].wall;
|
|
}*/
|
|
}
|
|
|
|
/* function mouseMove(canvas, evt) {
|
|
var rect = canvas.getBoundingClientRect();
|
|
mouse = {
|
|
x: evt.clientX - rect.left,
|
|
y: evt.clientY - rect.top
|
|
};
|
|
}*/
|
|
|
|
setup();
|
|
interv = setInterval(draw, 1000/frames);
|
|
</script>
|
|
</body>
|
|
</html> |