control tabs, organism editor, code refactor
This commit is contained in:
85
src/Controllers/CanvasController.js
Normal file
85
src/Controllers/CanvasController.js
Normal file
@@ -0,0 +1,85 @@
|
||||
|
||||
|
||||
class CanvasController{
|
||||
constructor(env, canvas) {
|
||||
this.env = env;
|
||||
this.canvas = canvas;
|
||||
this.mouse_x;
|
||||
this.mouse_y;
|
||||
this.mouse_c;
|
||||
this.mouse_r;
|
||||
this.left_click = false;
|
||||
this.right_click = false;
|
||||
this.cur_cell = null;
|
||||
this.cur_org = null;
|
||||
this.highlight_org = true;
|
||||
this.defineEvents();
|
||||
}
|
||||
|
||||
setControlPanel(panel){
|
||||
this.control_panel = panel;
|
||||
}
|
||||
|
||||
defineEvents() {
|
||||
this.canvas.addEventListener('mousemove', e => {
|
||||
var prev_cell = this.cur_cell;
|
||||
var prev_org = this.cur_org;
|
||||
|
||||
this.mouse_x = e.offsetX;
|
||||
this.mouse_y = e.offsetY;
|
||||
var colRow = this.env.grid_map.xyToColRow(this.mouse_x, this.mouse_y);
|
||||
this.mouse_c = colRow[0];
|
||||
this.mouse_r = colRow[1];
|
||||
this.cur_cell = this.env.grid_map.cellAt(this.mouse_c, this.mouse_r);
|
||||
this.cur_org = this.cur_cell.owner;
|
||||
|
||||
if (this.cur_org != prev_org || this.cur_cell != prev_cell) {
|
||||
this.env.renderer.clearAllHighlights(true);
|
||||
if (this.cur_org != null && this.highlight_org) {
|
||||
this.env.renderer.highlightOrganism(this.cur_org);
|
||||
}
|
||||
else if (this.cur_cell != null) {
|
||||
this.env.renderer.highlightCell(this.cur_cell, true);
|
||||
}
|
||||
}
|
||||
this.mouseMove();
|
||||
});
|
||||
|
||||
this.canvas.addEventListener('mouseup', function(evt) {
|
||||
evt.preventDefault();
|
||||
this.left_click=false;
|
||||
this.right_click=false;
|
||||
}.bind(this));
|
||||
|
||||
this.canvas.addEventListener('mousedown', function(evt) {
|
||||
evt.preventDefault();
|
||||
if (evt.button == 0) {
|
||||
this.left_click = true;
|
||||
}
|
||||
if (evt.button == 2)
|
||||
this.right_click = true;
|
||||
this.mouseDown();
|
||||
}.bind(this));
|
||||
|
||||
this.canvas.addEventListener('contextmenu', function(evt) {
|
||||
evt.preventDefault();
|
||||
});
|
||||
|
||||
this.canvas.addEventListener('mouseleave', function(){
|
||||
this.right_click = false;
|
||||
this.left_click = false;
|
||||
this.env.renderer.clearAllHighlights(true);
|
||||
}.bind(this));
|
||||
|
||||
}
|
||||
|
||||
mouseMove() {
|
||||
alert("mouse move must be overriden");
|
||||
}
|
||||
|
||||
mouseDown() {
|
||||
alert("mouse down must be overriden");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CanvasController;
|
||||
11
src/Controllers/ControlModes.js
Normal file
11
src/Controllers/ControlModes.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const Modes = {
|
||||
None: 0,
|
||||
FoodDrop: 1,
|
||||
WallDrop: 2,
|
||||
ClickKill: 3,
|
||||
Select: 4,
|
||||
Edit: 5,
|
||||
Clone: 6
|
||||
}
|
||||
|
||||
module.exports = Modes;
|
||||
192
src/Controllers/ControlPanel.js
Normal file
192
src/Controllers/ControlPanel.js
Normal file
@@ -0,0 +1,192 @@
|
||||
const Hyperparams = require("../Hyperparameters");
|
||||
const Modes = require("./ControlModes");
|
||||
const CellTypes = require("../Organism/Cell/CellTypes");
|
||||
|
||||
class ControlPanel {
|
||||
constructor(engine) {
|
||||
this.engine = engine;
|
||||
this.defineEngineSpeedControls();
|
||||
this.defineTabNavigation();
|
||||
this.defineHyperparameterControls();
|
||||
this.defineModeControls();
|
||||
this.fps = engine.fps;
|
||||
this.organism_record=0;
|
||||
this.env_controller = this.engine.env.controller;
|
||||
this.editor_controller = this.engine.organism_editor.controller;
|
||||
this.env_controller.setControlPanel(this);
|
||||
this.editor_controller.setControlPanel(this);
|
||||
}
|
||||
|
||||
defineEngineSpeedControls(){
|
||||
this.slider = document.getElementById("slider");
|
||||
this.slider.oninput = function() {
|
||||
this.fps = this.slider.value
|
||||
if (this.engine.running) {
|
||||
this.changeEngineSpeed(this.fps);
|
||||
|
||||
}
|
||||
$('#fps').text("Target FPS: "+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);
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
defineTabNavigation() {
|
||||
var self = this;
|
||||
$('.tabnav-item').click(function() {
|
||||
$('.tab').css('display', 'none');
|
||||
var tab = '#'+this.id+'.tab';
|
||||
self.engine.organism_editor.is_active = (this.id == 'editor');
|
||||
$(tab).css('display', 'grid');
|
||||
});
|
||||
}
|
||||
|
||||
defineHyperparameterControls() {
|
||||
$('#food-prod-prob').change(function() {
|
||||
var food_prob = $('#food-prod-prob').val();
|
||||
if ($('#fixed-ratio').is(":checked")) {
|
||||
Hyperparams.foodProdProb = food_prob;
|
||||
Hyperparams.calcProducerFoodRatio(false);
|
||||
$('#lifespan-multiplier').val(Hyperparams.lifespanMultiplier);
|
||||
}
|
||||
else{
|
||||
Hyperparams.foodProdProb = food_prob;
|
||||
}
|
||||
}.bind(this));
|
||||
$('#lifespan-multiplier').change(function() {
|
||||
var lifespan = $('#lifespan-multiplier').val();
|
||||
if ($('#fixed-ratio').is(":checked")) {
|
||||
Hyperparams.lifespanMultiplier = lifespan;
|
||||
Hyperparams.calcProducerFoodRatio(true);
|
||||
$('#food-prod-prob').val(Hyperparams.foodProdProb);
|
||||
}
|
||||
else {
|
||||
Hyperparams.lifespanMultiplier = lifespan;
|
||||
}
|
||||
}.bind(this));
|
||||
$('.mut-prob').change( function() {
|
||||
switch(this.id){
|
||||
case "add-prob":
|
||||
Hyperparams.addProb = this.value;
|
||||
Hyperparams.balanceMutationProbs(1);
|
||||
break;
|
||||
case "change-prob":
|
||||
Hyperparams.changeProb = this.value;
|
||||
Hyperparams.balanceMutationProbs(2);
|
||||
break;
|
||||
case "remove-prob":
|
||||
Hyperparams.removeProb = this.value;
|
||||
Hyperparams.balanceMutationProbs(3);
|
||||
break;
|
||||
}
|
||||
$('#add-prob').val(Math.floor(Hyperparams.addProb));
|
||||
$('#change-prob').val(Math.floor(Hyperparams.changeProb));
|
||||
$('#remove-prob').val(Math.floor(Hyperparams.removeProb));
|
||||
});
|
||||
|
||||
$('#mover-rot').change(function() {
|
||||
Hyperparams.moversCanRotate = this.checked;
|
||||
});
|
||||
$('#offspring-rot').change(function() {
|
||||
Hyperparams.offspringRotate = this.checked;
|
||||
});
|
||||
$('#insta-kill').change(function() {
|
||||
Hyperparams.instaKill = this.checked;
|
||||
});
|
||||
}
|
||||
|
||||
defineModeControls() {
|
||||
var self = this;
|
||||
$('#editor-mode').change( function(el) {
|
||||
var selection = $(this).children("option:selected").val();
|
||||
var prev_mode = self.env_controller.mode;
|
||||
$('#cell-selections').css('display', 'none');
|
||||
switch(selection){
|
||||
case "none":
|
||||
self.setMode(Modes.None);
|
||||
break;
|
||||
case "food":
|
||||
self.setMode(Modes.FoodDrop);
|
||||
break;
|
||||
case "wall":
|
||||
self.setMode(Modes.WallDrop);
|
||||
break;
|
||||
case "kill":
|
||||
self.setMode(Modes.ClickKill);
|
||||
break;
|
||||
case "select":
|
||||
if (prev_mode==Modes.Edit || prev_mode==Modes.Clone && self.engine.organism_editor.organism.cells.length > 1){
|
||||
if (confirm("Selecting a new organism will clear the current organism. Are you sure you wish to switch?")) {
|
||||
self.setMode(Modes.Select);
|
||||
}
|
||||
else {
|
||||
$("#editor-mode").val('edit');
|
||||
}
|
||||
}
|
||||
else {
|
||||
self.setMode(Modes.Select);
|
||||
}
|
||||
break;
|
||||
case "edit":
|
||||
self.setMode(Modes.Edit);
|
||||
$('#cell-selections').css('display', 'grid');
|
||||
break;
|
||||
case "clone":
|
||||
self.setMode(Modes.Clone);
|
||||
self.env_controller.org_to_clone = self.engine.organism_editor.getCopyOfOrg();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$('#reset-env').click( function() {
|
||||
this.engine.env.reset();
|
||||
}.bind(this));
|
||||
$('#kill-all').click( function() {
|
||||
this.engine.env.clearOrganisms();
|
||||
}.bind(this));
|
||||
$('#clear-walls').click( function() {
|
||||
this.engine.env.clearWalls();
|
||||
}.bind(this));
|
||||
$('#clear-editor').click( function() {
|
||||
this.engine.organism_editor.clear();
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
setMode(mode) {
|
||||
this.env_controller.mode = mode;
|
||||
this.editor_controller.mode = mode;
|
||||
}
|
||||
|
||||
setEditorOrganism(org) {
|
||||
this.engine.organism_editor.setOrganismToCopyOf(org);
|
||||
}
|
||||
|
||||
changeEngineSpeed(change_val) {
|
||||
this.engine.stop();
|
||||
this.engine.start(change_val)
|
||||
this.fps = this.engine.fps;
|
||||
}
|
||||
|
||||
update() {
|
||||
$('#fps-actual').text("Actual FPS: " + Math.floor(this.engine.actual_fps));
|
||||
var org_count = this.engine.env.organisms.length;
|
||||
$('#org-count').text("Organism count: " + org_count);
|
||||
if (org_count > this.organism_record)
|
||||
this.organism_record = org_count;
|
||||
$('#org-record').text("Highest count: " + this.organism_record);
|
||||
$('#avg-mut').text("Average Mutation Rate: " + Math.round(this.engine.env.averageMutability() * 100) / 100);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
module.exports = ControlPanel;
|
||||
53
src/Controllers/EditorController.js
Normal file
53
src/Controllers/EditorController.js
Normal file
@@ -0,0 +1,53 @@
|
||||
const CanvasController = require("./CanvasController");
|
||||
const Modes = require("./ControlModes");
|
||||
const CellTypes = require("../Organism/Cell/CellTypes");
|
||||
|
||||
class EditorController extends CanvasController{
|
||||
constructor(env, canvas) {
|
||||
super(env, canvas);
|
||||
this.mode = Modes.None;
|
||||
this.edit_cell_type = null;
|
||||
this.highlight_org = false;
|
||||
this.defineCellTypeSelection();
|
||||
}
|
||||
|
||||
mouseMove() {
|
||||
|
||||
}
|
||||
|
||||
mouseDown() {
|
||||
if (this.edit_cell_type == null || this.mode != Modes.Edit)
|
||||
return;
|
||||
if (this.left_click)
|
||||
this.env.addCellToOrg(this.mouse_c, this.mouse_r, this.edit_cell_type);
|
||||
if (this.right_click)
|
||||
this.env.removeCellFromOrg(this.mouse_c, this.mouse_r);
|
||||
}
|
||||
|
||||
defineCellTypeSelection() {
|
||||
var self = this;
|
||||
$('.cell-type').click( function() {
|
||||
switch(this.id){
|
||||
case "mouth":
|
||||
self.edit_cell_type = CellTypes.mouth;
|
||||
break;
|
||||
case "producer":
|
||||
self.edit_cell_type = CellTypes.producer;
|
||||
break;
|
||||
case "mover":
|
||||
self.edit_cell_type = CellTypes.mover;
|
||||
break;
|
||||
case "killer":
|
||||
self.edit_cell_type = CellTypes.killer;
|
||||
break;
|
||||
case "armor":
|
||||
self.edit_cell_type = CellTypes.armor;
|
||||
break;
|
||||
}
|
||||
$(".cell-type" ).css( "border-color", "black" );
|
||||
$("#"+this.id).css("border-color", "yellow");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EditorController;
|
||||
73
src/Controllers/EnvironmentController.js
Normal file
73
src/Controllers/EnvironmentController.js
Normal file
@@ -0,0 +1,73 @@
|
||||
const CanvasController = require("./CanvasController");
|
||||
const Organism = require('../Organism/Organism');
|
||||
const Modes = require("./ControlModes");
|
||||
const CellTypes = require("../Organism/Cell/CellTypes");
|
||||
|
||||
class EnvironmentController extends CanvasController{
|
||||
constructor(env, canvas) {
|
||||
super(env, canvas);
|
||||
this.mode = Modes.None;
|
||||
this.org_to_clone = null;
|
||||
}
|
||||
|
||||
mouseMove() {
|
||||
this.performModeAction();
|
||||
}
|
||||
|
||||
mouseDown() {
|
||||
this.performModeAction();
|
||||
}
|
||||
|
||||
performModeAction() {
|
||||
var mode = this.mode;
|
||||
var right_click = this.right_click;
|
||||
var left_click = this.left_click;
|
||||
if (mode != Modes.None && (right_click || left_click)) {
|
||||
var cell = this.cur_cell;
|
||||
if (cell == null){
|
||||
return;
|
||||
}
|
||||
switch(mode) {
|
||||
case Modes.FoodDrop:
|
||||
if (left_click && cell.type == CellTypes.empty){
|
||||
this.env.changeCell(cell.col, cell.row, CellTypes.food, null);
|
||||
}
|
||||
else if (right_click && cell.type == CellTypes.food){
|
||||
this.env.changeCell(cell.col, cell.row, CellTypes.empty, null);
|
||||
}
|
||||
break;
|
||||
case Modes.WallDrop:
|
||||
if (left_click && (cell.type == CellTypes.empty || cell.type == CellTypes.food)){
|
||||
this.env.changeCell(cell.col, cell.row, CellTypes.wall, null);
|
||||
}
|
||||
else if (right_click && cell.type == CellTypes.wall){
|
||||
this.env.changeCell(cell.col, cell.row, CellTypes.empty, null);
|
||||
}
|
||||
break;
|
||||
case Modes.ClickKill:
|
||||
if (this.cur_org != null)
|
||||
this.cur_org.die();
|
||||
break;
|
||||
|
||||
case Modes.Select:
|
||||
if (this.cur_org != null){
|
||||
this.control_panel.setEditorOrganism(this.cur_org);
|
||||
}
|
||||
break;
|
||||
|
||||
case Modes.Clone:
|
||||
if (this.org_to_clone != null){
|
||||
var new_org = new Organism(this.mouse_c, this.mouse_r, this.env, this.org_to_clone);
|
||||
if (new_org.isClear(this.mouse_c, this.mouse_r)){
|
||||
this.env.addOrganism(new_org)
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = EnvironmentController;
|
||||
Reference in New Issue
Block a user