Merge pull request #81 from MaxRobinsonTheGreat/random-walls
Random walls
This commit is contained in:
1
dist/css/style.css
vendored
1
dist/css/style.css
vendored
@@ -75,6 +75,7 @@ button {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
min-width: 30px;
|
min-width: 30px;
|
||||||
|
margin: 2px;
|
||||||
}
|
}
|
||||||
button:hover{
|
button:hover{
|
||||||
background-color: #81d2c7;
|
background-color: #81d2c7;
|
||||||
|
|||||||
2
dist/index.html
vendored
2
dist/index.html
vendored
@@ -35,6 +35,8 @@
|
|||||||
<button id='reset-env' title='Restarts simulation with default organism.'>Reset</button>
|
<button id='reset-env' title='Restarts simulation with default organism.'>Reset</button>
|
||||||
<button id='clear-env' title="Removes all organisms and walls. Will disable 'reset on extinction'"">Clear</button>
|
<button id='clear-env' title="Removes all organisms and walls. Will disable 'reset on extinction'"">Clear</button>
|
||||||
<br>
|
<br>
|
||||||
|
<button id='random-walls' title="Generates random walls.">Random Walls</button>
|
||||||
|
<br>
|
||||||
<label for="auto-reset">Reset on total extinction</label>
|
<label for="auto-reset">Reset on total extinction</label>
|
||||||
<input type="checkbox" id="auto-reset" checked>
|
<input type="checkbox" id="auto-reset" checked>
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
@@ -327,6 +327,9 @@ class ControlPanel {
|
|||||||
env.auto_reset = false;
|
env.auto_reset = false;
|
||||||
$('#auto-reset').prop('checked', false);;
|
$('#auto-reset').prop('checked', false);;
|
||||||
});
|
});
|
||||||
|
$('#random-walls').click( function() {
|
||||||
|
this.env_controller.randomizeWalls();
|
||||||
|
}.bind(this));
|
||||||
$('#auto-reset').change(function() {
|
$('#auto-reset').change(function() {
|
||||||
env.auto_reset = this.checked;
|
env.auto_reset = this.checked;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const CellStates = require("../Organism/Cell/CellStates");
|
|||||||
const Neighbors = require("../Grid/Neighbors");
|
const Neighbors = require("../Grid/Neighbors");
|
||||||
const FossilRecord = require("../Stats/FossilRecord");
|
const FossilRecord = require("../Stats/FossilRecord");
|
||||||
const Hyperparams = require("../Hyperparameters");
|
const Hyperparams = require("../Hyperparameters");
|
||||||
|
const Perlin = require("../Utils/Perlin");
|
||||||
|
|
||||||
class EnvironmentController extends CanvasController{
|
class EnvironmentController extends CanvasController{
|
||||||
constructor(env, canvas) {
|
constructor(env, canvas) {
|
||||||
@@ -51,8 +52,34 @@ class EnvironmentController extends CanvasController{
|
|||||||
this.scale = 1;
|
this.scale = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Iterate over grid from 0,0 to env.num_cols,env.num_rows and create random walls using perlin noise to create a more organic shape.
|
||||||
|
*/
|
||||||
|
randomizeWalls(thickness=1) {
|
||||||
|
this.env.clearWalls();
|
||||||
|
const noise_threshold = -0.017;
|
||||||
|
let avg_noise = 0;
|
||||||
|
let resolution = 20;
|
||||||
|
Perlin.seed();
|
||||||
|
|
||||||
|
for (let r = 0; r < this.env.num_rows; r++) {
|
||||||
|
for (let c = 0; c < this.env.num_cols; c++) {
|
||||||
|
let xval = c/this.env.num_cols*(resolution/this.env.renderer.cell_size*(this.env.num_cols/this.env.num_rows));
|
||||||
|
let yval = r/this.env.num_rows*(resolution/this.env.renderer.cell_size*(this.env.num_rows/this.env.num_cols));
|
||||||
|
let noise = Perlin.get(xval, yval);
|
||||||
|
avg_noise += noise/(this.env.num_rows*this.env.num_cols);
|
||||||
|
if (noise > noise_threshold && noise < noise_threshold + thickness/resolution) {
|
||||||
|
let cell = this.env.grid_map.cellAt(c, r);
|
||||||
|
if (cell != null) {
|
||||||
|
if(cell.owner != null) cell.owner.die();
|
||||||
|
this.env.changeCell(c, r, CellStates.wall, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateMouseLocation(offsetX, offsetY){
|
updateMouseLocation(offsetX, offsetY){
|
||||||
|
|
||||||
super.updateMouseLocation(offsetX, offsetY);
|
super.updateMouseLocation(offsetX, offsetY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ class WorldEnvironment extends Environment{
|
|||||||
super();
|
super();
|
||||||
this.renderer = new Renderer('env-canvas', 'env', cell_size);
|
this.renderer = new Renderer('env-canvas', 'env', cell_size);
|
||||||
this.controller = new EnvironmentController(this, this.renderer.canvas);
|
this.controller = new EnvironmentController(this, this.renderer.canvas);
|
||||||
var grid_rows = Math.ceil(this.renderer.height / cell_size);
|
this.num_rows = Math.ceil(this.renderer.height / cell_size);
|
||||||
var grid_cols = Math.ceil(this.renderer.width / cell_size);
|
this.num_cols = Math.ceil(this.renderer.width / cell_size);
|
||||||
this.grid_map = new GridMap(grid_cols, grid_rows, cell_size);
|
this.grid_map = new GridMap(this.num_cols, this.num_rows, cell_size);
|
||||||
this.organisms = [];
|
this.organisms = [];
|
||||||
this.walls = [];
|
this.walls = [];
|
||||||
this.total_mutability = 0;
|
this.total_mutability = 0;
|
||||||
@@ -104,7 +104,8 @@ class WorldEnvironment extends Environment{
|
|||||||
|
|
||||||
clearWalls() {
|
clearWalls() {
|
||||||
for(var wall of this.walls){
|
for(var wall of this.walls){
|
||||||
if (this.grid_map.cellAt(wall.col, wall.row).state == CellStates.wall)
|
let wcell = this.grid_map.cellAt(wall.col, wall.row);
|
||||||
|
if (wcell && wcell.state == CellStates.wall)
|
||||||
this.changeCell(wall.col, wall.row, CellStates.empty, null);
|
this.changeCell(wall.col, wall.row, CellStates.empty, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,9 +155,9 @@ class WorldEnvironment extends Environment{
|
|||||||
resizeFillWindow(cell_size) {
|
resizeFillWindow(cell_size) {
|
||||||
this.renderer.cell_size = cell_size;
|
this.renderer.cell_size = cell_size;
|
||||||
this.renderer.fillWindow('env');
|
this.renderer.fillWindow('env');
|
||||||
var cols = Math.ceil(this.renderer.width / cell_size);
|
this.num_cols = Math.ceil(this.renderer.width / cell_size);
|
||||||
var rows = Math.ceil(this.renderer.height / cell_size);
|
this.num_rows = Math.ceil(this.renderer.height / cell_size);
|
||||||
this.grid_map.resize(cols, rows, cell_size);
|
this.grid_map.resize(this.num_cols, this.num_rows, cell_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
46
src/Utils/Perlin.js
Normal file
46
src/Utils/Perlin.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
let perlin = {
|
||||||
|
rand_vect: function(){
|
||||||
|
let theta = Math.random() * 2 * Math.PI;
|
||||||
|
return {x: Math.cos(theta), y: Math.sin(theta)};
|
||||||
|
},
|
||||||
|
dot_prod_grid: function(x, y, vx, vy){
|
||||||
|
let g_vect;
|
||||||
|
let d_vect = {x: x - vx, y: y - vy};
|
||||||
|
if (this.gradients[[vx,vy]]){
|
||||||
|
g_vect = this.gradients[[vx,vy]];
|
||||||
|
} else {
|
||||||
|
g_vect = this.rand_vect();
|
||||||
|
this.gradients[[vx, vy]] = g_vect;
|
||||||
|
}
|
||||||
|
return d_vect.x * g_vect.x + d_vect.y * g_vect.y;
|
||||||
|
},
|
||||||
|
smootherstep: function(x){
|
||||||
|
return 6*x**5 - 15*x**4 + 10*x**3;
|
||||||
|
},
|
||||||
|
interp: function(x, a, b){
|
||||||
|
return a + this.smootherstep(x) * (b-a);
|
||||||
|
},
|
||||||
|
seed: function(){
|
||||||
|
this.gradients = {};
|
||||||
|
this.memory = {};
|
||||||
|
},
|
||||||
|
get: function(x, y) {
|
||||||
|
if (this.memory.hasOwnProperty([x,y]))
|
||||||
|
return this.memory[[x,y]];
|
||||||
|
let xf = Math.floor(x);
|
||||||
|
let yf = Math.floor(y);
|
||||||
|
//interpolate
|
||||||
|
let tl = this.dot_prod_grid(x, y, xf, yf);
|
||||||
|
let tr = this.dot_prod_grid(x, y, xf+1, yf);
|
||||||
|
let bl = this.dot_prod_grid(x, y, xf, yf+1);
|
||||||
|
let br = this.dot_prod_grid(x, y, xf+1, yf+1);
|
||||||
|
let xt = this.interp(x-xf, tl, tr);
|
||||||
|
let xb = this.interp(x-xf, bl, br);
|
||||||
|
let v = this.interp(y-yf, xt, xb);
|
||||||
|
this.memory[[x,y]] = v;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
perlin.seed();
|
||||||
|
|
||||||
|
module.exports = perlin;
|
||||||
Reference in New Issue
Block a user