Wall avoidance algorithm finalized.

master
Ben Burlingham 8 years ago
parent 6544b3b5f6
commit 905921ceb0
  1. 6
      css/animation3.scss
  2. 4
      css/style.css
  3. 2
      index.html
  4. 279
      js/animation3-ORIGINAL.js
  5. 169
      js/animation3.js
  6. 221
      js/bundle.js

@ -71,6 +71,10 @@
&.removed { &.removed {
// background: purple; // background: purple;
background: yellow; background: green;
}
&.touching {
outline: 2px solid yellow;
} }
} }

@ -102,7 +102,9 @@ body {
width: 2px; width: 2px;
z-index: 99; } z-index: 99; }
.anim3-dot.removed { .anim3-dot.removed {
background: yellow; } background: green; }
.anim3-dot.touching {
outline: 2px solid yellow; }
.anim3-particle { .anim3-particle {
background: url(../res/seahorse.svg) no-repeat center top #aaa; background: url(../res/seahorse.svg) no-repeat center top #aaa;
background-size: 20px 20px; background-size: 20px 20px;

@ -7,7 +7,7 @@
</head> </head>
<body> <body>
<h1>Dust</h1> <h1>Dust</h1>
<h2>Swarm behavior studies with RxJs</h2> <h2>Studying AI movement along arcs with RxJs</h2>
<hr> <hr>
<div class="particles"></div> <div class="particles"></div>

@ -0,0 +1,279 @@
// Single particle movement.
// Goal: per-frame decisions
// 20 x 20 grid
// The trickiest portion of this iteration was animating the curved paths. Calculating arc length (for scalar speed) along an elliptical
// geometry is quite difficult, so the current solution uses circular paths, which change radius and sometimes rotation after a random
// number of frames have emitted. A smoothstep cubic curve was considered, but maintaining consistent entry and exit angles will affect
// performance for large particle counts.
// This algorithm travels a random period of time around a random arc.
// If a wall is detected, a 180-degree turn is executed.
import Rx, { Observable } from 'rxjs';
import AnimationBase from './animation0';
import DOM from './dom';
import Store from './store';
const speed = 4;
const visionRadius = 50;
const grid = {};
const t45 = Math.PI / 4;
const t90 = Math.PI / 2;
const t270 = 3 * Math.PI / 2;
const t360 = Math.PI * 2;
const movementCircle = document.createElement('div');
movementCircle.className = 'anim3-movement-circle';
const visionGrid = document.createElement('div');
visionGrid.className = 'anim3-vision-grid';
const particle = document.createElement('div');
particle.className = 'anim3-particle';
const visionGridPoints = calculateVisionGridPoints();
function move(store) {
let {
clockwise,
interval,
circleX,
circleY,
particleX,
particleY,
radius,
theta
} = store.get();
// If wall detected, tight 180
if (detectWall(store) && radius !== 20) {
const radius0 = radius;
radius = 20;
interval = Math.PI * 20 / speed;
circleX -= (radius - radius0) * Math.cos(theta);
circleY += (radius - radius0) * Math.sin(theta);
} else if (interval <= 0) {
const radius0 = radius;
interval = Math.round(Math.random() * 10) + 50;
radius = Math.round(Math.random() * 200) + 50;
if (Math.random() < 0.5) {
clockwise = !clockwise;
theta = (theta + Math.PI) % t360;
circleX -= (radius + radius0) * Math.cos(theta);
circleY += (radius + radius0) * Math.sin(theta);
} else {
circleX -= (radius - radius0) * Math.cos(theta);
circleY += (radius - radius0) * Math.sin(theta);
}
}
interval -= 1;
const delta = speed / radius;
theta += (clockwise ? -delta : +delta);
theta = (theta > 0 ? theta % t360 : t360 - theta);
particleX = circleX + radius * Math.cos(theta);
particleY = circleY - radius * Math.sin(theta);
store.set({
clockwise,
interval,
circleX,
circleY,
particleX,
particleY,
radius,
theta
});
}
function detectWall(store) {
const len = visionGridPoints.length;
const { particleX, particleY } = store.get();
const gridX = particleX - particleX % 5;
const gridY = particleY - particleY % 5;
for (let i = 0; i < len; i++) {
const { x, y } = visionGridPoints[i];
const xx = x + gridX;
const yy = y + gridY;
if (grid[xx] && grid[xx][yy] && grid[xx][yy].type === 'wall') {
console.warn("Wall detected", xx, yy);
// TODO this goes somewhere else
// DOM.container.dispatchEvent(new CustomEvent('stop'));
return true;
}
}
return false;
}
function transformMovementCircle(store) {
// TODO UPDATE ONLY IF THETA CHANGED - MUST HAVE PREVSTATE
const { circleX, circleY, radius, theta } = store.get();
const r = Math.abs(radius);
movementCircle.style.left = `${circleX - r}px`;
movementCircle.style.top = `${circleY - r}px`;
movementCircle.style.height = `${2 * r}px`;
movementCircle.style.width = `${2 * r}px`;
movementCircle.style.borderRadius = `${r}px`;
}
function transformParticle(store) {
const { clockwise, particleX, particleY, theta } = store.get();
const rad = clockwise ? Math.PI - theta : t360 - theta;
particle.style.left = `${particleX}px`;
particle.style.top = `${particleY}px`;
particle.style.transform = `rotate(${rad}rad)`;
}
function transformVisionGrid(store) {
const {
circleX,
circleY,
clockwise,
particleX,
particleY,
radius,
theta
} = store.get();
const r0 = Math.min(theta, theta - Math.PI);
const r1 = Math.max(theta, theta + Math.PI);
const gridX = particleX - particleX % 5;
const gridY = particleY - particleY % 5;
visionGridPoints.forEach(({ x, y, alpha, div }, i) => {
if (alpha >= 0 && alpha <= r0) {
div.style.display = (clockwise ? 'none' : 'block');
} else if (alpha >= theta && alpha <= r1) {
div.style.display = (clockwise ? 'none' : 'block');
} else {
div.style.display = (clockwise ? 'block' : 'none');
}
div.style.left = `${x + gridX}px`;
div.style.top = `${-y + gridY}px`;
});
}
function calculateVisionGridPoints() {
const gridSize = 5;
const squareGrid = [];
for (let x = -visionRadius; x <= visionRadius; x += gridSize) {
for (let y = -visionRadius; y <= visionRadius; y += gridSize) {
let alpha = Math.atan(y / x);
if (x === 0 && y === 0) {
alpha = 0;
} else if (x === 0 && y < 0) {
alpha = t270;
} else if (y === 0 && x < 0) {
alpha = Math.PI;
} else if (x === 0 && y > 0) {
alpha = t90;
} else if (x < 0 && y < 0) {
alpha = alpha + Math.PI;
} else if (x <= 0) {
alpha = Math.PI + alpha;
} else if (y < 0) {
alpha = 2 * Math.PI + alpha;
}
squareGrid.push({ x, y, alpha });
}
}
const r0 = Math.pow(visionRadius, 2);
const r1 = Math.pow(visionRadius - gridSize, 2);
return squareGrid.reduce((acc, point) => {
const p = Math.pow(point.x, 2) + Math.pow(point.y, 2);
if (p > r0 || p < r1) {
return acc;
}
const div = document.createElement('div');
div.className = 'anim3-dot';
acc.push(Object.assign(point, { div }));
return acc;
}, []);
}
function reset() {
while (DOM.container.childNodes.length) {
DOM.container.removeChild(DOM.container.firstChild);
}
const store = new Store({
clockwise: false,
interval: 10,
circleX: 300,
circleY: 300,
radius: 270,
theta: Math.PI * 3 / 4
});
move(store);
transformParticle(store);
// transformMovementCircle(store);
// transformVisionGrid(store);
DOM.container.appendChild(particle);
DOM.container.appendChild(movementCircle);
visionGridPoints.forEach(point => {
DOM.container.appendChild(point.div);
});
return store;
};
function init() {
const store = reset();
for (let x = 0; x <= 600; x += 5) {
grid[x] = {};
for (let y = 0; y <= 600; y += 5) {
grid[x][y] = { type: null };
if (x === 0 || y === 0 || x === 600 || y === 600) {
grid[x][y] = { type: 'wall' };
}
}
}
const stop$ = Rx.Observable.fromEvent(DOM.container, 'stop');
const fps$ = Rx.Observable.interval(1000 / 32)
.map(_ => store)
// .take(300)
// .take(15)
.takeUntil(stop$); console.error("CLICK TO STOP");
const click$ = Rx.Observable.fromEvent(DOM.container, 'click');
click$.subscribe(() => {
DOM.container.dispatchEvent(new CustomEvent('stop'));
});
fps$.subscribe(move);
fps$.subscribe(transformParticle);
// fps$.subscribe(transformMovementCircle);
fps$.subscribe(transformVisionGrid);
};
const Animation3 = Object.assign({}, AnimationBase, { init, reset });
export default Animation3;

@ -7,13 +7,15 @@
// number of frames have emitted. A smoothstep cubic curve was considered, but maintaining consistent entry and exit angles will affect // number of frames have emitted. A smoothstep cubic curve was considered, but maintaining consistent entry and exit angles will affect
// performance for large particle counts. // performance for large particle counts.
// This algorithm travels a random period of time around a random arc.
// If a wall is detected, a 180-degree turn is executed.
import Rx, { Observable } from 'rxjs'; import Rx, { Observable } from 'rxjs';
import AnimationBase from './animation0'; import AnimationBase from './animation0';
import DOM from './dom'; import DOM from './dom';
import Store from './store'; import Store from './store';
const speed = 4; const speed = 4;
const visionRadius = 50;
const grid = {}; const grid = {};
const t45 = Math.PI / 4; const t45 = Math.PI / 4;
const t90 = Math.PI / 2; const t90 = Math.PI / 2;
@ -23,9 +25,6 @@ const t360 = Math.PI * 2;
const movementCircle = document.createElement('div'); const movementCircle = document.createElement('div');
movementCircle.className = 'anim3-movement-circle'; movementCircle.className = 'anim3-movement-circle';
const visionGrid = document.createElement('div');
visionGrid.className = 'anim3-vision-grid';
const particle = document.createElement('div'); const particle = document.createElement('div');
particle.className = 'anim3-particle'; particle.className = 'anim3-particle';
@ -33,102 +32,103 @@ const visionGridPoints = calculateVisionGridPoints();
function move(store) { function move(store) {
let { let {
arc,
clockwise, clockwise,
interval,
circleX,
circleY,
particleX, particleX,
particleY, particleY,
radius,
theta
} = store.get(); } = store.get();
// Separation, alignment, cohesion const delta = speed / arc.r;
// if (detectWall(store) && radius !== 20) { arc.t += (clockwise ? -delta : +delta);
// // IF SEEING A WALL: tight 180 arc.t = (arc.t > 0 ? arc.t % t360 : t360 - arc.t);
// const radius0 = radius;
// radius = 20;
// interval = Math.PI * 20 / speed;
// circleX -= (radius - radius0) * Math.cos(theta);
// circleY += (radius - radius0) * Math.sin(theta);
// } else
if (interval <= 0) {
const radius0 = radius;
interval = Math.round(Math.random() * 10) + 50;
radius = Math.round(Math.random() * 200) + 50;
if (Math.random() < 0.5) {
clockwise = !clockwise;
theta = (theta + Math.PI) % t360;
circleX -= (radius + radius0) * Math.cos(theta);
circleY += (radius + radius0) * Math.sin(theta);
} else {
circleX -= (radius - radius0) * Math.cos(theta);
circleY += (radius - radius0) * Math.sin(theta);
}
}
interval -= 1; const wall = detectWall(store);
const delta = speed / radius; if (wall.x !== null) {
theta += (clockwise ? -delta : +delta); // console.warn(wall.x, wall.y, particleX, particleY)
theta = (theta > 0 ? theta % t360 : t360 - theta); const x = wall.x - particleX;
const y = wall.y - particleY;
const v = Math.atan((particleY - wall.y) / (particleX - wall.x));
arc = modifyArc(arc, 40);
} else {
arc = modifyArc(arc, 400);
}
particleX = circleX + radius * Math.cos(theta); particleX = arc.x + arc.r * Math.cos(arc.t);
particleY = circleY - radius * Math.sin(theta); particleY = arc.y - arc.r * Math.sin(arc.t);
store.set({ store.set({
clockwise, arc,
interval,
circleX,
circleY,
particleX, particleX,
particleY, particleY,
radius,
theta
}); });
} }
// generate next arc:
// starting point will be locked
// starting angle will be locked
// therefore tangential
function modifyArc(arc, newRadius) {
const r0 = arc.r;
const r1 = newRadius;
arc.x -= (r1 - r0) * Math.cos(arc.t);
arc.y += (r1 - r0) * Math.sin(arc.t);
arc.r = r1;
return arc;
}
function changeDirection(arc) {
// clockwise = !clockwise;
// theta = (theta + Math.PI) % t360;
// circleX -= (radius + radius0) * Math.cos(theta);
// circleY += (radius + radius0) * Math.sin(theta);
}
function detectWall(store) { function detectWall(store) {
const len = visionGridPoints.length; const len = visionGridPoints.length;
const { particleX, particleY } = store.get(); const { arc, clockwise, particleX, particleY } = store.get();
const r0 = Math.min(arc.t, arc.t - Math.PI);
const r1 = Math.max(arc.t, arc.t + Math.PI);
const gridX = particleX - particleX % 5; const gridX = particleX - particleX % 5;
const gridY = particleY - particleY % 5; const gridY = particleY - particleY % 5;
for (let i = 0; i < len; i++) { return visionGridPoints.reduce((acc, { div, x, y, alpha }) => {
const { x, y } = visionGridPoints[i];
const xx = x + gridX; const xx = x + gridX;
const yy = y + gridY; const yy = gridY - y;
if (grid[xx] && grid[xx][yy] && grid[xx][yy].type === 'wall') { if (grid[xx] && grid[xx][yy] && grid[xx][yy].type === 'wall') {
console.warn("Wall detected", xx, yy); if (alpha >= 0 && alpha <= r0) {
// TODO this goes somewhere else if (clockwise === false) {
// DOM.container.dispatchEvent(new CustomEvent('stop')); DOM.addClass(div, 'touching');
return true;
} }
return (clockwise ? acc : { x: xx, y: yy });
} else if (alpha >= arc.t && alpha <= r1) {
if (clockwise === false) {
DOM.addClass(div, 'touching');
}
return (clockwise ? acc : { x: xx, y: yy });
} else {
if (clockwise === true) {
DOM.addClass(div, 'touching');
}
return (clockwise ? { x: xx, y: yy } : acc);
} }
return false;
} }
function transformMovementCircle(store) { DOM.removeClass(div, 'touching');
// TODO UPDATE ONLY IF THETA CHANGED - MUST HAVE PREVSTATE
const { circleX, circleY, radius, theta } = store.get();
const r = Math.abs(radius);
movementCircle.style.left = `${circleX - r}px`; return acc;
movementCircle.style.top = `${circleY - r}px`; }, { x: null, y: null });
movementCircle.style.height = `${2 * r}px`;
movementCircle.style.width = `${2 * r}px`;
movementCircle.style.borderRadius = `${r}px`;
} }
function transformParticle(store) { function transformParticle(store) {
const { clockwise, particleX, particleY, theta } = store.get(); const { arc, clockwise, particleX, particleY } = store.get();
const rad = clockwise ? Math.PI - theta : t360 - theta; const rad = clockwise ? Math.PI - arc.t : t360 - arc.t;
particle.style.left = `${particleX}px`; particle.style.left = `${particleX}px`;
particle.style.top = `${particleY}px`; particle.style.top = `${particleY}px`;
@ -137,17 +137,15 @@ function transformParticle(store) {
function transformVisionGrid(store) { function transformVisionGrid(store) {
const { const {
circleX, arc,
circleY,
clockwise, clockwise,
particleX, particleX,
particleY, particleY,
radius, radius,
theta
} = store.get(); } = store.get();
const r0 = Math.min(theta, theta - Math.PI); const r0 = Math.min(arc.t, arc.t - Math.PI);
const r1 = Math.max(theta, theta + Math.PI); const r1 = Math.max(arc.t, arc.t + Math.PI);
const gridX = particleX - particleX % 5; const gridX = particleX - particleX % 5;
const gridY = particleY - particleY % 5; const gridY = particleY - particleY % 5;
@ -155,10 +153,13 @@ function transformVisionGrid(store) {
visionGridPoints.forEach(({ x, y, alpha, div }, i) => { visionGridPoints.forEach(({ x, y, alpha, div }, i) => {
if (alpha >= 0 && alpha <= r0) { if (alpha >= 0 && alpha <= r0) {
div.style.display = (clockwise ? 'none' : 'block'); div.style.display = (clockwise ? 'none' : 'block');
} else if (alpha >= theta && alpha <= r1) { // div.className = (clockwise ? 'anim3-dot removed' : 'anim3-dot');
} else if (alpha >= arc.t && alpha <= r1) {
div.style.display = (clockwise ? 'none' : 'block'); div.style.display = (clockwise ? 'none' : 'block');
// div.className = (clockwise ? 'anim3-dot removed' : 'anim3-dot');
} else { } else {
div.style.display = (clockwise ? 'block' : 'none'); div.style.display = (clockwise ? 'block' : 'none');
// div.className = (clockwise ? 'anim3-dot' : 'anim3-dot removed');
} }
div.style.left = `${x + gridX}px`; div.style.left = `${x + gridX}px`;
@ -168,6 +169,7 @@ function transformVisionGrid(store) {
function calculateVisionGridPoints() { function calculateVisionGridPoints() {
const gridSize = 5; const gridSize = 5;
const visionRadius = 50;
const squareGrid = []; const squareGrid = [];
for (let x = -visionRadius; x <= visionRadius; x += gridSize) { for (let x = -visionRadius; x <= visionRadius; x += gridSize) {
@ -217,18 +219,19 @@ function reset() {
} }
const store = new Store({ const store = new Store({
arc: {
r: Math.round(Math.random() * 200) + 100,
t: Math.random() * t360,
x: 300,
y: 300,
},
clockwise: false, clockwise: false,
interval: 10,
circleX: 300,
circleY: 300,
radius: 270,
theta: Math.PI * 3 / 4
}); });
move(store); move(store);
transformParticle(store); transformParticle(store);
transformMovementCircle(store); // transformMovementCircle(store);
transformVisionGrid(store); transformVisionGrid(store);
DOM.container.appendChild(particle); DOM.container.appendChild(particle);
@ -256,11 +259,11 @@ function init() {
} }
const stop$ = Rx.Observable.fromEvent(DOM.container, 'stop'); const stop$ = Rx.Observable.fromEvent(DOM.container, 'stop');
const fps$ = Rx.Observable.interval(1000 / 32) const fps$ = Rx.Observable.interval(1000 / 256)
.map(_ => store) .map(_ => store)
.take(300) // .take(300)
// .take(15) // .take(15)
// .takeUntil(stop$); console.error("CLICK TO STOP"); .takeUntil(stop$); console.error("CLICK TO STOP");
const click$ = Rx.Observable.fromEvent(DOM.container, 'click'); const click$ = Rx.Observable.fromEvent(DOM.container, 'click');
click$.subscribe(() => { click$.subscribe(() => {
@ -269,8 +272,8 @@ function init() {
fps$.subscribe(move); fps$.subscribe(move);
fps$.subscribe(transformParticle); fps$.subscribe(transformParticle);
fps$.subscribe(transformMovementCircle);
fps$.subscribe(transformVisionGrid); fps$.subscribe(transformVisionGrid);
// fps$.subscribe(transformMovementCircle);
}; };
const Animation3 = Object.assign({}, AnimationBase, { init, reset }); const Animation3 = Object.assign({}, AnimationBase, { init, reset });

@ -6379,8 +6379,10 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
// number of frames have emitted. A smoothstep cubic curve was considered, but maintaining consistent entry and exit angles will affect // number of frames have emitted. A smoothstep cubic curve was considered, but maintaining consistent entry and exit angles will affect
// performance for large particle counts. // performance for large particle counts.
// This algorithm travels a random period of time around a random arc.
// If a wall is detected, a 180-degree turn is executed.
var speed = 4; var speed = 4;
var visionRadius = 50;
var grid = {}; var grid = {};
var t45 = Math.PI / 4; var t45 = Math.PI / 4;
var t90 = Math.PI / 2; var t90 = Math.PI / 2;
@ -6390,9 +6392,6 @@ var t360 = Math.PI * 2;
var movementCircle = document.createElement('div'); var movementCircle = document.createElement('div');
movementCircle.className = 'anim3-movement-circle'; movementCircle.className = 'anim3-movement-circle';
var visionGrid = document.createElement('div');
visionGrid.className = 'anim3-vision-grid';
var particle = document.createElement('div'); var particle = document.createElement('div');
particle.className = 'anim3-particle'; particle.className = 'anim3-particle';
@ -6400,118 +6399,116 @@ var visionGridPoints = calculateVisionGridPoints();
function move(store) { function move(store) {
var _store$get = store.get(), var _store$get = store.get(),
arc = _store$get.arc,
clockwise = _store$get.clockwise, clockwise = _store$get.clockwise,
interval = _store$get.interval,
circleX = _store$get.circleX,
circleY = _store$get.circleY,
particleX = _store$get.particleX, particleX = _store$get.particleX,
particleY = _store$get.particleY, particleY = _store$get.particleY;
radius = _store$get.radius,
theta = _store$get.theta;
// Separation, alignment, cohesion
// if (detectWall(store) && radius !== 20) {
// // IF SEEING A WALL: tight 180
// const radius0 = radius;
// radius = 20;
// interval = Math.PI * 20 / speed;
// circleX -= (radius - radius0) * Math.cos(theta);
// circleY += (radius - radius0) * Math.sin(theta);
// } else
if (interval <= 0) {
var radius0 = radius;
interval = Math.round(Math.random() * 10) + 50;
radius = Math.round(Math.random() * 200) + 50;
if (Math.random() < 0.5) {
clockwise = !clockwise;
theta = (theta + Math.PI) % t360;
circleX -= (radius + radius0) * Math.cos(theta);
circleY += (radius + radius0) * Math.sin(theta);
} else {
circleX -= (radius - radius0) * Math.cos(theta);
circleY += (radius - radius0) * Math.sin(theta);
}
}
interval -= 1; var delta = speed / arc.r;
arc.t += clockwise ? -delta : +delta;
arc.t = arc.t > 0 ? arc.t % t360 : t360 - arc.t;
var delta = speed / radius; var wall = detectWall(store);
theta += clockwise ? -delta : +delta;
theta = theta > 0 ? theta % t360 : t360 - theta;
particleX = circleX + radius * Math.cos(theta); if (wall.x !== null) {
particleY = circleY - radius * Math.sin(theta); // console.warn(wall.x, wall.y, particleX, particleY)
var x = wall.x - particleX;
var y = wall.y - particleY;
var v = Math.atan((particleY - wall.y) / (particleX - wall.x));
arc = modifyArc(arc, 40);
} else {
arc = modifyArc(arc, 400);
}
particleX = arc.x + arc.r * Math.cos(arc.t);
particleY = arc.y - arc.r * Math.sin(arc.t);
store.set({ store.set({
clockwise: clockwise, arc: arc,
interval: interval,
circleX: circleX,
circleY: circleY,
particleX: particleX, particleX: particleX,
particleY: particleY, particleY: particleY
radius: radius,
theta: theta
}); });
} }
// generate next arc:
// starting point will be locked
// starting angle will be locked
// therefore tangential
function modifyArc(arc, newRadius) {
var r0 = arc.r;
var r1 = newRadius;
arc.x -= (r1 - r0) * Math.cos(arc.t);
arc.y += (r1 - r0) * Math.sin(arc.t);
arc.r = r1;
return arc;
}
function changeDirection(arc) {
// clockwise = !clockwise;
// theta = (theta + Math.PI) % t360;
// circleX -= (radius + radius0) * Math.cos(theta);
// circleY += (radius + radius0) * Math.sin(theta);
}
function detectWall(store) { function detectWall(store) {
var len = visionGridPoints.length; var len = visionGridPoints.length;
var _store$get2 = store.get(), var _store$get2 = store.get(),
arc = _store$get2.arc,
clockwise = _store$get2.clockwise,
particleX = _store$get2.particleX, particleX = _store$get2.particleX,
particleY = _store$get2.particleY; particleY = _store$get2.particleY;
var r0 = Math.min(arc.t, arc.t - Math.PI);
var r1 = Math.max(arc.t, arc.t + Math.PI);
var gridX = particleX - particleX % 5; var gridX = particleX - particleX % 5;
var gridY = particleY - particleY % 5; var gridY = particleY - particleY % 5;
for (var i = 0; i < len; i++) { return visionGridPoints.reduce(function (acc, _ref) {
var _visionGridPoints$i = visionGridPoints[i], var div = _ref.div,
x = _visionGridPoints$i.x, x = _ref.x,
y = _visionGridPoints$i.y; y = _ref.y,
alpha = _ref.alpha;
var xx = x + gridX; var xx = x + gridX;
var yy = y + gridY; var yy = gridY - y;
if (grid[xx] && grid[xx][yy] && grid[xx][yy].type === 'wall') { if (grid[xx] && grid[xx][yy] && grid[xx][yy].type === 'wall') {
console.warn("Wall detected", xx, yy); if (alpha >= 0 && alpha <= r0) {
// TODO this goes somewhere else if (clockwise === false) {
// DOM.container.dispatchEvent(new CustomEvent('stop')); _dom2.default.addClass(div, 'touching');
return true;
} }
return clockwise ? acc : { x: xx, y: yy };
} else if (alpha >= arc.t && alpha <= r1) {
if (clockwise === false) {
_dom2.default.addClass(div, 'touching');
}
return clockwise ? acc : { x: xx, y: yy };
} else {
if (clockwise === true) {
_dom2.default.addClass(div, 'touching');
}
return clockwise ? { x: xx, y: yy } : acc;
} }
return false;
} }
function transformMovementCircle(store) { _dom2.default.removeClass(div, 'touching');
// TODO UPDATE ONLY IF THETA CHANGED - MUST HAVE PREVSTATE
var _store$get3 = store.get(),
circleX = _store$get3.circleX,
circleY = _store$get3.circleY,
radius = _store$get3.radius,
theta = _store$get3.theta;
var r = Math.abs(radius);
movementCircle.style.left = circleX - r + 'px'; return acc;
movementCircle.style.top = circleY - r + 'px'; }, { x: null, y: null });
movementCircle.style.height = 2 * r + 'px';
movementCircle.style.width = 2 * r + 'px';
movementCircle.style.borderRadius = r + 'px';
} }
function transformParticle(store) { function transformParticle(store) {
var _store$get4 = store.get(), var _store$get3 = store.get(),
clockwise = _store$get4.clockwise, arc = _store$get3.arc,
particleX = _store$get4.particleX, clockwise = _store$get3.clockwise,
particleY = _store$get4.particleY, particleX = _store$get3.particleX,
theta = _store$get4.theta; particleY = _store$get3.particleY;
var rad = clockwise ? Math.PI - theta : t360 - theta; var rad = clockwise ? Math.PI - arc.t : t360 - arc.t;
particle.style.left = particleX + 'px'; particle.style.left = particleX + 'px';
particle.style.top = particleY + 'px'; particle.style.top = particleY + 'px';
@ -6519,33 +6516,34 @@ function transformParticle(store) {
} }
function transformVisionGrid(store) { function transformVisionGrid(store) {
var _store$get5 = store.get(), var _store$get4 = store.get(),
circleX = _store$get5.circleX, arc = _store$get4.arc,
circleY = _store$get5.circleY, clockwise = _store$get4.clockwise,
clockwise = _store$get5.clockwise, particleX = _store$get4.particleX,
particleX = _store$get5.particleX, particleY = _store$get4.particleY,
particleY = _store$get5.particleY, radius = _store$get4.radius;
radius = _store$get5.radius,
theta = _store$get5.theta; var r0 = Math.min(arc.t, arc.t - Math.PI);
var r1 = Math.max(arc.t, arc.t + Math.PI);
var r0 = Math.min(theta, theta - Math.PI);
var r1 = Math.max(theta, theta + Math.PI);
var gridX = particleX - particleX % 5; var gridX = particleX - particleX % 5;
var gridY = particleY - particleY % 5; var gridY = particleY - particleY % 5;
visionGridPoints.forEach(function (_ref, i) { visionGridPoints.forEach(function (_ref2, i) {
var x = _ref.x, var x = _ref2.x,
y = _ref.y, y = _ref2.y,
alpha = _ref.alpha, alpha = _ref2.alpha,
div = _ref.div; div = _ref2.div;
if (alpha >= 0 && alpha <= r0) { if (alpha >= 0 && alpha <= r0) {
div.style.display = clockwise ? 'none' : 'block'; div.style.display = clockwise ? 'none' : 'block';
} else if (alpha >= theta && alpha <= r1) { // div.className = (clockwise ? 'anim3-dot removed' : 'anim3-dot');
} else if (alpha >= arc.t && alpha <= r1) {
div.style.display = clockwise ? 'none' : 'block'; div.style.display = clockwise ? 'none' : 'block';
// div.className = (clockwise ? 'anim3-dot removed' : 'anim3-dot');
} else { } else {
div.style.display = clockwise ? 'block' : 'none'; div.style.display = clockwise ? 'block' : 'none';
// div.className = (clockwise ? 'anim3-dot' : 'anim3-dot removed');
} }
div.style.left = x + gridX + 'px'; div.style.left = x + gridX + 'px';
@ -6555,6 +6553,7 @@ function transformVisionGrid(store) {
function calculateVisionGridPoints() { function calculateVisionGridPoints() {
var gridSize = 5; var gridSize = 5;
var visionRadius = 50;
var squareGrid = []; var squareGrid = [];
for (var x = -visionRadius; x <= visionRadius; x += gridSize) { for (var x = -visionRadius; x <= visionRadius; x += gridSize) {
@ -6604,18 +6603,19 @@ function reset() {
} }
var store = new _store2.default({ var store = new _store2.default({
clockwise: false, arc: {
interval: 10, r: Math.round(Math.random() * 200) + 100,
circleX: 300, t: Math.random() * t360,
circleY: 300, x: 300,
radius: 270, y: 300
theta: Math.PI * 3 / 4 },
clockwise: false
}); });
move(store); move(store);
transformParticle(store); transformParticle(store);
transformMovementCircle(store); // transformMovementCircle(store);
transformVisionGrid(store); transformVisionGrid(store);
_dom2.default.container.appendChild(particle); _dom2.default.container.appendChild(particle);
@ -6643,11 +6643,12 @@ function init() {
} }
var stop$ = _rxjs2.default.Observable.fromEvent(_dom2.default.container, 'stop'); var stop$ = _rxjs2.default.Observable.fromEvent(_dom2.default.container, 'stop');
var fps$ = _rxjs2.default.Observable.interval(1000 / 32).map(function (_) { var fps$ = _rxjs2.default.Observable.interval(1000 / 256).map(function (_) {
return store; return store;
}).take(300); })
// .take(300)
// .take(15) // .take(15)
// .takeUntil(stop$); console.error("CLICK TO STOP"); .takeUntil(stop$);console.error("CLICK TO STOP");
var click$ = _rxjs2.default.Observable.fromEvent(_dom2.default.container, 'click'); var click$ = _rxjs2.default.Observable.fromEvent(_dom2.default.container, 'click');
click$.subscribe(function () { click$.subscribe(function () {
@ -6656,8 +6657,8 @@ function init() {
fps$.subscribe(move); fps$.subscribe(move);
fps$.subscribe(transformParticle); fps$.subscribe(transformParticle);
fps$.subscribe(transformMovementCircle);
fps$.subscribe(transformVisionGrid); fps$.subscribe(transformVisionGrid);
// fps$.subscribe(transformMovementCircle);
}; };
var Animation3 = Object.assign({}, _animation2.default, { init: init, reset: reset }); var Animation3 = Object.assign({}, _animation2.default, { init: init, reset: reset });

Loading…
Cancel
Save