Added control panel

This commit is contained in:
MaxRobinsonTheGreat
2020-07-08 19:32:05 -06:00
parent 2ba56abb1d
commit c6b0a5bafc
9 changed files with 176 additions and 37 deletions

21
dist/bundle.js vendored

File diff suppressed because one or more lines are too long

35
dist/css/style.css vendored
View File

@@ -6,9 +6,44 @@ body{
canvas { canvas {
display: block; display: block;
} }
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
}
.env {
height: 80vh;
position: static;
}
.control-panel {
height: 20vh;
width: 100vw;
background-color: gray;
position: fixed;
display: grid;
}
.control-set {
margin: 5px;
padding: 5px;
border: 10px;
border-color: black;
grid-row: 1;
height: 100%;
}
#speed-controller {
grid-column: 1;
}
#hyperparameters {
grid-column: 2;
}
#powers {
grid-column: 3;
} }

22
dist/html/index.html vendored
View File

@@ -4,9 +4,29 @@
<meta charste="UTF-8"> <meta charste="UTF-8">
<title>Evolution Simulator</title> <title>Evolution Simulator</title>
<link rel="stylesheet" href="../css/style.css"> <link rel="stylesheet" href="../css/style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head> </head>
<body> <body>
<canvas id='canvas'></canvas>
<script src="../bundle.js"></script> <script src="../bundle.js"></script>
<div class='env'>
<canvas id='canvas'></canvas>
</div>
<div class='control-panel'>
<div id='speed-controller' class='control-set'>
<h2>Simulation Speed</h2>
<input id="slider" type="range" min="1" max="300" value="60">
<button id='pause-button'>Pause</button>
</div>
<div id='hyperparameters' class='control-set'>
<h2>Hyperparameters</h2>
</div>
<div id='powers' class='control-set'>
<h2>Powers</h2>
</div>
</div>
</body> </body>
</html> </html>

View File

@@ -64,7 +64,7 @@ function growFood(self, env){
if (r==0 && c==0) if (r==0 && c==0)
continue; continue;
var cell = env.grid_map.cellAt(self.col+c, self.row+r); var cell = env.grid_map.cellAt(self.col+c, self.row+r);
if (cell != null && cell.type == CellTypes.empty && Math.random() * 100 <= 0.5){ if (cell != null && cell.type == CellTypes.empty && Math.random() * 100 <= 1){
env.changeCell(self.col+c, self.row+r, CellTypes.food, null); env.changeCell(self.col+c, self.row+r, CellTypes.food, null);
return; return;
} }
@@ -73,21 +73,38 @@ function growFood(self, env){
} }
function killNeighbors(self, env) { function killNeighbors(self, env) {
killNeighbor(env.grid_map.cellAt(self.col+1, self.row)); killNeighbor(self, env.grid_map.cellAt(self.col+1, self.row));
killNeighbor(env.grid_map.cellAt(self.col-1, self.row)); killNeighbor(self, env.grid_map.cellAt(self.col-1, self.row));
killNeighbor(env.grid_map.cellAt(self.col, self.row+1)); killNeighbor(self, env.grid_map.cellAt(self.col, self.row+1));
killNeighbor(env.grid_map.cellAt(self.col, self.row-1)); killNeighbor(self, env.grid_map.cellAt(self.col, self.row-1));
} }
function killNeighbor(n_cell) { function killNeighbor(self, n_cell) {
if(n_cell == null) { if(n_cell == null) {
// console.log("null cell")
return;
}
if(n_cell.owner == null) {
// console.log("is no one's cell")
return;
}
if(n_cell.owner == self.owner) {
// console.log("is my cell")
return;
}
if (!n_cell.owner.living) {
// console.log("cell is dead")
return;
}
if (n_cell.type == CellTypes.armor) {
// console.log("armor block")
// self.owner.die();
return return
} }
if (n_cell.type != CellTypes.armor && n_cell.owner != null && n_cell.owner != self.owner && n_cell.owner.living){ var should_die = n_cell.type == CellTypes.killer; // has to be calculated before death
n_cell.owner.die(); n_cell.owner.die();
if (n_cell == CellTypes.killer){ if (should_die){
self.owner.die(); self.owner.die();
}
} }
} }

