Web Dev Solutions

Catalin Mititiuc

aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCatalin Mititiuc <webdevcat@proton.me>2024-04-26 12:14:24 -0700
committerCatalin Mititiuc <webdevcat@proton.me>2024-04-26 12:14:24 -0700
commit9d02591fac098f9f49eab33f7412da33a62be77e (patch)
tree47c69a4341b2ddb3df4d61f6ce369d55091fa852 /src/modules/game
parent93ef00d18016786ae3491b14c4098c63590e18b9 (diff)
More refactor of firing arc module
Diffstat (limited to 'src/modules/game')
-rw-r--r--src/modules/game/firingArc.js179
1 files changed, 96 insertions, 83 deletions
diff --git a/src/modules/game/firingArc.js b/src/modules/game/firingArc.js
index cbde0d4..6dfd8cb 100644
--- a/src/modules/game/firingArc.js
+++ b/src/modules/game/firingArc.js
@@ -23,6 +23,17 @@ const svgns = "http://www.w3.org/2000/svg",
let svg;
+class Point {
+ constructor(x = 0, y = 0) {
+ this.x = +x;
+ this.y = +y;
+ }
+
+ toString() {
+ return `${this.x},${this.y}`;
+ }
+}
+
function calculateAngle(xDiff, yDiff) {
yDiff = -yDiff;
let angle = Math.abs(Math.atan(yDiff / xDiff));
@@ -67,124 +78,127 @@ function edgePoint({ x: x1, y: y1 }, { x: x2, y: y2 }, { x: [minX, maxX], y: [mi
return new Point(...pointCoords);
}
-class Point {
- constructor(x = 0, y = 0) {
- this.x = +x;
- this.y = +y;
- }
-
- toString() {
- return `${this.x},${this.y}`;
- }
+function touchSameEdge({ x: x1, y: y1 }, { x: x2, y: y2 }) {
+ return x1 === x2 || y1 === y2;
}
-function position(e, firingArc, firingArcOutline, aimLine, grid) {
- // TODO: handle exactly horizontal and vertical lines?
-
- let pointer = new DOMPoint(e.clientX, e.clientY);
- let pointerPt = pointer.matrixTransform(grid.getScreenCTM().inverse());
+function shareValue({ x: x1, y: y1 }, { x: x2, y: y2 }) {
+ return x1 === x2 || y1 === y2;
+}
- let pivotPt = new Point(aimLine.getAttribute('x1'), aimLine.getAttribute('y1'));
+function touchOrthogonalEdges({ x: x1, y: y1 }, { x: x2, y: y2 }, bounds) {
+ return (bounds.x.includes(x1) && bounds.y.includes(y2)) || (bounds.y.includes(y1) && bounds.x.includes(x2));
+}
- let { x, y, width, height } = grid.getBBox();
+function getCornerPts({ x: [xMin, xMax], y: [yMin, yMax] }) {
+ const corners = [[xMin, yMin], [xMax, yMin], [xMax, yMax], [xMin, yMax]];
+ return corners.map(([x, y]) => new Point(x, y));
+}
- const bounds = {
+function getBounds({ x, y, width, height }) {
+ return {
x: [x, x + width],
y: [y, y + height]
- }
-
- let cornerPoints = [
- [x, y],
- [x + width, y],
- [x + width, y + height],
- [x, y + height]
- ].map(([x, y]) => new Point(x, y));
-
- let aimPt = edgePoint(pivotPt, pointerPt, bounds);
- aimLine.setAttributeNS(null, 'x2', aimPt.x);
- aimLine.setAttributeNS(null, 'y2', aimPt.y);
-
- let angle = calculateAngle(aimPt.x - pivotPt.x, aimPt.y - pivotPt.y);
- let arcAngle = arcSize[firingArc.dataset.size];
- let distance = Math.sqrt((aimPt.x - pivotPt.x) ** 2 + (aimPt.y - pivotPt.y) ** 2);
- let yDelta = distance * Math.cos(angle) * Math.tan(arcAngle);
- let xDelta = distance * Math.sin(angle) * Math.tan(arcAngle);
-
- let arcPt1 = new Point(aimPt.x - xDelta, aimPt.y - yDelta);
- let arcPt2 = new Point(aimPt.x + xDelta, aimPt.y + yDelta);
-
- arcPt1 = edgePoint(pivotPt, arcPt1, bounds);
- arcPt2 = edgePoint(pivotPt, arcPt2, bounds);
+ };
+}
- firingArcOutline.setAttributeNS(null, 'points', `${arcPt1} ${pivotPt} ${arcPt2}`);
+// which arcpt does aimpt share a value with?
+// if they share an x value, we will look for corner y value
+// if they share a y value, we will look for corner x value
+// is aim pt non-shared value greater or less than arcpt non-shared value?
+function findWhichTwoCorners(pt, bounds, ...pts) {
+ const ptVals = Object.values(pt),
+ sharedValPt = pts.find(({ x, y }) => ptVals.includes(x) || ptVals.includes(y));
- function touchSameEdge({ x: x1, y: y1 }, { x: x2, y: y2 }) {
- return x1 === x2 || y1 === y2;
+ if (!sharedValPt) {
+ return;
}
- function touchOrthogonalEdges({ x: x1, y: y1 }, { x: x2, y: y2 }) {
- return (bounds.x.includes(x1) && bounds.y.includes(y2)) || (bounds.y.includes(y1) && bounds.x.includes(x2));
- }
+ const nonSharedValKey = pt.x === sharedValPt.x ? 'y' : 'x';
+ let cornerVal;
- function shareValue({ x: x1, y: y1 }, { x: x2, y: y2 }) {
- return x1 === x2 || y1 === y2;
+ if (pt[nonSharedValKey] < sharedValPt[nonSharedValKey]) {
+ cornerVal = Math.min(...bounds[nonSharedValKey]);
+ } else {
+ cornerVal = Math.max(...bounds[nonSharedValKey]);
}
- // which arcpt does aimpt share a value with?
- // if they share an x value, we will look for corner y value
- // if they share a y value, we will look for corner x value
- // is aim pt non-shared value greater or less than arcpt non-shared value?
- function findWhichCorners(pt, ...pts) {
- const ptVals = Object.values(pt),
- sharedValPt = pts.find(({ x, y }) => ptVals.includes(x) || ptVals.includes(y));
-
- if (!sharedValPt) {
- return;
- }
-
- const nonSharedValKey = pt.x === sharedValPt.x ? 'x' : 'y';
- let cornerVal;
-
- if (pt[nonSharedValKey] < sharedValPt[nonSharedValKey]) {
- cornerVal = Math.min(...bounds[nonSharedValKey]);
- } else {
- cornerVal = Math.max(...bounds[nonSharedValKey]);
- }
+ return getCornerPts(bounds).filter(cp => cp[nonSharedValKey] === cornerVal);
+}
- return cornerPoints.filter(cp => cp[nonSharedValKey] === cornerVal);
- }
+function chooseCornerPoints(aimPt, arcPt1, arcPt2, bounds) {
+ const cornerPoints = getCornerPts(bounds);
let points;
if (touchSameEdge(arcPt1, arcPt2)) {
// 0-corner case
- points = [arcPt2, pivotPt, arcPt1];
- } else if (touchOrthogonalEdges(arcPt1, arcPt2)) {
+ points = [];
+ } else if (touchOrthogonalEdges(arcPt1, arcPt2, bounds)) {
if (touchSameEdge(aimPt, arcPt1) || touchSameEdge(aimPt, arcPt2)) {
// 1-corner case
let cp = cornerPoints.find(cp => shareValue(cp, arcPt1) && shareValue(cp, arcPt2));
- points = [arcPt2, pivotPt, arcPt1, cp];
+ points = [cp];
} else {
// 3-corner case
points = cornerPoints.filter(cp => !shareValue(cp, arcPt1) || !shareValue(cp, arcPt2));
- let index = points.findIndex(cp => shareValue(cp, arcPt2));
- points.splice(index + 1, 0, arcPt2, pivotPt, arcPt1);
}
} else {
if (touchSameEdge(aimPt, arcPt1) || touchSameEdge(aimPt, arcPt2)) {
// 2-corner case, aim and an arc point touch the same edge
- points = findWhichCorners(aimPt, arcPt1, arcPt2);
- let index = points.findIndex(cp => shareValue(cp, arcPt2));
- points.splice(index + 1, 0, arcPt2, pivotPt, arcPt1);
+ points = findWhichTwoCorners(aimPt, bounds, arcPt1, arcPt2);
} else {
// 2-corner case, aim and both arc points all touch different edges
points = cornerPoints.filter(cp => shareValue(cp, aimPt) || shareValue(cp, aimPt));
- let index = points.findIndex(cp => shareValue(cp, arcPt2));
- points.splice(index + 1, 0, arcPt2, pivotPt, arcPt1);
}
}
- firingArc.setAttributeNS(null, 'points', points.join(' '));
+ return points;
+}
+
+function orderPoints(arcPoints, cornerPoints) {
+ if (cornerPoints.length === 0) {
+ return arcPoints;
+ }
+
+ const index = cornerPoints.findIndex(cp => shareValue(cp, arcPoints.at(0)));
+ cornerPoints.splice(index + 1, 0, ...arcPoints);
+ return cornerPoints;
+}
+
+function calcArcLinePtDeltas(aimPt, pivotPt, { dataset: { size }}) {
+ const angle = calculateAngle(aimPt.x - pivotPt.x, aimPt.y - pivotPt.y),
+ arcAngle = arcSize[size],
+ distance = Math.sqrt((aimPt.x - pivotPt.x) ** 2 + (aimPt.y - pivotPt.y) ** 2),
+ yDelta = distance * Math.cos(angle) * Math.tan(arcAngle),
+ xDelta = distance * Math.sin(angle) * Math.tan(arcAngle);
+
+ return { xDelta, yDelta };
+}
+
+function position(e, firingArc, firingArcOutline, aimLine, grid) {
+ // TODO: handle exactly horizontal and vertical lines?
+
+ const pointer = new DOMPoint(e.clientX, e.clientY),
+ pointerPt = pointer.matrixTransform(grid.getScreenCTM().inverse()),
+ pivotPt = new Point(aimLine.getAttribute('x1'), aimLine.getAttribute('y1')),
+
+ bounds = getBounds(grid.getBBox()),
+ aimPt = edgePoint(pivotPt, pointerPt, bounds),
+
+ { xDelta, yDelta } = calcArcLinePtDeltas(aimPt, pivotPt, firingArc),
+ arcPt1 = edgePoint(pivotPt, new Point(aimPt.x - xDelta, aimPt.y - yDelta), bounds),
+ arcPt2 = edgePoint(pivotPt, new Point(aimPt.x + xDelta, aimPt.y + yDelta), bounds),
+
+ outlinePoints = [arcPt2, pivotPt, arcPt1],
+ cps = chooseCornerPoints(aimPt, arcPt1, arcPt2, bounds),
+ arcPoints = orderPoints(outlinePoints, cps);
+
+ aimLine.setAttributeNS(null, 'x2', aimPt.x);
+ aimLine.setAttributeNS(null, 'y2', aimPt.y);
+
+ firingArcOutline.setAttributeNS(null, 'points', outlinePoints.join(' '));
+ firingArc.setAttributeNS(null, 'points', arcPoints.join(' '));
}
function setDataAttrs({ dataset: { allegiance, number }}, el) {
@@ -242,7 +256,6 @@ export default function (el) {
arcLayer.appendChild(firingArc);
outlineLayer.appendChild(firingArcOutline);
- // const positionListener = position.bind(svg, firingArc, firingArcOutline, aim, grid);
function positionListener(e) {
position(e, firingArc, firingArcOutline, aimLine, grid);
}