import { ENTITIES, RAD } from './enums'; import Random from './random'; const Arc = { create: function(bounds, grid) { let arc = { centerX: Random.num(0, bounds.width), centerY: Random.num(0, bounds.height), clockwise: Random.bool(), endX: 0, endY: 0, length: Random.num(RAD.t90, RAD.t360), radius: Random.num(100, 200), theta: Random.num(RAD.t90, RAD.t360) }; arc.cosTheta = Math.cos(arc.theta); arc.sinTheta = Math.sin(arc.theta); arc.endX = arc.centerX + arc.radius * arc.cosTheta; arc.endY = arc.centerY - arc.radius * arc.sinTheta; arc = Arc.overflow(arc, bounds); // If starting in a hazard, recurse. if (grid.getPoint({ x: arc.endX, y: arc.endY, type: ENTITIES.HAZARD })) { arc = Arc.create(bounds, grid); } return arc; }, step: function(arc, bounds, speed) { // Ensure constant velocity and theta between 0 and 2π. const delta = speed / arc.radius; arc.length -= delta; arc.theta += (arc.clockwise ? -delta : +delta); arc.theta = (arc.theta > 0 ? arc.theta % RAD.t360 : RAD.t360 + arc.theta); arc.cosTheta = Math.cos(arc.theta); arc.sinTheta = Math.sin(arc.theta); arc.endX = arc.centerX + arc.radius * arc.cosTheta; arc.endY = arc.centerY - arc.radius * arc.sinTheta; // Overflow. arc = Arc.overflow(arc, bounds); return arc; }, randomize: function(arc) { arc.length = Random.num(RAD.t90, RAD.t360); arc = Arc.changeRadius(arc, Random.num(100, 200)); if (Random.bool(0.8)) { arc = Arc.reverse(arc); } return arc; }, overflow: function(arc, bounds) { if (arc.endX < 0) { arc.endX += bounds.width; arc.centerX += bounds.width } else if (arc.endX > bounds.width) { arc.endX -= bounds.width; arc.centerX -= bounds.width } if (arc.endY < 0) { arc.endY += bounds.height; arc.centerY += bounds.height } else if (arc.endY > bounds.height) { arc.endY -= bounds.height; arc.centerY -= bounds.height } return arc; }, changeRadius: function(arc, newRadius) { const r0 = arc.radius; const r1 = newRadius; // Moves arc center to new radius while keeping theta constant. arc.centerX -= (r1 - r0) * arc.cosTheta; arc.centerY += (r1 - r0) * arc.sinTheta; arc.radius = r1; return arc; }, reverse: function(arc) { arc.clockwise = !arc.clockwise; arc.theta = (arc.theta + RAD.t180) % RAD.t360; arc.cosTheta = Math.cos(arc.theta); arc.sinTheta = Math.sin(arc.theta); arc.centerX -= (2 * arc.radius) * arc.cosTheta; arc.centerY += (2 * arc.radius) * arc.sinTheta; return arc; }, follow: function(arc, arcToFollow) { if (arc.clockwise !== arcToFollow.clockwise) { arc = Arc.reverse(arc); } if (Math.abs(arc.theta - arcToFollow.theta) > 0.2) { arc = Arc.changeRadius(arc, 50); } else { arc = Arc.changeRadius(arc, arcToFollow.radius); } return arc; }, evade: function(arc) { arc = Arc.changeRadius(arc, 20); arc.length = 1; return arc; } } export default Arc;