Skip to content

Commit

Permalink
Implemented issue #15
Browse files Browse the repository at this point in the history
  • Loading branch information
jobtalle committed Feb 17, 2020
1 parent 269afac commit 66ed75c
Show file tree
Hide file tree
Showing 21 changed files with 146 additions and 107 deletions.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<script src="js/agent/body.js"></script>
<script src="js/agent/eyes.js"></script>
<script src="js/agent/mouth.js"></script>
<script src="js/agent/tentacles.js"></script>
<script src="js/agent/tentacle/tentacles.js"></script>
<script src="js/agent/agent.js"></script>
<script src="js/rater.js"></script>
<script src="js/selector.js"></script>
Expand Down
29 changes: 17 additions & 12 deletions js/agent/agent.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
const Agent = function(dna, position, direction) {
this.dna = dna;
this.position = position;
this.positionPrevious = this.position.copy();
this.direction = direction;
this.directionPrevious = this.direction.copy();
this.velocity = new Vector();
this.body = new Body(dna.body, this.position, this.direction);
this.body = new Body(dna.body, this.position, this.positionPrevious, this.direction, this.directionPrevious);
this.impulse = new Vector();
this.mass = this.body.getMass();
this.eaten = 0;
};

Agent.FRICTION = 1;
Agent.TORQUE = .5;
Agent.IMPULSE = 150;
Agent.FRICTION = .88;
Agent.TORQUE = .65;
Agent.IMPULSE = 20;

