mirror of
https://github.com/rileyjshaw/terra.git
synced 2024-11-21 04:54:23 +00:00
parent
7bf8132311
commit
bb42f11306
@ -117,9 +117,10 @@ var factory = (function () {
|
|||||||
return {
|
return {
|
||||||
x: step.x,
|
x: step.x,
|
||||||
y: step.y,
|
y: step.y,
|
||||||
creature: creature
|
creature: creature,
|
||||||
|
observed: true
|
||||||
};
|
};
|
||||||
} else return false;
|
} else return this.energy !== this.maxEnergy;
|
||||||
};
|
};
|
||||||
|
|
||||||
baseCA.prototype.boundEnergy = function () {};
|
baseCA.prototype.boundEnergy = function () {};
|
||||||
|
@ -19,6 +19,7 @@ function Terrarium(width, height, id, cellSize, insertAfter) {
|
|||||||
this.grid = [];
|
this.grid = [];
|
||||||
this.canvas = dom.createCanvasElement(width, height, cellSize, id, insertAfter);
|
this.canvas = dom.createCanvasElement(width, height, cellSize, id, insertAfter);
|
||||||
this.nextFrame = false;
|
this.nextFrame = false;
|
||||||
|
this.hasChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,8 +68,11 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
function copyAndRemoveInner (origCreature) {
|
function copyAndRemoveInner (origCreature) {
|
||||||
if (origCreature) {
|
if (origCreature) {
|
||||||
var copy = _.assign(new (origCreature.constructor)(), origCreature);
|
var copy = _.assign(new (origCreature.constructor)(), origCreature);
|
||||||
|
var dead = copy && copy.isDead();
|
||||||
|
if (dead && !self.hasChanged) self.hasChanged = true;
|
||||||
copy.age++;
|
copy.age++;
|
||||||
return copy && !copy.isDead() ? copy : false;
|
|
||||||
|
return !dead ? copy : false;
|
||||||
} else return false;
|
} else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +80,7 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
return _.map(origCols, copyAndRemoveInner);
|
return _.map(origCols, copyAndRemoveInner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Switch coords to just x and y to be consistent w/ pickWinnerInner
|
||||||
function zipCoordsWithNeighbors (coords) {
|
function zipCoordsWithNeighbors (coords) {
|
||||||
return {
|
return {
|
||||||
coords: coords,
|
coords: coords,
|
||||||
@ -101,16 +106,21 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
zipCoordsWithNeighbors
|
zipCoordsWithNeighbors
|
||||||
);
|
);
|
||||||
var result = creature.process(neighbors, x, y);
|
var result = creature.process(neighbors, x, y);
|
||||||
if (result) {
|
if (typeof result === 'object') {
|
||||||
var eigenColumn = eigenGrid[result.x];
|
var eigenColumn = eigenGrid[result.x];
|
||||||
if (!eigenColumn[result.y]) eigenColumn[result.y] = [];
|
var returnedCreature = result.creature;
|
||||||
|
var returnedY = result.y;
|
||||||
|
|
||||||
eigenColumn[result.y].push({
|
if (!eigenColumn[returnedY]) eigenColumn[returnedY] = [];
|
||||||
|
|
||||||
|
eigenColumn[returnedY].push({
|
||||||
x: x,
|
x: x,
|
||||||
y: y,
|
y: y,
|
||||||
creature: result.creature
|
creature: returnedCreature
|
||||||
});
|
});
|
||||||
|
if (!self.hasChanged && returnedCreature.observed) self.hasChanged = true;
|
||||||
} else {
|
} else {
|
||||||
|
if (result && !self.hasChanged) self.hasChanged = true;
|
||||||
processLoser(creature);
|
processLoser(creature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,7 +139,7 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
if (!winnerCreature.successFn()) {
|
if (!winnerCreature.successFn()) {
|
||||||
newGrid[winner.x][winner.y] = false;
|
newGrid[winner.x][winner.y] = false;
|
||||||
}
|
}
|
||||||
|
// TODO: so many calls to this. Can we just run it once at the start of a step?
|
||||||
winnerCreature.boundEnergy();
|
winnerCreature.boundEnergy();
|
||||||
|
|
||||||
// put the winner in its rightful place
|
// put the winner in its rightful place
|
||||||
@ -146,6 +156,7 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
_.each(column, function (superposition, y) { pickWinnerInner(superposition, x, y); });
|
_.each(column, function (superposition, y) { pickWinnerInner(superposition, x, y); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
var gridWidth = this.width;
|
var gridWidth = this.width;
|
||||||
var gridHeight = this.height;
|
var gridHeight = this.height;
|
||||||
var oldGrid = this.grid, newGrid, eigenGrid;
|
var oldGrid = this.grid, newGrid, eigenGrid;
|
||||||
@ -153,6 +164,8 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
if (typeof steps !== 'number') steps = 1;
|
if (typeof steps !== 'number') steps = 1;
|
||||||
|
|
||||||
while (steps--) {
|
while (steps--) {
|
||||||
|
this.hasChanged = false;
|
||||||
|
|
||||||
oldGrid = newGrid ? _.clone(newGrid) : this.grid;
|
oldGrid = newGrid ? _.clone(newGrid) : this.grid;
|
||||||
|
|
||||||
// copy the old grid & remove dead creatures
|
// copy the old grid & remove dead creatures
|
||||||
@ -166,6 +179,8 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
|
|
||||||
// Choose a winner from each of the eigenGrid's superpositions
|
// Choose a winner from each of the eigenGrid's superpositions
|
||||||
_.each(eigenGrid, pickWinner);
|
_.each(eigenGrid, pickWinner);
|
||||||
|
|
||||||
|
if (!this.hasChanged) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return newGrid;
|
return newGrid;
|
||||||
@ -179,19 +194,25 @@ Terrarium.prototype.draw = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts animating the simulation
|
* Starts animating the simulation. Can be called with only a function.
|
||||||
* @param {int} steps the simulation will stop after <steps> steps if specified
|
* @param {int} steps the simulation will stop after <steps> steps if specified
|
||||||
* @param {Function} fn called as a callback once the animation finishes
|
* @param {Function} fn called as a callback once the animation finishes
|
||||||
*/
|
*/
|
||||||
Terrarium.prototype.animate = function (steps, fn) {
|
Terrarium.prototype.animate = function (steps, fn) {
|
||||||
function tick () {
|
function tick () {
|
||||||
self.grid = self.step();
|
var grid = self.step();
|
||||||
|
if (grid) {
|
||||||
|
self.grid = grid;
|
||||||
self.draw();
|
self.draw();
|
||||||
if (i++ !== steps) self.nextFrame = requestAnimationFrame(tick);
|
if (++i !== steps) return self.nextFrame = requestAnimationFrame(tick);
|
||||||
else {
|
} // if grid hasn't changed || reached last step
|
||||||
self.nextFrame = false;
|
self.nextFrame = false;
|
||||||
if (fn) fn();
|
if (fn) fn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof steps === 'function') {
|
||||||
|
fn = steps;
|
||||||
|
steps = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.nextFrame) {
|
if (!this.nextFrame) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "terra",
|
"name": "terra",
|
||||||
"version": "1.0.0-beta",
|
"version": "1.1.0-beta",
|
||||||
"homepage": "https://github.com/rileyjshaw/terra",
|
"homepage": "https://github.com/rileyjshaw/terra",
|
||||||
"authors": [
|
"authors": [
|
||||||
"rileyjshaw <i@rileyjshaw.com>"
|
"rileyjshaw <i@rileyjshaw.com>"
|
||||||
|
46
dist/terra.js
vendored
46
dist/terra.js
vendored
@ -128,9 +128,10 @@ var factory = (function () {
|
|||||||
return {
|
return {
|
||||||
x: step.x,
|
x: step.x,
|
||||||
y: step.y,
|
y: step.y,
|
||||||
creature: creature
|
creature: creature,
|
||||||
|
observed: true
|
||||||
};
|
};
|
||||||
} else return false;
|
} else return this.energy !== this.maxEnergy;
|
||||||
};
|
};
|
||||||
|
|
||||||
baseCA.prototype.boundEnergy = function () {};
|
baseCA.prototype.boundEnergy = function () {};
|
||||||
@ -313,6 +314,7 @@ function Terrarium(width, height, id, cellSize, insertAfter) {
|
|||||||
this.grid = [];
|
this.grid = [];
|
||||||
this.canvas = dom.createCanvasElement(width, height, cellSize, id, insertAfter);
|
this.canvas = dom.createCanvasElement(width, height, cellSize, id, insertAfter);
|
||||||
this.nextFrame = false;
|
this.nextFrame = false;
|
||||||
|
this.hasChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -361,8 +363,11 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
function copyAndRemoveInner (origCreature) {
|
function copyAndRemoveInner (origCreature) {
|
||||||
if (origCreature) {
|
if (origCreature) {
|
||||||
var copy = _.assign(new (origCreature.constructor)(), origCreature);
|
var copy = _.assign(new (origCreature.constructor)(), origCreature);
|
||||||
|
var dead = copy && copy.isDead();
|
||||||
|
if (dead && !self.hasChanged) self.hasChanged = true;
|
||||||
copy.age++;
|
copy.age++;
|
||||||
return copy && !copy.isDead() ? copy : false;
|
|
||||||
|
return !dead ? copy : false;
|
||||||
} else return false;
|
} else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,6 +375,7 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
return _.map(origCols, copyAndRemoveInner);
|
return _.map(origCols, copyAndRemoveInner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Switch coords to just x and y to be consistent w/ pickWinnerInner
|
||||||
function zipCoordsWithNeighbors (coords) {
|
function zipCoordsWithNeighbors (coords) {
|
||||||
return {
|
return {
|
||||||
coords: coords,
|
coords: coords,
|
||||||
@ -395,16 +401,21 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
zipCoordsWithNeighbors
|
zipCoordsWithNeighbors
|
||||||
);
|
);
|
||||||
var result = creature.process(neighbors, x, y);
|
var result = creature.process(neighbors, x, y);
|
||||||
if (result) {
|
if (typeof result === 'object') {
|
||||||
var eigenColumn = eigenGrid[result.x];
|
var eigenColumn = eigenGrid[result.x];
|
||||||
if (!eigenColumn[result.y]) eigenColumn[result.y] = [];
|
var returnedCreature = result.creature;
|
||||||
|
var returnedY = result.y;
|
||||||
|
|
||||||
eigenColumn[result.y].push({
|
if (!eigenColumn[returnedY]) eigenColumn[returnedY] = [];
|
||||||
|
|
||||||
|
eigenColumn[returnedY].push({
|
||||||
x: x,
|
x: x,
|
||||||
y: y,
|
y: y,
|
||||||
creature: result.creature
|
creature: returnedCreature
|
||||||
});
|
});
|
||||||
|
if (!self.hasChanged && returnedCreature.observed) self.hasChanged = true;
|
||||||
} else {
|
} else {
|
||||||
|
if (result && !self.hasChanged) self.hasChanged = true;
|
||||||
processLoser(creature);
|
processLoser(creature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,7 +434,7 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
if (!winnerCreature.successFn()) {
|
if (!winnerCreature.successFn()) {
|
||||||
newGrid[winner.x][winner.y] = false;
|
newGrid[winner.x][winner.y] = false;
|
||||||
}
|
}
|
||||||
|
// TODO: so many calls to this. Can we just run it once at the start of a step?
|
||||||
winnerCreature.boundEnergy();
|
winnerCreature.boundEnergy();
|
||||||
|
|
||||||
// put the winner in its rightful place
|
// put the winner in its rightful place
|
||||||
@ -440,6 +451,7 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
_.each(column, function (superposition, y) { pickWinnerInner(superposition, x, y); });
|
_.each(column, function (superposition, y) { pickWinnerInner(superposition, x, y); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
var gridWidth = this.width;
|
var gridWidth = this.width;
|
||||||
var gridHeight = this.height;
|
var gridHeight = this.height;
|
||||||
var oldGrid = this.grid, newGrid, eigenGrid;
|
var oldGrid = this.grid, newGrid, eigenGrid;
|
||||||
@ -447,6 +459,8 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
if (typeof steps !== 'number') steps = 1;
|
if (typeof steps !== 'number') steps = 1;
|
||||||
|
|
||||||
while (steps--) {
|
while (steps--) {
|
||||||
|
this.hasChanged = false;
|
||||||
|
|
||||||
oldGrid = newGrid ? _.clone(newGrid) : this.grid;
|
oldGrid = newGrid ? _.clone(newGrid) : this.grid;
|
||||||
|
|
||||||
// copy the old grid & remove dead creatures
|
// copy the old grid & remove dead creatures
|
||||||
@ -460,6 +474,8 @@ Terrarium.prototype.step = function (steps) {
|
|||||||
|
|
||||||
// Choose a winner from each of the eigenGrid's superpositions
|
// Choose a winner from each of the eigenGrid's superpositions
|
||||||
_.each(eigenGrid, pickWinner);
|
_.each(eigenGrid, pickWinner);
|
||||||
|
|
||||||
|
if (!this.hasChanged) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return newGrid;
|
return newGrid;
|
||||||
@ -473,19 +489,25 @@ Terrarium.prototype.draw = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts animating the simulation
|
* Starts animating the simulation. Can be called with only a function.
|
||||||
* @param {int} steps the simulation will stop after <steps> steps if specified
|
* @param {int} steps the simulation will stop after <steps> steps if specified
|
||||||
* @param {Function} fn called as a callback once the animation finishes
|
* @param {Function} fn called as a callback once the animation finishes
|
||||||
*/
|
*/
|
||||||
Terrarium.prototype.animate = function (steps, fn) {
|
Terrarium.prototype.animate = function (steps, fn) {
|
||||||
function tick () {
|
function tick () {
|
||||||
self.grid = self.step();
|
var grid = self.step();
|
||||||
|
if (grid) {
|
||||||
|
self.grid = grid;
|
||||||
self.draw();
|
self.draw();
|
||||||
if (i++ !== steps) self.nextFrame = requestAnimationFrame(tick);
|
if (++i !== steps) return self.nextFrame = requestAnimationFrame(tick);
|
||||||
else {
|
} // if grid hasn't changed || reached last step
|
||||||
self.nextFrame = false;
|
self.nextFrame = false;
|
||||||
if (fn) fn();
|
if (fn) fn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof steps === 'function') {
|
||||||
|
fn = steps;
|
||||||
|
steps = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.nextFrame) {
|
if (!this.nextFrame) {
|
||||||
|
983
dist/terra.min.js
vendored
983
dist/terra.min.js
vendored
File diff suppressed because one or more lines are too long
@ -53,7 +53,7 @@ gulp.task('scripts', ['lint'], function() {
|
|||||||
.pipe(source('terra.js'))
|
.pipe(source('terra.js'))
|
||||||
.pipe(gulp.dest(paths.dist.scripts))
|
.pipe(gulp.dest(paths.dist.scripts))
|
||||||
.pipe($.rename('terra.min.js'))
|
.pipe($.rename('terra.min.js'))
|
||||||
.pipe($.streamify( $.uglify() ))
|
//.pipe($.streamify( $.uglify() ))
|
||||||
.pipe(gulp.dest(paths.dist.scripts))
|
.pipe(gulp.dest(paths.dist.scripts))
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ gulp.task('sass', function () {
|
|||||||
gulp.task('js_concat', ['demo'], function () {
|
gulp.task('js_concat', ['demo'], function () {
|
||||||
return gulp.src(paths.demo.extraScripts.concat(paths.demo.temp + '/*.js'))
|
return gulp.src(paths.demo.extraScripts.concat(paths.demo.temp + '/*.js'))
|
||||||
.pipe($.concat('terra.demo.min.js'))
|
.pipe($.concat('terra.demo.min.js'))
|
||||||
.pipe($.streamify( $.uglify() ))
|
//.pipe($.streamify( $.uglify() ))
|
||||||
.pipe(gulp.dest(paths.dist.demo))
|
.pipe(gulp.dest(paths.dist.demo))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "terra",
|
"name": "terra",
|
||||||
"version": "1.0.0-beta",
|
"version": "1.1.0-beta",
|
||||||
"description": "A JavaScript library for simple biological simulations and cellular automata.",
|
"description": "A JavaScript library for simple biological simulations and cellular automata.",
|
||||||
"main": "dist/terra.min.js",
|
"main": "dist/terra.min.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
Loading…
Reference in New Issue
Block a user