Leader reset. Hazard update. Animation 3c.

master
Ben Burlingham 8 years ago
parent 16bb851024
commit 85208e9063
  1. 8
      index.html
  2. 3
      js/animation.js
  3. 2
      js/animation2a.js
  4. 2
      js/animation2b.js
  5. 2
      js/animation3a.js
  6. 15
      js/animation3c.js
  7. 12
      js/arc.js
  8. 28
      js/bundle.js
  9. 12
      js/index.js
  10. 48
      js/particle.js

@ -84,12 +84,18 @@
<div class='outerContainer' id='3a'></div> <div class='outerContainer' id='3a'></div>
<p>
On a larger scale, the particles are starting to take on a personality.
</p>
<div class='outerContainer' id='3b'></div>
<p> <p>
The exploration is now complete: arc-based movement, independent AIs, grid-based vision, The exploration is now complete: arc-based movement, independent AIs, grid-based vision,
hazards, and cohesive flocking behavior, on a large scale: hazards, and cohesive flocking behavior, on a large scale:
</p> </p>
<div class='outerContainer' id='3b'></div> <div class='outerContainer' id='3c'></div>
<script src='js/bundle.js'></script> <script src='js/bundle.js'></script>
<script src='/core/js/ui.js'></script> <script src='/core/js/ui.js'></script>

@ -44,10 +44,9 @@ Animation.prototype.subscribeCount = function(count) {
} }
} }
Animation.prototype.addHazards = function() { Animation.prototype.addHazards = function(n) {
const bounds = this.container.getBoundingClientRect(); const bounds = this.container.getBoundingClientRect();
const n = Random.num(1, 3);
for (let i = 0; i < n; i++) { for (let i = 0; i < n; i++) {
const w = Random.num(50, 200); const w = Random.num(50, 200);
const h = Random.num(50, 200); const h = Random.num(50, 200);

@ -10,5 +10,5 @@ export default function(destroy$) {
}; };
const observables = Controls(destroy$, config); const observables = Controls(destroy$, config);
(new Animation(observables, id, true)).addHazards(); (new Animation(observables, id, true)).addHazards(2);
} }

@ -10,5 +10,5 @@ export default function(destroy$) {
}; };
const observables = Controls(destroy$, config); const observables = Controls(destroy$, config);
new Animation(observables, id).addHazards(); new Animation(observables, id).addHazards(2);
} }

@ -11,5 +11,5 @@ export default function(destroy$) {
}; };
const observables = Controls(destroy$, config); const observables = Controls(destroy$, config);
new Animation(observables, id, BEHAVIOR.COHESION); new Animation(observables, id, BEHAVIOR.COHESION).addHazards();
} }

@ -0,0 +1,15 @@
import Animation from './animation';
import Controls from './controls';
import { BEHAVIOR } from './enums';
export default function(destroy$) {
const id = '3c';
const config = {
id,
count: 200,
maxCount: 1000
};
const observables = Controls(destroy$, config);
new Animation(observables, id, BEHAVIOR.COHESION).addHazards(1);
}

@ -137,20 +137,22 @@ const Arc = {
if (arc.speed > arcToFollow.speed) { if (arc.speed > arcToFollow.speed) {
arc = Arc.changeSpeed(arc, arc.speed - 1); arc = Arc.changeSpeed(arc, arc.speed - 1);
} if (arc.speed < arcToFollow.speed) { }
if (arc.speed < arcToFollow.speed) {
arc = Arc.changeSpeed(arc, arc.speed + 1); arc = Arc.changeSpeed(arc, arc.speed + 1);
} }
} else if (rigidityCoeff < rigidity) { } else if (rigidityCoeff < rigidity) {
arc = Arc.changeRadius(arc, 20); arc = Arc.changeRadius(arc, 20);
if (arc.speed > arcToFollow.speed - 1) { if (arc.speed > arcToFollow.speed) {
arc = Arc.changeSpeed(arc, arc.speed - 1); arc = Arc.changeSpeed(arc, arc.speed - 1);
} }
} else { } else {
arc = Arc.changeRadius(arc, 4000); arc = Arc.changeRadius(arc, 4000);
if (arc.speed < (arcToFollow.speed + 2)) { if (arc.speed < arcToFollow.speed + 2) {
arc = Arc.changeSpeed(arc, arc.speed + 1); arc = Arc.changeSpeed(arc, arc.speed + 1);
} }
} }
@ -159,8 +161,8 @@ const Arc = {
}, },
evade: function(arc) { evade: function(arc) {
arc = Arc.changeRadius(arc, 20); arc = Arc.changeRadius(arc, 15);
arc.length = 1; arc.length = 0.3;
return arc; return arc;
} }

