From 905921ceb0a6b558dc5124c456f4953c9caa4bf2 Mon Sep 17 00:00:00 2001 From: Ben Burlingham Date: Fri, 28 Jul 2017 06:04:53 -0700 Subject: [PATCH] Wall avoidance algorithm finalized. --- css/animation3.scss | 6 +- css/style.css | 4 +- index.html | 2 +- js/animation3-ORIGINAL.js | 279 ++++++++++++++++++++++++++++++++++++++ js/animation3.js | 173 +++++++++++------------ js/bundle.js | 225 +++++++++++++++--------------- 6 files changed, 489 insertions(+), 200 deletions(-) create mode 100644 js/animation3-ORIGINAL.js diff --git a/css/animation3.scss b/css/animation3.scss index 03a86e8..413b813 100644 --- a/css/animation3.scss +++ b/css/animation3.scss @@ -71,6 +71,10 @@ &.removed { // background: purple; - background: yellow; + background: green; + } + + &.touching { + outline: 2px solid yellow; } } diff --git a/css/style.css b/css/style.css index 3e076e5..5977150 100644 --- a/css/style.css +++ b/css/style.css @@ -102,7 +102,9 @@ body { width: 2px; z-index: 99; } .anim3-dot.removed { - background: yellow; } + background: green; } + .anim3-dot.touching { + outline: 2px solid yellow; } .anim3-particle { background: url(../res/seahorse.svg) no-repeat center top #aaa; background-size: 20px 20px; diff --git a/index.html b/index.html index dbc9251..7cb2d61 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@

Dust

-

Swarm behavior studies with RxJs

+

Studying AI movement along arcs with RxJs


diff --git a/js/animation3-ORIGINAL.js b/js/animation3-ORIGINAL.js new file mode 100644 index 0000000..65c7a1a --- /dev/null +++ b/js/animation3-ORIGINAL.js @@ -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; diff --git a/js/animation3.js b/js/animation3.js index 766d0a4..49c3c64 100644 --- a/js/animation3.js +++ b/js/animation3.js @@ -7,13 +7,15 @@ // 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; @@ -23,9 +25,6 @@ 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'; @@ -33,102 +32,103 @@ const visionGridPoints = calculateVisionGridPoints(); function move(store) { let { + arc, clockwise, - interval, - circleX, - circleY, particleX, particleY, - radius, - theta } = store.get(); - // 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) { - 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); - } - } + const delta = speed / arc.r; + arc.t += (clockwise ? -delta : +delta); + arc.t = (arc.t > 0 ? arc.t % t360 : t360 - arc.t); - interval -= 1; + const wall = detectWall(store); - const delta = speed / radius; - theta += (clockwise ? -delta : +delta); - theta = (theta > 0 ? theta % t360 : t360 - theta); + if (wall.x !== null) { + // console.warn(wall.x, wall.y, particleX, particleY) + 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); - particleY = circleY - radius * Math.sin(theta); + particleX = arc.x + arc.r * Math.cos(arc.t); + particleY = arc.y - arc.r * Math.sin(arc.t); store.set({ - clockwise, - interval, - circleX, - circleY, + arc, particleX, 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) { 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 gridY = particleY - particleY % 5; - for (let i = 0; i < len; i++) { - const { x, y } = visionGridPoints[i]; + return visionGridPoints.reduce((acc, { div, x, y, alpha }) => { const xx = x + gridX; - const yy = y + gridY; + const yy = gridY - y; 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; + if (alpha >= 0 && alpha <= r0) { + if (clockwise === false) { + DOM.addClass(div, 'touching'); + } + 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; -} + DOM.removeClass(div, 'touching'); -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`; + return acc; + }, { x: null, y: null }); } function transformParticle(store) { - const { clockwise, particleX, particleY, theta } = store.get(); - const rad = clockwise ? Math.PI - theta : t360 - theta; + const { arc, clockwise, particleX, particleY } = store.get(); + const rad = clockwise ? Math.PI - arc.t : t360 - arc.t; particle.style.left = `${particleX}px`; particle.style.top = `${particleY}px`; @@ -137,17 +137,15 @@ function transformParticle(store) { function transformVisionGrid(store) { const { - circleX, - circleY, + arc, clockwise, particleX, particleY, radius, - theta } = store.get(); - const r0 = Math.min(theta, theta - Math.PI); - const r1 = Math.max(theta, theta + Math.PI); + 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 gridY = particleY - particleY % 5; @@ -155,10 +153,13 @@ function transformVisionGrid(store) { 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.className = (clockwise ? 'anim3-dot removed' : 'anim3-dot'); + } else if (alpha >= arc.t && alpha <= r1) { div.style.display = (clockwise ? 'none' : 'block'); + // div.className = (clockwise ? 'anim3-dot removed' : 'anim3-dot'); } else { div.style.display = (clockwise ? 'block' : 'none'); + // div.className = (clockwise ? 'anim3-dot' : 'anim3-dot removed'); } div.style.left = `${x + gridX}px`; @@ -168,6 +169,7 @@ function transformVisionGrid(store) { function calculateVisionGridPoints() { const gridSize = 5; + const visionRadius = 50; const squareGrid = []; for (let x = -visionRadius; x <= visionRadius; x += gridSize) { @@ -217,18 +219,19 @@ function reset() { } const store = new Store({ + arc: { + r: Math.round(Math.random() * 200) + 100, + t: Math.random() * t360, + x: 300, + y: 300, + }, clockwise: false, - interval: 10, - circleX: 300, - circleY: 300, - radius: 270, - theta: Math.PI * 3 / 4 }); move(store); transformParticle(store); - transformMovementCircle(store); + // transformMovementCircle(store); transformVisionGrid(store); DOM.container.appendChild(particle); @@ -256,11 +259,11 @@ function init() { } const stop$ = Rx.Observable.fromEvent(DOM.container, 'stop'); - const fps$ = Rx.Observable.interval(1000 / 32) + const fps$ = Rx.Observable.interval(1000 / 256) .map(_ => store) - .take(300) + // .take(300) // .take(15) - // .takeUntil(stop$); console.error("CLICK TO STOP"); + .takeUntil(stop$); console.error("CLICK TO STOP"); const click$ = Rx.Observable.fromEvent(DOM.container, 'click'); click$.subscribe(() => { @@ -269,8 +272,8 @@ function init() { fps$.subscribe(move); fps$.subscribe(transformParticle); - fps$.subscribe(transformMovementCircle); fps$.subscribe(transformVisionGrid); + // fps$.subscribe(transformMovementCircle); }; const Animation3 = Object.assign({}, AnimationBase, { init, reset }); diff --git a/js/bundle.js b/js/bundle.js index 2311e00..0d0afc6 100644 --- a/js/bundle.js +++ b/js/bundle.js @@ -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 // 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 visionRadius = 50; var grid = {}; var t45 = Math.PI / 4; var t90 = Math.PI / 2; @@ -6390,9 +6392,6 @@ var t360 = Math.PI * 2; var movementCircle = document.createElement('div'); movementCircle.className = 'anim3-movement-circle'; -var visionGrid = document.createElement('div'); -visionGrid.className = 'anim3-vision-grid'; - var particle = document.createElement('div'); particle.className = 'anim3-particle'; @@ -6400,118 +6399,116 @@ var visionGridPoints = calculateVisionGridPoints(); function move(store) { var _store$get = store.get(), + arc = _store$get.arc, clockwise = _store$get.clockwise, - interval = _store$get.interval, - circleX = _store$get.circleX, - circleY = _store$get.circleY, particleX = _store$get.particleX, - 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); - } - } + particleY = _store$get.particleY; - 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; - theta += clockwise ? -delta : +delta; - theta = theta > 0 ? theta % t360 : t360 - theta; + var wall = detectWall(store); - particleX = circleX + radius * Math.cos(theta); - particleY = circleY - radius * Math.sin(theta); + if (wall.x !== null) { + // 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({ - clockwise: clockwise, - interval: interval, - circleX: circleX, - circleY: circleY, + arc: arc, particleX: particleX, - particleY: particleY, - radius: radius, - theta: theta + particleY: particleY }); } +// 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) { var len = visionGridPoints.length; var _store$get2 = store.get(), + arc = _store$get2.arc, + clockwise = _store$get2.clockwise, particleX = _store$get2.particleX, 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 gridY = particleY - particleY % 5; - for (var i = 0; i < len; i++) { - var _visionGridPoints$i = visionGridPoints[i], - x = _visionGridPoints$i.x, - y = _visionGridPoints$i.y; + return visionGridPoints.reduce(function (acc, _ref) { + var div = _ref.div, + x = _ref.x, + y = _ref.y, + alpha = _ref.alpha; var xx = x + gridX; - var yy = y + gridY; + var yy = gridY - y; 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; + if (alpha >= 0 && alpha <= r0) { + if (clockwise === false) { + _dom2.default.addClass(div, 'touching'); + } + 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; -} + _dom2.default.removeClass(div, 'touching'); -function transformMovementCircle(store) { - // 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'; - movementCircle.style.top = circleY - r + 'px'; - movementCircle.style.height = 2 * r + 'px'; - movementCircle.style.width = 2 * r + 'px'; - movementCircle.style.borderRadius = r + 'px'; + return acc; + }, { x: null, y: null }); } function transformParticle(store) { - var _store$get4 = store.get(), - clockwise = _store$get4.clockwise, - particleX = _store$get4.particleX, - particleY = _store$get4.particleY, - theta = _store$get4.theta; + var _store$get3 = store.get(), + arc = _store$get3.arc, + clockwise = _store$get3.clockwise, + particleX = _store$get3.particleX, + 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.top = particleY + 'px'; @@ -6519,33 +6516,34 @@ function transformParticle(store) { } function transformVisionGrid(store) { - var _store$get5 = store.get(), - circleX = _store$get5.circleX, - circleY = _store$get5.circleY, - clockwise = _store$get5.clockwise, - particleX = _store$get5.particleX, - particleY = _store$get5.particleY, - radius = _store$get5.radius, - theta = _store$get5.theta; - - var r0 = Math.min(theta, theta - Math.PI); - var r1 = Math.max(theta, theta + Math.PI); + var _store$get4 = store.get(), + arc = _store$get4.arc, + clockwise = _store$get4.clockwise, + particleX = _store$get4.particleX, + particleY = _store$get4.particleY, + radius = _store$get4.radius; + + 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 gridY = particleY - particleY % 5; - visionGridPoints.forEach(function (_ref, i) { - var x = _ref.x, - y = _ref.y, - alpha = _ref.alpha, - div = _ref.div; + visionGridPoints.forEach(function (_ref2, i) { + var x = _ref2.x, + y = _ref2.y, + alpha = _ref2.alpha, + div = _ref2.div; if (alpha >= 0 && alpha <= r0) { 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.className = (clockwise ? 'anim3-dot removed' : 'anim3-dot'); } else { div.style.display = clockwise ? 'block' : 'none'; + // div.className = (clockwise ? 'anim3-dot' : 'anim3-dot removed'); } div.style.left = x + gridX + 'px'; @@ -6555,6 +6553,7 @@ function transformVisionGrid(store) { function calculateVisionGridPoints() { var gridSize = 5; + var visionRadius = 50; var squareGrid = []; for (var x = -visionRadius; x <= visionRadius; x += gridSize) { @@ -6604,18 +6603,19 @@ function reset() { } var store = new _store2.default({ - clockwise: false, - interval: 10, - circleX: 300, - circleY: 300, - radius: 270, - theta: Math.PI * 3 / 4 + arc: { + r: Math.round(Math.random() * 200) + 100, + t: Math.random() * t360, + x: 300, + y: 300 + }, + clockwise: false }); move(store); transformParticle(store); - transformMovementCircle(store); + // transformMovementCircle(store); transformVisionGrid(store); _dom2.default.container.appendChild(particle); @@ -6643,11 +6643,12 @@ function init() { } 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; - }).take(300); + }) + // .take(300) // .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'); click$.subscribe(function () { @@ -6656,8 +6657,8 @@ function init() { fps$.subscribe(move); fps$.subscribe(transformParticle); - fps$.subscribe(transformMovementCircle); fps$.subscribe(transformVisionGrid); + // fps$.subscribe(transformMovementCircle); }; var Animation3 = Object.assign({}, _animation2.default, { init: init, reset: reset });