-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathtrajectory.js
107 lines (98 loc) · 3.03 KB
/
trajectory.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import { GRAVITY, LANDER_HEIGHT, CRASH_ANGLE } from "../helpers/constants.js";
export const drawTrajectory = (
state,
currentPosition,
currentAngle,
currentVelocity,
currentRotationVelocity
) => {
const CTX = state.get("CTX");
const canvasWidth = state.get("canvasWidth");
const canvasHeight = state.get("canvasHeight");
const terrainLandingData = state.get("terrain").getLandingData();
const scaleFactor = state.get("scaleFactor");
// Iterate on ballistic properties until hitting the ground, and push these
// points into an array to draw later
const generateTrajectoryPoints = () => {
let projectedXPosition = currentPosition.x;
let projectedYPosition = currentPosition.y;
let projectedYVelocity = currentVelocity.y;
let projectedAngle = currentAngle;
const segments = [];
while (
projectedYPosition <= canvasHeight &&
projectedXPosition <= canvasWidth &&
projectedXPosition >= 0 &&
!CTX.isPointInPath(
terrainLandingData.terrainPath2D,
projectedXPosition * scaleFactor,
projectedYPosition * scaleFactor
)
) {
segments.push({ x: projectedXPosition, y: projectedYPosition });
projectedYPosition = Math.min(
projectedYPosition + projectedYVelocity,
canvasHeight
);
projectedXPosition += currentVelocity.x;
projectedAngle += (Math.PI / 180) * currentRotationVelocity;
projectedYVelocity += GRAVITY;
}
return [
segments,
{
projectedXPosition,
projectedYPosition,
projectedYVelocity,
projectedAngle,
},
];
};
const [segments, lastSegment] = generateTrajectoryPoints();
if (segments.length > 20) {
CTX.save();
CTX.globalAlpha = 0.4;
const gradientLength = Math.floor(segments.length / 2);
segments.forEach(({ x, y }, index) => {
if (segments.length > index + 1) {
const nextSegment = segments[index + 1];
CTX.beginPath();
CTX.moveTo(x, y);
CTX.lineTo(nextSegment.x, nextSegment.y);
CTX.strokeStyle = `rgba(255, 255, 255, ${index / gradientLength})`;
CTX.stroke();
}
});
// Draw landing zone angle indicator
if (
lastSegment.projectedXPosition > 0 &&
lastSegment.projectedXPosition < canvasWidth
) {
const arrowSize = Math.max(
Math.min(lastSegment.projectedYVelocity * 4, 20),
2
);
const arrowLength = Math.max(
Math.min(lastSegment.projectedYVelocity * 30, 60),
5
);
CTX.globalAlpha = 1;
CTX.strokeStyle = "#fff";
CTX.translate(
lastSegment.projectedXPosition,
lastSegment.projectedYPosition
);
CTX.rotate(lastSegment.projectedAngle + Math.PI);
CTX.beginPath();
CTX.moveTo(0, 0);
CTX.lineTo(0, arrowLength);
CTX.lineTo(-arrowSize, arrowLength);
CTX.lineTo(0, arrowLength + arrowSize);
CTX.lineTo(arrowSize, arrowLength);
CTX.lineTo(0, arrowLength);
CTX.closePath();
CTX.stroke();
}
CTX.restore();
}
};