File diff suppressed because one or more lines are too long

@ -5,6 +5,7 @@ import Animation2a from './animation2a';
import Animation2b from './animation2b'; import Animation2b from './animation2b';
import Animation3a from './animation3a'; import Animation3a from './animation3a';
import Animation3b from './animation3b'; import Animation3b from './animation3b';
import Animation3c from './animation3c';
require('../css/reset.scss'); require('../css/reset.scss');
require('../css/index.scss'); require('../css/index.scss');
@ -14,9 +15,9 @@ require('../css/controls.scss');
window.addEventListener('load', () => { window.addEventListener('load', () => {
const destroy$ = new Rx.BehaviorSubject(null); const destroy$ = new Rx.BehaviorSubject(null);
window.addEventListener('blur', () => { // window.addEventListener('blur', () => {
destroy$.next('all'); // destroy$.next('all');
}); // });
Animation1a(destroy$); Animation1a(destroy$);
Animation1b(destroy$); Animation1b(destroy$);
@ -24,14 +25,11 @@ window.addEventListener('load', () => {
Animation2b(destroy$); Animation2b(destroy$);
Animation3a(destroy$); Animation3a(destroy$);
Animation3b(destroy$); Animation3b(destroy$);
Animation3c(destroy$);
}); });
// TODO remove bottom padding from Disqus // TODO remove bottom padding from Disqus
// TODO sort out particle nextframe // TODO sort out particle nextframe
// TODO abs positioning on controls elements so order doesn't matter
// TODO grid touches
// TODO leader not quite right, if 2 particles, sometimes ignored
// TODO Randomize leaders every 30 sec
// INTERESTING CONTROLS: // INTERESTING CONTROLS:
// sensitivity // sensitivity

@ -53,9 +53,9 @@ function Particle(parent, bounds, globalGrid, observables, behavior) {
this.remove$ = new Rx.Subject(); this.remove$ = new Rx.Subject();
observables.fps$ const frames = observables.fps$.takeUntil(this.remove$);
.takeUntil(this.remove$) frames.subscribe(this.subscribeFrameMove.bind(this));
.subscribe(this.subscribeNextFrame.bind(this)); frames.subscribe(this.subscribeFrameRepaint.bind(this));
observables.speed$ observables.speed$
.takeUntil(this.remove$) .takeUntil(this.remove$)
@ -89,7 +89,7 @@ Particle.prototype.remove = function() {
delete this.nodes; delete this.nodes;
} }
Particle.prototype.subscribeNextFrame = function(n) { Particle.prototype.subscribeFrameMove = function(n) {
this.grids.global.deletePoint({ this.grids.global.deletePoint({
x: this.arc.endX, x: this.arc.endX,
y: this.arc.endY, y: this.arc.endY,
@ -102,23 +102,25 @@ Particle.prototype.subscribeNextFrame = function(n) {
this.arc = Arc.randomize(this.arc); this.arc = Arc.randomize(this.arc);
} }
this.arc = Arc.step(this.arc, this.config.bounds);
this.grids.vision = updateVisionGrid(this.arc, this.config, this.grids); this.grids.vision = updateVisionGrid(this.arc, this.config, this.grids);
const { hazards, particles } = look(this.arc, this.grids); const { hazards, particles } = look(this.arc, this.grids);
this.updateLeader(particles);
if (hazards.length > 0) { if (hazards.length > 0) {
this.arc = Arc.evade(this.arc); this.arc = Arc.evade(this.arc);
} }
this.updateLeader(particles); this.arc = Arc.step(this.arc, this.config.bounds);
this.grids.global.setPoint({ this.grids.global.setPoint({
x: this.arc.endX, x: this.arc.endX,
y: this.arc.endY, y: this.arc.endY,
type: ENTITIES.PARTICLE type: ENTITIES.PARTICLE
}, this); }, this);
}
Particle.prototype.subscribeFrameRepaint = function(n) {
repaintContainer(this.nodes.container, this.arc, this.leaderTime); repaintContainer(this.nodes.container, this.arc, this.leaderTime);
repaintBody(this.nodes.body, this.arc, this.leaderTime); repaintBody(this.nodes.body, this.arc, this.leaderTime);
repaintCircle(this.nodes.circle, this.arc); repaintCircle(this.nodes.circle, this.arc);
@ -166,27 +168,38 @@ Particle.prototype.updateLeader = function(particles) {
if (leader !== undefined) { if (leader !== undefined) {
leader.leaderTime = 1; leader.leaderTime = 1;
this.leaderTime = 0;
this.leader = leader; this.leader = leader;
} }
} }
if (this.leader === null) { if (this.leader === null) {
if (this.leaderTime > 0) {
this.leaderTime++;
}
// Reset leader after a bit. (320 frames is 10 seconds)
if (this.leaderTime > 3000) {
this.leaderTime = 0;
}
// This particle may now be leading - break execution.
return; return;
} }
if (this.leader.nodes === undefined) { // if (this.leader.nodes === undefined) {
if (this.leader.leaderTime === 0 && this.leader.leader === null) {
this.leader = null; this.leader = null;
return; return;
} }
this.leaderTime = 0;
// Visit next node to keep chains of leaders short.
if (this.leader.leader !== null) { if (this.leader.leader !== null) {
this.leader = this.leader.leader; this.leader = this.leader.leader;
} }
if (this.leaderTime > 0) {
this.leaderTime = 0;
}
// Beware of circular leadership, where a leader sees its tail. // Beware of circular leadership, where a leader sees its tail.
if (this.leader.id === this.id) { if (this.leader.id === this.id) {
this.leader = null; this.leader = null;
@ -207,6 +220,9 @@ function look(arc, grids) {
if (global.getPoint({ x, y, type: ENTITIES.HAZARD })) { if (global.getPoint({ x, y, type: ENTITIES.HAZARD })) {
acc.hazards.push({ x, y }); acc.hazards.push({ x, y });
point.touch = true;
} else {
point.touch = false;
} }
return acc; return acc;
@ -302,7 +318,7 @@ function repaintContainer(node, arc, leaderTime) {
node.style.left = `${arc.endX}px`; node.style.left = `${arc.endX}px`;
node.style.top = `${arc.endY}px`; node.style.top = `${arc.endY}px`;
node.style.zIndex = (leaderTime > 0 ? 2000 : 2); // node.style.zIndex = (leaderTime > 0 ? 2000 : 2);
} }
function repaintBody(node, arc, leaderTime) { function repaintBody(node, arc, leaderTime) {
@ -312,7 +328,7 @@ function repaintBody(node, arc, leaderTime) {
node.style.transform = `rotate(${rad + RAD.t45}rad)`; node.style.transform = `rotate(${rad + RAD.t45}rad)`;
node.style.border = (leaderTime > 0 ? '3px dotted #fff' : ''); // node.style.border = (leaderTime > 0 ? '3px dotted #fff' : '');
} }
function repaintCircle(node, arc) { function repaintCircle(node, arc) {
@ -334,11 +350,11 @@ function repaintVisionGrid(nodes, arc, grids) {
return; return;
} }
grids.vision.forEach(({ x, y }, i) => { grids.vision.forEach(({ x, y, touch }, i) => {
nodes[i].style.left = `${x}px`; nodes[i].style.left = `${x}px`;
nodes[i].style.top = `${y}px`; nodes[i].style.top = `${y}px`;
// nodes[i].style.border = (touch ? '2px solid red' : '0'); nodes[i].style.border = (touch ? '1px solid red' : '0');
}); });
} }

Loading…
Cancel
Save