summaryrefslogtreecommitdiff
path: root/packages/client/src/scripts/physics.ts
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2021-11-12 02:02:25 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2021-11-12 02:02:25 +0900
commit0e4a111f81cceed275d9bec2695f6e401fb654d8 (patch)
tree40874799472fa07416f17b50a398ac33b7771905 /packages/client/src/scripts/physics.ts
parentupdate deps (diff)
downloadsharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.gz
sharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.bz2
sharkey-0e4a111f81cceed275d9bec2695f6e401fb654d8.zip
refactoring
Resolve #7779
Diffstat (limited to 'packages/client/src/scripts/physics.ts')
-rw-r--r--packages/client/src/scripts/physics.ts152
1 files changed, 152 insertions, 0 deletions
diff --git a/packages/client/src/scripts/physics.ts b/packages/client/src/scripts/physics.ts
new file mode 100644
index 0000000000..445b6296eb
--- /dev/null
+++ b/packages/client/src/scripts/physics.ts
@@ -0,0 +1,152 @@
+import * as Matter from 'matter-js';
+
+export function physics(container: HTMLElement) {
+ const containerWidth = container.offsetWidth;
+ const containerHeight = container.offsetHeight;
+ const containerCenterX = containerWidth / 2;
+
+ // サイズ固定化(要らないかも?)
+ container.style.position = 'relative';
+ container.style.boxSizing = 'border-box';
+ container.style.width = `${containerWidth}px`;
+ container.style.height = `${containerHeight}px`;
+
+ // create engine
+ const engine = Matter.Engine.create({
+ constraintIterations: 4,
+ positionIterations: 8,
+ velocityIterations: 8,
+ });
+
+ const world = engine.world;
+
+ // create renderer
+ const render = Matter.Render.create({
+ engine: engine,
+ //element: document.getElementById('debug'),
+ options: {
+ width: containerWidth,
+ height: containerHeight,
+ background: 'transparent', // transparent to hide
+ wireframeBackground: 'transparent', // transparent to hide
+ }
+ });
+
+ // Disable to hide debug
+ Matter.Render.run(render);
+
+ // create runner
+ const runner = Matter.Runner.create();
+ Matter.Runner.run(runner, engine);
+
+ const groundThickness = 1024;
+ const ground = Matter.Bodies.rectangle(containerCenterX, containerHeight + (groundThickness / 2), containerWidth, groundThickness, {
+ isStatic: true,
+ restitution: 0.1,
+ friction: 2
+ });
+
+ //const wallRight = Matter.Bodies.rectangle(window.innerWidth+50, window.innerHeight/2, 100, window.innerHeight, wallopts);
+ //const wallLeft = Matter.Bodies.rectangle(-50, window.innerHeight/2, 100, window.innerHeight, wallopts);
+
+ Matter.World.add(world, [
+ ground,
+ //wallRight,
+ //wallLeft,
+ ]);
+
+ const objEls = Array.from(container.children);
+ const objs = [];
+ for (const objEl of objEls) {
+ const left = objEl.dataset.physicsX ? parseInt(objEl.dataset.physicsX) : objEl.offsetLeft;
+ const top = objEl.dataset.physicsY ? parseInt(objEl.dataset.physicsY) : objEl.offsetTop;
+
+ let obj;
+ if (objEl.classList.contains('_physics_circle_')) {
+ obj = Matter.Bodies.circle(
+ left + (objEl.offsetWidth / 2),
+ top + (objEl.offsetHeight / 2),
+ Math.max(objEl.offsetWidth, objEl.offsetHeight) / 2,
+ {
+ restitution: 0.5
+ }
+ );
+ } else {
+ const style = window.getComputedStyle(objEl);
+ obj = Matter.Bodies.rectangle(
+ left + (objEl.offsetWidth / 2),
+ top + (objEl.offsetHeight / 2),
+ objEl.offsetWidth,
+ objEl.offsetHeight,
+ {
+ chamfer: { radius: parseInt(style.borderRadius || '0', 10) },
+ restitution: 0.5
+ }
+ );
+ }
+ objEl.id = obj.id;
+ objs.push(obj);
+ }
+
+ Matter.World.add(engine.world, objs);
+
+ // Add mouse control
+
+ const mouse = Matter.Mouse.create(container);
+ const mouseConstraint = Matter.MouseConstraint.create(engine, {
+ mouse: mouse,
+ constraint: {
+ stiffness: 0.1,
+ render: {
+ visible: false
+ }
+ }
+ });
+
+ Matter.World.add(engine.world, mouseConstraint);
+
+ // keep the mouse in sync with rendering
+ render.mouse = mouse;
+
+ for (const objEl of objEls) {
+ objEl.style.position = `absolute`;
+ objEl.style.top = 0;
+ objEl.style.left = 0;
+ objEl.style.margin = 0;
+ }
+
+ window.requestAnimationFrame(update);
+
+ let stop = false;
+
+ function update() {
+ for (const objEl of objEls) {
+ const obj = objs.find(obj => obj.id.toString() === objEl.id.toString());
+ if (obj == null) continue;
+
+ const x = (obj.position.x - objEl.offsetWidth / 2);
+ const y = (obj.position.y - objEl.offsetHeight / 2);
+ const angle = obj.angle;
+ objEl.style.transform = `translate(${x}px, ${y}px) rotate(${angle}rad)`;
+ }
+
+ if (!stop) {
+ window.requestAnimationFrame(update);
+ }
+ }
+
+ // 奈落に落ちたオブジェクトは消す
+ const intervalId = setInterval(() => {
+ for (const obj of objs) {
+ if (obj.position.y > (containerHeight + 1024)) Matter.World.remove(world, obj);
+ }
+ }, 1000 * 10);
+
+ return {
+ stop: () => {
+ stop = true;
+ Matter.Runner.stop(runner);
+ clearInterval(intervalId);
+ }
+ };
+}