39
src/ControlPanel.js Normal file
View File

@@ -0,0 +1,39 @@
class ControlPanel {
constructor(engine) {
this.engine = engine;
this.defineEngineSpeedControls();
this.fps = engine.fps;
}
defineEngineSpeedControls(){
this.slider = document.getElementById("slider");
this.slider.oninput = function() {
this.fps = this.slider.value
if (this.engine.running) {
this.changeEngineSpeed(this.fps);
}
}.bind(this);
$('#pause-button').click(function() {
if ($('#pause-button').text() == "Pause" && this.engine.running) {
$('#pause-button').text("Play")
this.engine.stop();
}
else if (!this.engine.running){
$('#pause-button').text("Pause")
this.engine.start(this.fps);
}
console.log()
}.bind(this));
}
changeEngineSpeed(change_val) {
this.engine.stop();
this.engine.start(change_val)
this.fps = this.engine.fps;
}
}
module.exports = ControlPanel;

View File

@@ -1,19 +1,26 @@
const Environment = require('./Environment'); const Environment = require('./Environment');
const ControlPanel = require('./ControlPanel');
class Engine{ class Engine{
constructor(){ constructor(){
this.fps = 0; this.fps = 0;
this.environment = new Environment(5); this.environment = new Environment(5);
this.controlpanel = new ControlPanel(this);
this.environment.OriginOfLife(); this.environment.OriginOfLife();
this.last_update = Date.now(); this.last_update = Date.now();
this.delta_time = 0; this.delta_time = 0;
this.actual_fps = 0;
this.running = false; this.running = false;
} }
start(fps=60) { start(fps=60) {
if (fps <= 0)
fps = 1;
if (fps > 500)
fps = 500;
this.fps = fps; this.fps = fps;
this.game_loop = setInterval(function(){this.update();}.bind(this), 1000/fps); this.game_loop = setInterval(function(){this.update();}.bind(this), 1000/fps);
this.runnning = true; this.running = true;
} }
stop() { stop() {
@@ -27,6 +34,7 @@ class Engine{
this.last_update = Date.now(); this.last_update = Date.now();
this.environment.update(this.delta_time); this.environment.update(this.delta_time);
this.environment.render(); this.environment.render();
this.actual_fps = 1/this.delta_time*1000;
} }
} }

View File

@@ -39,7 +39,7 @@ class Organism {
for (var i=0; i<this.cells.length; i++) { for (var i=0; i<this.cells.length; i++) {
var cell = this.cells[i]; var cell = this.cells[i];
if (cell.loc_col == c && cell.loc_row == r){ if (cell.loc_col == c && cell.loc_row == r){
if (cell.type == this.producer || cell.type == this.mover) { if (cell.type == CellTypes.producer || cell.type == CellTypes.mover) {
check_change = true; check_change = true;
} }
this.cells.splice(i, 1); this.cells.splice(i, 1);
@@ -77,7 +77,7 @@ class Organism {
} }
lifespan() { lifespan() {
return this.cells.length * 150; return this.cells.length * 100;
} }
reproduce() { reproduce() {
@@ -87,7 +87,9 @@ class Organism {
if (Math.random() * 100 <= this.mutability) { if (Math.random() * 100 <= this.mutability) {
org.mutate(); org.mutate();
} }
else if (Math.random() * 100 <= 2) { if (Math.random() <= 0.5)
org.mutability++;
else{
org.mutability--; org.mutability--;
if (org.mutability < 1) if (org.mutability < 1)
org.mutability = 1; org.mutability = 1;
@@ -96,7 +98,7 @@ class Organism {
var direction = this.getRandomDirection(); var direction = this.getRandomDirection();
var direction_c = direction[0]; var direction_c = direction[0];
var direction_r = direction[1]; var direction_r = direction[1];
var offset = (Math.floor(Math.random() * 2)); var offset = (Math.floor(Math.random() * 2)) * 2;
var new_c = this.c + (direction_c*this.cells.length*2) + (direction_c*offset); var new_c = this.c + (direction_c*this.cells.length*2) + (direction_c*offset);
var new_r = this.r + (direction_r*this.cells.length*2) + (direction_r*offset); var new_r = this.r + (direction_r*this.cells.length*2) + (direction_r*offset);
@@ -113,14 +115,17 @@ class Organism {
} }
mutate() { mutate() {
this.mutability += 2;
var choice = Math.floor(Math.random() * 3); var choice = Math.floor(Math.random() * 3);
if (choice == 0) { if (choice == 0) {
// add cell
var type = CellTypes.getRandomLivingType(); var type = CellTypes.getRandomLivingType();
var branch = this.cells[Math.floor(Math.random() * this.cells.length)]; var num_to_add = Math.floor(Math.random() * 3) + 1;
var c = branch.loc_col+Math.floor(Math.random() * 2) - 1; for (var i=0; i<num_to_add; i++){
var r = branch.loc_row+Math.floor(Math.random() * 2) - 1; var branch = this.cells[Math.floor(Math.random() * this.cells.length)];
return this.addCell(type, c, r); var c = branch.loc_col+Math.floor(Math.random() * 2) - 1;
var r = branch.loc_row+Math.floor(Math.random() * 2) - 1;
return this.addCell(type, c, r);
}
} }
else if (choice == 1){ else if (choice == 1){
// change cell // change cell
@@ -157,7 +162,9 @@ class Organism {
this.c = new_c; this.c = new_c;
this.r = new_r; this.r = new_r;
this.updateGrid(); this.updateGrid();
return true;
} }
return false;
} }
getRandomDirection(){ getRandomDirection(){
@@ -236,6 +243,9 @@ class Organism {
this.die(); this.die();
return this.living; return this.living;
} }
if (this.food_collected >= this.foodNeeded()) {
this.reproduce();
}
for (var cell of this.cells) { for (var cell of this.cells) {
this.getRealCell(cell).performFunction(this.env); this.getRealCell(cell).performFunction(this.env);
} }
@@ -244,14 +254,11 @@ class Organism {
} }
if (this.is_mover) { if (this.is_mover) {
this.move_count++; this.move_count++;
if (this.move_count > this.move_range){ var success = this.attemptMove(this.direction);
if (this.move_count > this.move_range || !success){
this.move_count = 0; this.move_count = 0;
this.direction = this.getRandomDirection() this.direction = this.getRandomDirection()
} }
this.attemptMove(this.direction);
}
if (this.food_collected >= this.foodNeeded()) {
this.reproduce();
} }
return this.living; return this.living;

View File

@@ -5,9 +5,9 @@ class Renderer {
this.cell_size = cell_size; this.cell_size = cell_size;
this.env = env; this.env = env;
this.canvas = document.getElementById(canvas_id); this.canvas = document.getElementById(canvas_id);
this.ctx = canvas.getContext("2d"); this.ctx = this.canvas.getContext("2d");
this.canvas.width = window.innerWidth; this.canvas.width = $('.env').width();
this.canvas.height = window.innerHeight; this.canvas.height = $('.env').height();
this.height = canvas.height; this.height = canvas.height;
this.width = canvas.width; this.width = canvas.width;
this.cells_to_render = new Set(); this.cells_to_render = new Set();

View File

@@ -2,5 +2,7 @@
import Engine from './Engine'; import Engine from './Engine';
var engine = new Engine(); $('document').ready(function(){
engine.start(45); var engine = new Engine();
engine.start(60);
});