Agent.prototype.update = function(timeStep) {
this.velocity.divide(1 + Agent.FRICTION * timeStep);
Agent.prototype.update = function() {
this.positionPrevious.set(this.position);
this.directionPrevious.set(this.direction);

this.position.x += this.velocity.x * timeStep;
this.position.y += this.velocity.y * timeStep;
this.velocity.multiply(Agent.FRICTION);

this.position.x += this.velocity.x;
this.position.y += this.velocity.y;

this.impulse.zero();
this.body.update(timeStep, this.impulse);
this.body.update(this.impulse);

this.velocity.add(this.impulse.copy().multiply(Agent.IMPULSE / this.mass));
this.direction.add(this.impulse.copy().multiply(Agent.TORQUE / this.mass));
this.direction.subtract(this.impulse.copy().multiply(Agent.TORQUE / this.mass));
this.direction.normalize();
};

Agent.prototype.draw = function(context) {
this.body.draw(context);
Agent.prototype.draw = function(context, f) {
this.body.draw(context, f);
};
33 changes: 20 additions & 13 deletions js/agent/body.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const Body = function(dna, position, direction) {
const Body = function(dna, position, positionPrevious, direction, directionPrevious) {
this.position = position;
this.positionPrevious = positionPrevious;
this.direction = direction;
this.directionPrevious = directionPrevious;
this.brain = new Brain(dna.brain);
this.mouth = new Mouth(dna.mouth);
this.eyes = new Eyes(dna.eyes);
Expand All @@ -10,31 +12,36 @@ const Body = function(dna, position, direction) {

Body.MASS_BASE = 50;

Body.prototype.update = function(timeStep, impulse) {
this.brain.update(timeStep);
this.tentacles.update(timeStep, impulse, this.brain.outputs);
this.mouth.update(timeStep);
this.eyes.update(timeStep);
Body.prototype.update = function(impulse) {
this.brain.update();
this.tentacles.update(impulse, this.brain.outputs);
this.mouth.update();
this.eyes.update();
};

Body.prototype.draw = function(context) {
this.tentacles.draw(context);
Body.prototype.draw = function(context, f) {
const x = this.positionPrevious.x + (this.position.x - this.positionPrevious.x) * f;
const y = this.positionPrevious.y + (this.position.y - this.positionPrevious.y) * f;
const dx = this.directionPrevious.x + (this.direction.x - this.directionPrevious.x) * f;
const dy = this.directionPrevious.y + (this.direction.y - this.directionPrevious.y) * f;

this.tentacles.draw(context, f);
this.mouth.draw(context);
this.eyes.draw(context);

context.strokeStyle = "red";
context.beginPath();
context.moveTo(
this.position.x - this.direction.x * this.radius,
this.position.y - this.direction.y * this.radius);
x - dx * this.radius,
y - dy * this.radius);
context.lineTo(
this.position.x + this.direction.x * this.radius,
this.position.y + this.direction.y * this.radius);
x + dx * this.radius,
y + dy * this.radius);
context.stroke();

context.strokeStyle = "white";
context.beginPath();
context.arc(this.position.x, this.position.y, this.radius, 0, Math.PI * 2);
context.arc(x, y, this.radius, 0, Math.PI * 2);
context.stroke();
};

Expand Down
4 changes: 2 additions & 2 deletions js/agent/brain/axon.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ const Axon = function(dna, from, to) {
this.to = to;
};

Axon.prototype.update = function(timeStep) {
this.to.activation += this.from.output * this.weight * timeStep;
Axon.prototype.update = function() {
this.to.activation += this.from.output * this.weight;
};
8 changes: 4 additions & 4 deletions js/agent/brain/brain.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ Brain.prototype.getNeuron = function(axonIndex) {
}
};

Brain.prototype.update = function(timeStep) {
Brain.prototype.update = function() {
for (const neuron of this.neurons)
neuron.update(timeStep);
neuron.update();

for (const output of this.outputs)
output.update(timeStep);
output.update();

for (const axon of this.axons)
axon.update(timeStep);
axon.update();
};
21 changes: 7 additions & 14 deletions js/agent/brain/neuron.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
const Neuron = function(dna) {
this.decay = dna.decay;
this.activation = .5;
this.activationPrevious = this.activation;
this.output = 0;
this.outputPrevious = this.output;
};

Neuron.prototype.update = function(timeStep) {
Neuron.prototype.update = function() {
this.activationPrevious = this.activation;
this.outputPrevious = this.output;

const d = .2;
let a = this.activation;

Expand All @@ -16,19 +21,7 @@ Neuron.prototype.update = function(timeStep) {
a = 0;

this.output = 1 / (1 + Math.exp(-a)); // Logistic function
// this.output = Math.tanh(a * .1); // Tanh

// Linear decay
// if (this.activation > 0) {
// if ((this.activation -= this.decay * timeStep) < 0)
// this.activation = 0;
// }
// else {
// if ((this.activation += this.decay * timeStep) > 0)
// this.activation = 0;
// }

// Quadratic decay
this.activation /= 1 + this.decay * timeStep;
// this.activation -= this.activation * Math.min(this.decay * timeStep, 1);
this.activation *= this.decay;
};
2 changes: 1 addition & 1 deletion js/agent/dna/dnaAxon.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const DNAAxon = function(
from,
to,
weight = (-.5 + Math.random()) * 50) {
weight = (-.5 + Math.random()) * 2) {
this.from = from;
this.to = to;
this.weight = weight;
Expand Down
2 changes: 1 addition & 1 deletion js/agent/dna/dnaNeuron.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const DNANeuron = function(
this.decay = decay;
};

DNANeuron.DEFAULT_DECAY = 1;
DNANeuron.DEFAULT_DECAY = .95;

DNANeuron.prototype.copy = function() {
return new DNANeuron(
Expand Down
2 changes: 1 addition & 1 deletion js/agent/dna/dnaTentacle.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const DNATentacle = function(

DNATentacle.DEFAULT_ANGLE = 0;
DNATentacle.DEFAULT_LENGTH = 8;
DNATentacle.DEFAULT_SPRING = 10;
DNATentacle.DEFAULT_SPRING = .5;
DNATentacle.DEFAULT_SPRING_POWER = 3;

DNATentacle.prototype.copy = function() {
Expand Down
2 changes: 1 addition & 1 deletion js/agent/eyes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const Eyes = function(dna) {

};

Eyes.prototype.update = function(timeStep) {
Eyes.prototype.update = function() {

};

Expand Down
2 changes: 1 addition & 1 deletion js/agent/mouth.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const Mouth = function(dna) {

};

Mouth.prototype.update = function(timeStep) {
Mouth.prototype.update = function() {

};

Expand Down
44 changes: 28 additions & 16 deletions js/agent/tentacle/segment.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const Segment = function(position, spring = 0, spacing = 0, parent = null) {
this.position = position.copy();
this.positionPrevious = this.position.copy();
this.spring = spring;
this.spacing = spacing;
this.parent = parent;
Expand All @@ -9,8 +10,12 @@ const Segment = function(position, spring = 0, spacing = 0, parent = null) {
this.direction = this.parent.position.copy().subtract(this.position).normalize();
else
this.direction = new Vector();

this.directionPrevious = this.direction.copy();
};

Segment.PUSH_POWER = 3;

Segment.prototype.getHead = function() {
if (this.parent)
return this.parent.getHead();
Expand All @@ -25,27 +30,27 @@ Segment.prototype.getLength = function() {
return 0;
};

Segment.prototype.update = function(timeStep, velocity) {
Segment.prototype.update = function(velocity) {
if (!this.parent)
return;

const xp = this.position.x;
const yp = this.position.y;
this.positionPrevious.set(this.position);
this.directionPrevious.set(this.direction);

this.parent.update(timeStep, velocity);
this.parent.update(velocity);
this.direction.set(this.parent.position).subtract(this.position).normalize();
this.delta.set(this.direction).negate();

const lateralDot = (this.direction.x * this.parent.direction.y - this.direction.y * this.parent.direction.x);

if (this.direction.dot(this.parent.direction) < 0) {
const force = this.spring * Math.sign(lateralDot) * timeStep;
const force = this.spring * Math.sign(lateralDot);

this.delta.x += this.direction.y * force;
this.delta.y -= this.direction.x * force;
}
else {
const force = this.spring * lateralDot * timeStep;
const force = this.spring * lateralDot;

this.delta.x += this.direction.y * force;
this.delta.y -= this.direction.x * force;
Expand All @@ -58,35 +63,42 @@ Segment.prototype.update = function(timeStep, velocity) {
else
this.position.set(this.parent.position).add(this.delta.multiply(this.spacing / this.delta.length()));

const dx = this.position.x - xp;
const dy = this.position.y - yp;
const push = (this.direction.y * dx - this.direction.x * dy) * lateralDot * lateralDot;
const dx = this.position.x - this.positionPrevious.x;
const dy = this.position.y - this.positionPrevious.y;
const push = (this.direction.y * dx - this.direction.x * dy) * Math.pow(Math.abs(lateralDot), Segment.PUSH_POWER);

velocity.x -= this.direction.y * push;
velocity.y += this.direction.x * push;
};

Segment.prototype.draw = function(context) {
Segment.prototype.draw = function(context, f) {
if (!this.parent)
return;

this.parent.draw(context);
this.parent.draw(context, f);

const x = this.positionPrevious.x + (this.position.x - this.positionPrevious.x) * f;
const y = this.positionPrevious.y + (this.position.y - this.positionPrevious.y) * f;
const px = this.parent.positionPrevious.x + (this.parent.position.x - this.parent.positionPrevious.x) * f;
const py = this.parent.positionPrevious.y + (this.parent.position.y - this.parent.positionPrevious.y) * f;
const dx = this.directionPrevious.x + (this.direction.x - this.directionPrevious.x) * f;
const dy = this.directionPrevious.y + (this.direction.y - this.directionPrevious.y) * f;

context.strokeStyle = "white";

context.beginPath();
context.moveTo(this.position.x, this.position.y);
context.lineTo(this.parent.position.x, this.parent.position.y);
context.moveTo(x, y);
context.lineTo(px, py);
context.stroke();

context.beginPath();
context.arc(this.position.x, this.position.y, 3, 0, Math.PI * 2);
context.arc(x, y, 3, 0, Math.PI * 2);
context.stroke();

context.strokeStyle = "red";

context.beginPath();
context.moveTo(this.position.x, this.position.y);
context.lineTo(this.position.x - this.direction.x * 40, this.position.y - this.direction.y * 40);
context.moveTo(x, y);
context.lineTo(x - dx * 40, y - dy * 40);
context.stroke();
};
3 changes: 3 additions & 0 deletions js/agent/tentacle/segmentHead.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ const SegmentHead = function(position) {
SegmentHead.prototype = Object.create(Segment.prototype);

SegmentHead.prototype.setAnchor = function(position, angle) {
this.positionPrevious.set(this.position);
this.directionPrevious.set(this.direction);

this.position.set(position);
this.direction.fromAngle(angle);
};
10 changes: 5 additions & 5 deletions js/agent/tentacle/tentacle.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ const Tentacle = function(dna, position, direction, radius) {

Tentacle.SPACING = 18;

Tentacle.prototype.update = function(timeStep, velocity) {
this.tail.update(timeStep, velocity);
Tentacle.prototype.update = function(velocity) {
this.tail.update(velocity);
};

Tentacle.prototype.draw = function(context) {
this.tail.draw(context);
Tentacle.prototype.draw = function(context, f) {
this.tail.draw(context, f);
};

Tentacle.prototype.getLength = function() {
Expand All @@ -36,7 +36,7 @@ Tentacle.prototype.build = function() {
let tail = this.head;

for (let i = 0; i < this.length; ++i) {
const spring = this.spring * Math.pow(1 - (i / (this.length - 1)) * .35, this.springPower);
const spring = this.spring * Math.pow(1 - (i / (this.length - 1)) * 0.35, this.springPower);

tail = new Segment(
tail.position.copy().add(this.delta.copy().normalize().multiply(Tentacle.SPACING)),
Expand Down
8 changes: 4 additions & 4 deletions js/agent/tentacles.js → js/agent/tentacle/tentacles.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ Tentacles.prototype.getMass = function() {
return mass;
};

Tentacles.prototype.update = function(timeStep, impulse, outputs) {
Tentacles.prototype.update = function(impulse, outputs) {
for (let tentacle = 0; tentacle < this.tentacles.length; ++tentacle) {
this.tentacles[tentacle].setAnchor(this.position, 2 * outputs[tentacle].output - 1);
this.tentacles[tentacle].update(timeStep, impulse);
this.tentacles[tentacle].update(impulse);
}
};

Tentacles.prototype.draw = function(context) {
Tentacles.prototype.draw = function(context, f) {
for (const tentacle of this.tentacles)
tentacle.draw(context);
tentacle.draw(context, f);
};
Loading

0 comments on commit 66ed75c

Please sign in to comment.