224 lines
8.0 KiB
JavaScript
224 lines
8.0 KiB
JavaScript
const CanvasController = require("./CanvasController");
|
|
const Organism = require('../Organism/Organism');
|
|
const Modes = require("./ControlModes");
|
|
const CellStates = require("../Organism/Cell/CellStates");
|
|
const Neighbors = require("../Grid/Neighbors");
|
|
const FossilRecord = require("../Stats/FossilRecord");
|
|
const Hyperparams = require("../Hyperparameters");
|
|
const Perlin = require("../Utils/Perlin");
|
|
|
|
class EnvironmentController extends CanvasController{
|
|
constructor(env, canvas) {
|
|
super(env, canvas);
|
|
this.mode = Modes.FoodDrop;
|
|
this.org_to_clone = null;
|
|
this.add_new_species = false;
|
|
this.defineZoomControls();
|
|
this.scale = 1;
|
|
}
|
|
|
|
defineZoomControls() {
|
|
var scale = 1;
|
|
var zoom_speed = 0.5;
|
|
const el = document.querySelector('#env-canvas');
|
|
el.onwheel = function zoom(event) {
|
|
event.preventDefault();
|
|
|
|
var sign = -Math.sign(event.deltaY);
|
|
|
|
// Restrict scale
|
|
scale = Math.max(0.5, this.scale+(sign*zoom_speed));
|
|
|
|
var cur_top = parseInt($('#env-canvas').css('top'));
|
|
var cur_left = parseInt($('#env-canvas').css('left'));
|
|
|
|
var diff_x = (this.canvas.width/2 - this.mouse_x) * (scale - this.scale);
|
|
var diff_y = (this.canvas.height/2 - this.mouse_y) * (scale - this.scale);
|
|
|
|
$('#env-canvas').css('top', (cur_top+diff_y)+'px');
|
|
$('#env-canvas').css('left', (cur_left+diff_x)+'px');
|
|
|
|
// Apply scale transform
|
|
el.style.transform = `scale(${scale})`;
|
|
this.scale = scale;
|
|
|
|
}.bind(this);
|
|
}
|
|
|
|
resetView() {
|
|
$('#env-canvas').css('transform', 'scale(1)');
|
|
$('#env-canvas').css('top', '0px');
|
|
$('#env-canvas').css('left', '0px');
|
|
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();
|
|
var noise_threshold = -0.017;
|
|
var avg_noise = 0;
|
|
Perlin.seed();
|
|
|
|
for (var r = 0; r < this.env.num_rows; r++) {
|
|
for (var c = 0; c < this.env.num_cols; c++) {
|
|
var noise = Perlin.get(c/this.env.num_cols*(20/this.env.renderer.cell_size), r/this.env.num_rows*(20/this.env.renderer.cell_size));
|
|
avg_noise += noise/(this.env.num_rows*this.env.num_cols);
|
|
if (noise > noise_threshold && noise < noise_threshold + thickness/(4*this.env.renderer.cell_size)) {
|
|
var 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log("Average noise: " + avg_noise);
|
|
}
|
|
|
|
updateMouseLocation(offsetX, offsetY){
|
|
|
|
super.updateMouseLocation(offsetX, offsetY);
|
|
}
|
|
|
|
mouseMove() {
|
|
this.performModeAction();
|
|
}
|
|
|
|
mouseDown() {
|
|
this.start_x = this.mouse_x;
|
|
this.start_y = this.mouse_y;
|
|
this.performModeAction();
|
|
}
|
|
|
|
mouseUp() {
|
|
|
|
}
|
|
|
|
performModeAction() {
|
|
if (Hyperparams.headless)
|
|
return;
|
|
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){
|
|
this.dropCellType(cell.col, cell.row, CellStates.food, false);
|
|
}
|
|
else if (right_click){
|
|
this.dropCellType(cell.col, cell.row, CellStates.empty, false);
|
|
}
|
|
break;
|
|
case Modes.WallDrop:
|
|
if (left_click){
|
|
this.dropCellType(cell.col, cell.row, CellStates.wall, true);
|
|
|
|
}
|
|
else if (right_click){
|
|
this.dropCellType(cell.col, cell.row, CellStates.empty, false);
|
|
}
|
|
break;
|
|
case Modes.ClickKill:
|
|
this.killNearOrganisms();
|
|
break;
|
|
|
|
case Modes.Select:
|
|
if (this.cur_org == null) {
|
|
this.cur_org = this.findNearOrganism();
|
|
}
|
|
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 (this.add_new_species){
|
|
FossilRecord.addSpeciesObj(new_org.species);
|
|
new_org.species.start_tick = this.env.total_ticks;
|
|
this.add_new_species = false;
|
|
new_org.species.population = 0;
|
|
}
|
|
else if (this.org_to_clone.species.extinct){
|
|
FossilRecord.resurrect(this.org_to_clone.species);
|
|
}
|
|
|
|
if (new_org.isClear(this.mouse_c, this.mouse_r)){
|
|
this.env.addOrganism(new_org);
|
|
new_org.species.addPop();
|
|
}
|
|
}
|
|
break;
|
|
case Modes.Drag:
|
|
var cur_top = parseInt($('#env-canvas').css('top'), 10);
|
|
var cur_left = parseInt($('#env-canvas').css('left'), 10);
|
|
var new_top = cur_top + ((this.mouse_y - this.start_y)*this.scale);
|
|
var new_left = cur_left + ((this.mouse_x - this.start_x)*this.scale);
|
|
$('#env-canvas').css('top', new_top+'px');
|
|
$('#env-canvas').css('left', new_left+'px');
|
|
break;
|
|
}
|
|
}
|
|
else if (this.middle_click) {
|
|
//drag on middle click
|
|
var cur_top = parseInt($('#env-canvas').css('top'), 10);
|
|
var cur_left = parseInt($('#env-canvas').css('left'), 10);
|
|
var new_top = cur_top + ((this.mouse_y - this.start_y)*this.scale);
|
|
var new_left = cur_left + ((this.mouse_x - this.start_x)*this.scale);
|
|
$('#env-canvas').css('top', new_top+'px');
|
|
$('#env-canvas').css('left', new_left+'px');
|
|
}
|
|
}
|
|
|
|
dropCellType(col, row, state, killBlocking=false) {
|
|
for (var loc of Neighbors.allSelf){
|
|
var c=col + loc[0];
|
|
var r=row + loc[1];
|
|
var cell = this.env.grid_map.cellAt(c, r);
|
|
if (cell == null)
|
|
continue;
|
|
if (killBlocking && cell.owner != null){
|
|
cell.owner.die();
|
|
}
|
|
else if (cell.owner != null) {
|
|
continue;
|
|
}
|
|
this.env.changeCell(c, r, state, null);
|
|
}
|
|
}
|
|
|
|
findNearOrganism() {
|
|
for (var loc of Neighbors.all){
|
|
var c = this.cur_cell.col + loc[0];
|
|
var r = this.cur_cell.row + loc[1];
|
|
var cell = this.env.grid_map.cellAt(c, r);
|
|
if (cell != null && cell.owner != null)
|
|
return cell.owner;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
killNearOrganisms() {
|
|
for (var loc of Neighbors.allSelf){
|
|
var c = this.cur_cell.col + loc[0];
|
|
var r = this.cur_cell.row + loc[1];
|
|
var cell = this.env.grid_map.cellAt(c, r);
|
|
if (cell != null && cell.owner != null)
|
|
cell.owner.die();
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
module.exports = EnvironmentController;
|