You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
4.5 KiB
169 lines
4.5 KiB
import { ENTITIES, RAD } from './enums';
|
|
import Random from './random';
|
|
|
|
// "How much of movement is in the correct direction"
|
|
const rigidity = 0.9;
|
|
// "How close to the leader is enough"
|
|
const sensitivity = 30;
|
|
|
|
const Arc = {
|
|
create: function(bounds) {
|
|
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),
|
|
prevEndX: 0,
|
|
prevEndY: 0,
|
|
radius: Random.num(100, 200),
|
|
speed: 0,
|
|
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);
|
|
|
|
return arc;
|
|
},
|
|
|
|
step: function(arc, bounds) {
|
|
// Ensure constant velocity and theta between 0 and 2π.
|
|
const delta = arc.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.prevEndX = arc.endX;
|
|
arc.prevEndY = arc.endY;
|
|
|
|
arc.endX = arc.centerX + arc.radius * arc.cosTheta;
|
|
arc.endY = arc.centerY - arc.radius * arc.sinTheta;
|
|
|
|
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;
|
|
},
|
|
|
|
changeSpeed: function(arc, newSpeed) {
|
|
arc.speed = newSpeed * 1;
|
|
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) {
|
|
const prevD = Math.pow(
|
|
Math.pow(arcToFollow.endX - arc.prevEndX, 2) +
|
|
Math.pow(arcToFollow.endY - arc.prevEndY, 2)
|
|
, 0.5);
|
|
|
|
const currD = Math.pow(
|
|
Math.pow(arcToFollow.endX - arc.endX, 2) +
|
|
Math.pow(arcToFollow.endY - arc.endY, 2)
|
|
, 0.5);
|
|
|
|
const rigidityCoeff = (prevD - currD) / arc.speed;
|
|
|
|
if (currD < sensitivity) {
|
|
arc = (arc.clockwise !== arcToFollow.clockwise ? Arc.reverse(arc) : arc);
|
|
arc = Arc.changeRadius(arc, arcToFollow.radius);
|
|
|
|
if (arc.speed > arcToFollow.speed) {
|
|
arc = Arc.changeSpeed(arc, arc.speed - 1);
|
|
} if (arc.speed < arcToFollow.speed) {
|
|
arc = Arc.changeSpeed(arc, arc.speed + 1);
|
|
}
|
|
|
|
} else if (rigidityCoeff < rigidity) {
|
|
arc = Arc.changeRadius(arc, 20);
|
|
|
|
if (arc.speed > arcToFollow.speed - 1) {
|
|
arc = Arc.changeSpeed(arc, arc.speed - 1);
|
|
}
|
|
} else {
|
|
arc = Arc.changeRadius(arc, 4000);
|
|
|
|
if (arc.speed < (arcToFollow.speed + 2)) {
|
|
arc = Arc.changeSpeed(arc, arc.speed + 1);
|
|
}
|
|
}
|
|
|
|
return arc;
|
|
},
|
|
|
|
evade: function(arc) {
|
|
arc = Arc.changeRadius(arc, 20);
|
|
arc.length = 1;
|
|
|
|
return arc;
|
|
}
|
|
}
|
|
|
|
export default Arc;
|
|
|