54 lines
2.3 KiB
JavaScript
54 lines
2.3 KiB
JavaScript
|
|
"use strict";
|
||
|
|
|
||
|
|
(function (global) {
|
||
|
|
function bounceInsideWorld(obj, worldRef, opts = {}) {
|
||
|
|
if (!obj || !worldRef) return false;
|
||
|
|
const p = Math.max(opts.padding ?? 28, CONFIG.worldPadding || 30);
|
||
|
|
const bx = opts.bounceX ?? opts.bounce ?? 0.72;
|
||
|
|
const by = opts.bounceY ?? opts.bounce ?? 0.72;
|
||
|
|
const spinBounce = opts.spinBounce ?? -0.72;
|
||
|
|
let bounced = false;
|
||
|
|
if (obj.x < p) { obj.x = p; obj.vx = Math.abs(obj.vx || 0) * bx; bounced = true; }
|
||
|
|
if (obj.x > worldRef.w - p) { obj.x = worldRef.w - p; obj.vx = -Math.abs(obj.vx || 0) * bx; bounced = true; }
|
||
|
|
if (obj.y < p) { obj.y = p; obj.vy = Math.abs(obj.vy || 0) * by; bounced = true; }
|
||
|
|
if (obj.y > worldRef.h - p) { obj.y = worldRef.h - p; obj.vy = -Math.abs(obj.vy || 0) * by; bounced = true; }
|
||
|
|
if (bounced && Number.isFinite(obj.spinVelocity)) obj.spinVelocity *= spinBounce;
|
||
|
|
return bounced;
|
||
|
|
}
|
||
|
|
|
||
|
|
function applyKinematicItemMotion(item, worldRef, dt, opts = {}) {
|
||
|
|
if (!item || !worldRef) return 0;
|
||
|
|
const stopSpeed = opts.stopSpeed ?? 0.05;
|
||
|
|
const speed = Math.hypot(item.vx || 0, item.vy || 0);
|
||
|
|
item.prevX = item.x;
|
||
|
|
item.prevY = item.y;
|
||
|
|
if (speed <= stopSpeed) {
|
||
|
|
item.vx = 0;
|
||
|
|
item.vy = 0;
|
||
|
|
if (Number.isFinite(item.spinVelocity)) {
|
||
|
|
item.spinVelocity *= Math.pow(opts.spinRestDamp ?? 0.08, dt);
|
||
|
|
item.spin = (item.spin || 0) + (item.spinVelocity || 0) * dt;
|
||
|
|
}
|
||
|
|
return speed;
|
||
|
|
}
|
||
|
|
item.x += (item.vx || 0) * dt;
|
||
|
|
item.y += (item.vy || 0) * dt;
|
||
|
|
bounceInsideWorld(item, worldRef, opts);
|
||
|
|
const friction = Math.pow(opts.frictionBase ?? 0.68, dt * (opts.frictionRate ?? 1));
|
||
|
|
item.vx *= friction;
|
||
|
|
item.vy *= friction;
|
||
|
|
if (opts.spin !== false) {
|
||
|
|
item.spin = (item.spin || 0) + (item.spinVelocity || 0) * dt + (item.vx || 0) * dt / Math.max(7, item.r || 16);
|
||
|
|
item.spinVelocity = (item.spinVelocity || 0) * Math.pow(opts.spinFrictionBase ?? 0.38, dt);
|
||
|
|
}
|
||
|
|
if (Math.hypot(item.vx || 0, item.vy || 0) < (opts.zeroBelow ?? 0)) {
|
||
|
|
item.vx = 0;
|
||
|
|
item.vy = 0;
|
||
|
|
if (Number.isFinite(item.spinVelocity)) item.spinVelocity *= 0.3;
|
||
|
|
}
|
||
|
|
worldRef.drawListDirty = true;
|
||
|
|
return speed;
|
||
|
|
}
|
||
|
|
|
||
|
|
global.TarinaiPhysics = { bounceInsideWorld, applyKinematicItemMotion };
|
||
|
|
})(typeof window !== "undefined" ? window : globalThis);
|