Extract input module
This commit is contained in:
175
src/main.js
175
src/main.js
@@ -1,15 +1,6 @@
|
||||
(() => {
|
||||
const {
|
||||
Engine,
|
||||
Render,
|
||||
Runner,
|
||||
World,
|
||||
Body,
|
||||
Constraint,
|
||||
Events,
|
||||
Query,
|
||||
Vector,
|
||||
} = Matter;
|
||||
const { Engine, Render, Runner, World, Body, Constraint, Events, Vector } =
|
||||
Matter;
|
||||
|
||||
const { scenes = [], defaultSceneId } = window.PhysilinksScenes || {};
|
||||
const getSceneById = (sceneId) =>
|
||||
@@ -143,8 +134,8 @@
|
||||
let levelWon = false;
|
||||
let timerEndMs = null;
|
||||
let lastTimerDisplay = null;
|
||||
let dragConstraint = null;
|
||||
let spawnSystem = null;
|
||||
let input = null;
|
||||
|
||||
const {
|
||||
loadHighScore = () => 0,
|
||||
@@ -303,7 +294,7 @@
|
||||
clearedCount = 0;
|
||||
clearedByColor = {};
|
||||
goals.resetMilestones();
|
||||
endDrag();
|
||||
input?.endDrag();
|
||||
const winCond = currentScene?.config?.winCondition;
|
||||
if (winCond?.type === "timer") {
|
||||
const duration = winCond.durationSec ?? 120;
|
||||
@@ -571,143 +562,6 @@
|
||||
checkWinCondition();
|
||||
};
|
||||
|
||||
const pickBody = (point) => {
|
||||
const hits = Query.point(balls, point);
|
||||
return hits[0];
|
||||
};
|
||||
|
||||
const getDraggableBody = (point) => {
|
||||
const draggables = [
|
||||
...boundaries.filter((b) => b.plugin?.draggable),
|
||||
...balls.filter((b) => b.plugin?.draggable),
|
||||
];
|
||||
const hits = Query.point(draggables, point);
|
||||
return hits[0];
|
||||
};
|
||||
|
||||
const startDrag = (body, point) => {
|
||||
endDrag();
|
||||
dragConstraint = Constraint.create({
|
||||
pointA: point,
|
||||
bodyB: body,
|
||||
stiffness: 0.2,
|
||||
damping: 0.3,
|
||||
render: { visible: false },
|
||||
});
|
||||
World.add(world, dragConstraint);
|
||||
};
|
||||
|
||||
const updateDrag = (point) => {
|
||||
if (!dragConstraint) return;
|
||||
dragConstraint.pointA = point;
|
||||
};
|
||||
|
||||
const endDrag = () => {
|
||||
if (dragConstraint) {
|
||||
World.remove(world, dragConstraint);
|
||||
dragConstraint = null;
|
||||
}
|
||||
};
|
||||
|
||||
const getPointerPosition = (evt) => {
|
||||
const rect = render.canvas.getBoundingClientRect();
|
||||
const clientX = evt.touches ? evt.touches[0].clientX : evt.clientX;
|
||||
const clientY = evt.touches ? evt.touches[0].clientY : evt.clientY;
|
||||
return {
|
||||
x: clientX - rect.left,
|
||||
y: clientY - rect.top,
|
||||
};
|
||||
};
|
||||
|
||||
const handlePointerDown = (evt) => {
|
||||
if (gameOver || isPaused || levelWon) return;
|
||||
const point = getPointerPosition(evt);
|
||||
const dragTarget = getDraggableBody(point);
|
||||
if (dragTarget) {
|
||||
startDrag(dragTarget, point);
|
||||
return;
|
||||
}
|
||||
const body = pickBody(point);
|
||||
if (!body) return;
|
||||
if (!currentScene?.config?.relaxMode) {
|
||||
// Only allow linking same colors unless relax mode explicitly opts out.
|
||||
chain.color = body.plugin.color;
|
||||
} else {
|
||||
chain.color = body.plugin.color;
|
||||
}
|
||||
chain.active = true;
|
||||
chain.bodies = [body];
|
||||
chain.constraints = [];
|
||||
chain.pointer = point;
|
||||
setHighlight(body, true);
|
||||
updateHud();
|
||||
};
|
||||
|
||||
const handlePointerMove = (evt) => {
|
||||
if (dragConstraint) {
|
||||
updateDrag(getPointerPosition(evt));
|
||||
return;
|
||||
}
|
||||
if (!chain.active) return;
|
||||
if (gameOver || isPaused || levelWon) return;
|
||||
const point = getPointerPosition(evt);
|
||||
chain.pointer = point;
|
||||
const body = pickBody(point);
|
||||
if (!body) return;
|
||||
const alreadyInChain = chain.bodies.includes(body);
|
||||
if (alreadyInChain) {
|
||||
const targetIndex = chain.bodies.indexOf(body);
|
||||
if (chain.bodies.length > 1 && targetIndex === chain.bodies.length - 2) {
|
||||
removeLastFromChain();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!currentScene?.config?.relaxMode && body.plugin.color !== chain.color)
|
||||
return;
|
||||
const maxLinkDist = getMaxLinkDistance();
|
||||
const dist = Vector.magnitude(
|
||||
Vector.sub(chain.bodies[chain.bodies.length - 1].position, body.position),
|
||||
);
|
||||
if (dist > maxLinkDist) return;
|
||||
addToChain(body);
|
||||
};
|
||||
|
||||
const handlePointerUp = () => {
|
||||
if (dragConstraint) {
|
||||
endDrag();
|
||||
return;
|
||||
}
|
||||
finishChain(chain.pointer);
|
||||
};
|
||||
|
||||
render.canvas.addEventListener("mousedown", handlePointerDown);
|
||||
render.canvas.addEventListener("mousemove", handlePointerMove);
|
||||
window.addEventListener("mouseup", handlePointerUp);
|
||||
render.canvas.addEventListener(
|
||||
"touchstart",
|
||||
(e) => {
|
||||
e.preventDefault();
|
||||
handlePointerDown(e);
|
||||
},
|
||||
{ passive: false },
|
||||
);
|
||||
render.canvas.addEventListener(
|
||||
"touchmove",
|
||||
(e) => {
|
||||
e.preventDefault();
|
||||
handlePointerMove(e);
|
||||
},
|
||||
{ passive: false },
|
||||
);
|
||||
render.canvas.addEventListener(
|
||||
"touchend",
|
||||
(e) => {
|
||||
e.preventDefault();
|
||||
handlePointerUp(e);
|
||||
},
|
||||
{ passive: false },
|
||||
);
|
||||
|
||||
const updateHud = () => {
|
||||
ui.updateHud({
|
||||
spawnIntervalMs: config.spawnIntervalMs,
|
||||
@@ -722,6 +576,25 @@
|
||||
goals.maybeAnnounceGoalProgress(goal);
|
||||
};
|
||||
|
||||
input = window.PhysilinksInput.create({
|
||||
render,
|
||||
world,
|
||||
balls,
|
||||
boundaries,
|
||||
chain,
|
||||
config,
|
||||
getCurrentScene: () => currentScene,
|
||||
isPaused: () => isPaused,
|
||||
isLevelWon: () => levelWon,
|
||||
isGameOver: () => gameOver,
|
||||
getMaxLinkDistance,
|
||||
setHighlight,
|
||||
removeLastFromChain,
|
||||
addToChain,
|
||||
finishChain,
|
||||
updateHud,
|
||||
});
|
||||
|
||||
const buildLegend = () => {
|
||||
ui.buildLegend(config.palette);
|
||||
};
|
||||
@@ -743,7 +616,7 @@
|
||||
Body.setVelocity(ball, { x: 0, y: 0 });
|
||||
});
|
||||
resetChainVisuals();
|
||||
endDrag();
|
||||
input?.endDrag();
|
||||
};
|
||||
|
||||
const handleResize = () => {
|
||||
|
||||
Reference in New Issue
Block a user