fixed issues
This commit is contained in:
parent
46258a83eb
commit
aea08dc3fb
25 changed files with 1625 additions and 513 deletions
138
js/items.js
138
js/items.js
|
|
@ -1,3 +1,4 @@
|
|||
// tarinai_colony_game build 15.4.0: ball collisions, fence hitboxes, and archive throttling
|
||||
"use strict";
|
||||
|
||||
class Item {
|
||||
|
|
@ -122,16 +123,7 @@ class Item {
|
|||
updateBall(dt, worldRef) {
|
||||
this.prevX = this.x;
|
||||
this.prevY = this.y;
|
||||
const maxSpeed = 1250;
|
||||
const clampVelocity = () => {
|
||||
const speed = Math.hypot(this.vx || 0, this.vy || 0);
|
||||
if (speed > maxSpeed) {
|
||||
this.vx = (this.vx || 0) / speed * maxSpeed;
|
||||
this.vy = (this.vy || 0) / speed * maxSpeed;
|
||||
}
|
||||
return Math.hypot(this.vx || 0, this.vy || 0);
|
||||
};
|
||||
const moving = clampVelocity();
|
||||
const moving = Math.hypot(this.vx || 0, this.vy || 0);
|
||||
if (moving > 0.04) {
|
||||
this.x += (this.vx || 0) * dt;
|
||||
this.y += (this.vy || 0) * dt;
|
||||
|
|
@ -143,7 +135,6 @@ class Item {
|
|||
this.resolveBallObstacleCollisions(dt, worldRef);
|
||||
this.x = clamp(this.x, p, worldRef.w - p);
|
||||
this.y = clamp(this.y, p, worldRef.h - p);
|
||||
clampVelocity();
|
||||
const groundFriction = Math.pow(0.72, dt);
|
||||
this.vx *= groundFriction;
|
||||
this.vy *= groundFriction;
|
||||
|
|
@ -156,21 +147,22 @@ class Item {
|
|||
resolveBallObstacleCollisions(dt, worldRef) {
|
||||
if (!worldRef?.nearbyItems) return;
|
||||
const speed = Math.hypot(this.vx || 0, this.vy || 0);
|
||||
const searchRadius = Math.max(130, (this.r || 18) + speed * Math.max(dt || 0.016, 0.016) + 96);
|
||||
const searchRadius = Math.max(150, (this.r || 18) + speed * Math.max(dt || 0.016, 0.016) + 120);
|
||||
const items = worldRef.nearbyItems(this.x, this.y, searchRadius) || [];
|
||||
let fenceChecks = 0;
|
||||
const maxFenceChecks = CONFIG.maxFenceCollisionChecks ?? 18;
|
||||
let solidChecks = 0;
|
||||
const maxSolidChecks = CONFIG.maxFenceCollisionChecks ?? 24;
|
||||
for (const it of items) {
|
||||
if (!it || it === this || it.dead) continue;
|
||||
if (it.type === "bed") {
|
||||
this.applyBallHayDrag(it, dt, worldRef);
|
||||
} else if (it.type === "stone") {
|
||||
this.resolveBallCircleBounce(it, (it.r || 20) * 1.08 + (this.r || 18), 0.82, worldRef);
|
||||
} else if (it.type === "fence_v" || it.type === "fence_h") {
|
||||
if (fenceChecks >= maxFenceChecks) continue;
|
||||
fenceChecks += 1;
|
||||
this.resolveBallFenceBounce(it, worldRef);
|
||||
}
|
||||
const rects = worldRef.solidObstacleRects ? worldRef.solidObstacleRects(it) : [];
|
||||
if (!rects.length) continue;
|
||||
if (solidChecks >= maxSolidChecks) continue;
|
||||
solidChecks += 1;
|
||||
for (const rect of rects) this.resolveBallRectBounce(rect, worldRef, it);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -195,7 +187,27 @@ class Item {
|
|||
let dx = this.x - obstacle.x;
|
||||
let dy = this.y - obstacle.y;
|
||||
let d = Math.hypot(dx, dy);
|
||||
if (d >= hitRadius) return;
|
||||
if (d >= hitRadius) {
|
||||
const px = this.prevX;
|
||||
const py = this.prevY;
|
||||
if (!Number.isFinite(px) || !Number.isFinite(py)) return;
|
||||
const sx = this.x - px;
|
||||
const sy = this.y - py;
|
||||
const len2 = sx * sx + sy * sy;
|
||||
if (len2 <= 0.0001) return;
|
||||
const t = clamp(((obstacle.x - px) * sx + (obstacle.y - py) * sy) / len2, 0, 1);
|
||||
const cx = px + sx * t;
|
||||
const cy = py + sy * t;
|
||||
dx = cx - obstacle.x;
|
||||
dy = cy - obstacle.y;
|
||||
d = Math.hypot(dx, dy);
|
||||
if (d >= hitRadius) return;
|
||||
if (d < 0.001) {
|
||||
const speed = Math.hypot(this.vx || 0, this.vy || 0);
|
||||
if (speed > 0.001) { dx = -(this.vx || 0) / speed; dy = -(this.vy || 0) / speed; d = 1; }
|
||||
else { dx = -sx / Math.sqrt(len2); dy = -sy / Math.sqrt(len2); d = 1; }
|
||||
}
|
||||
}
|
||||
if (d < 0.001) {
|
||||
const speed = Math.hypot(this.vx || 0, this.vy || 0);
|
||||
if (speed > 0.001) { dx = -(this.vx || 0) / speed; dy = -(this.vy || 0) / speed; d = 1; }
|
||||
|
|
@ -219,29 +231,69 @@ class Item {
|
|||
this.emitBallBounce(worldRef, obstacle);
|
||||
}
|
||||
|
||||
resolveBallFenceBounce(fence, worldRef) {
|
||||
const vertical = fence.type === "fence_v";
|
||||
const len = Math.max(112, (fence.r || 42) * 3.55);
|
||||
const thick = Math.max(10, (fence.r || 42) * 0.31);
|
||||
const halfLen = len / 2;
|
||||
const sx1 = vertical ? fence.x : fence.x - halfLen;
|
||||
const sy1 = vertical ? fence.y - halfLen : fence.y;
|
||||
const sx2 = vertical ? fence.x : fence.x + halfLen;
|
||||
const sy2 = vertical ? fence.y + halfLen : fence.y;
|
||||
const vx = sx2 - sx1;
|
||||
const vy = sy2 - sy1;
|
||||
const segLenSq = vx * vx + vy * vy || 1;
|
||||
const u = clamp(((this.x - sx1) * vx + (this.y - sy1) * vy) / segLenSq, 0, 1);
|
||||
const cx = sx1 + vx * u;
|
||||
const cy = sy1 + vy * u;
|
||||
const hitRadius = (this.r || 18) + thick / 2 + 2;
|
||||
resolveBallRectBounce(rect, worldRef, source = null) {
|
||||
if (!rect) return;
|
||||
const hitRadius = (this.r || 18) + 2;
|
||||
const cx = clamp(this.x, rect.left, rect.right);
|
||||
const cy = clamp(this.y, rect.top, rect.bottom);
|
||||
let dx = this.x - cx;
|
||||
let dy = this.y - cy;
|
||||
let d = Math.hypot(dx, dy);
|
||||
if (d >= hitRadius) return;
|
||||
if (d >= hitRadius) {
|
||||
const px = this.prevX;
|
||||
const py = this.prevY;
|
||||
const expanded = { left: rect.left - hitRadius, right: rect.right + hitRadius, top: rect.top - hitRadius, bottom: rect.bottom + hitRadius };
|
||||
if (!Number.isFinite(px) || !Number.isFinite(py) || !worldRef?.segmentIntersectsRect?.(px, py, this.x, this.y, expanded)) return;
|
||||
let nx = 0;
|
||||
let ny = 0;
|
||||
const vx = this.vx || 0;
|
||||
const vy = this.vy || 0;
|
||||
const candidates = [];
|
||||
const sx = this.x - px;
|
||||
const sy = this.y - py;
|
||||
if (px < expanded.left && sx > 0) candidates.push({ nx: -1, ny: 0, t: (expanded.left - px) / Math.max(sx, 0.001) });
|
||||
if (px > expanded.right && sx < 0) candidates.push({ nx: 1, ny: 0, t: (px - expanded.right) / Math.max(-sx, 0.001) });
|
||||
if (py < expanded.top && sy > 0) candidates.push({ nx: 0, ny: -1, t: (expanded.top - py) / Math.max(sy, 0.001) });
|
||||
if (py > expanded.bottom && sy < 0) candidates.push({ nx: 0, ny: 1, t: (py - expanded.bottom) / Math.max(-sy, 0.001) });
|
||||
if (candidates.length) {
|
||||
candidates.sort((a, b) => a.t - b.t);
|
||||
nx = candidates[0].nx;
|
||||
ny = candidates[0].ny;
|
||||
} else if (Math.abs(vx) >= Math.abs(vy)) {
|
||||
nx = vx >= 0 ? -1 : 1;
|
||||
} else {
|
||||
ny = vy >= 0 ? -1 : 1;
|
||||
}
|
||||
const toward = vx * nx + vy * ny;
|
||||
if (nx < 0) this.x = expanded.left - 0.5;
|
||||
else if (nx > 0) this.x = expanded.right + 0.5;
|
||||
if (ny < 0) this.y = expanded.top - 0.5;
|
||||
else if (ny > 0) this.y = expanded.bottom + 0.5;
|
||||
if (nx) this.y = clamp(this.y, expanded.top, expanded.bottom);
|
||||
if (ny) this.x = clamp(this.x, expanded.left, expanded.right);
|
||||
if (toward < 0) {
|
||||
this.vx = vx - 1.78 * toward * nx;
|
||||
this.vy = vy - 1.78 * toward * ny;
|
||||
} else {
|
||||
this.vx = vx + nx * 18;
|
||||
this.vy = vy + ny * 18;
|
||||
}
|
||||
this.vx *= 0.94;
|
||||
this.vy *= 0.94;
|
||||
this.spinVelocity = clamp((this.spinVelocity || 0) + (nx >= 0 ? -1 : 1) * 6.2, -38, 38);
|
||||
this.emitBallBounce(worldRef, source || rect.item || rect);
|
||||
return;
|
||||
}
|
||||
if (d < 0.001) {
|
||||
if (vertical) { dx = (this.vx || 0) >= 0 ? -1 : 1; dy = 0; }
|
||||
else { dx = 0; dy = (this.vy || 0) >= 0 ? -1 : 1; }
|
||||
const left = Math.abs(this.x - rect.left);
|
||||
const right = Math.abs(rect.right - this.x);
|
||||
const top = Math.abs(this.y - rect.top);
|
||||
const bottom = Math.abs(rect.bottom - this.y);
|
||||
const m = Math.min(left, right, top, bottom);
|
||||
if (m === left) { dx = -1; dy = 0; }
|
||||
else if (m === right) { dx = 1; dy = 0; }
|
||||
else if (m === top) { dx = 0; dy = -1; }
|
||||
else { dx = 0; dy = 1; }
|
||||
d = 1;
|
||||
}
|
||||
const nx = dx / d;
|
||||
|
|
@ -252,11 +304,19 @@ class Item {
|
|||
if (toward < 0) {
|
||||
this.vx = (this.vx || 0) - 1.78 * toward * nx;
|
||||
this.vy = (this.vy || 0) - 1.78 * toward * ny;
|
||||
} else {
|
||||
this.vx = (this.vx || 0) + nx * 18;
|
||||
this.vy = (this.vy || 0) + ny * 18;
|
||||
}
|
||||
this.vx *= 0.94;
|
||||
this.vy *= 0.94;
|
||||
this.spinVelocity = clamp((this.spinVelocity || 0) + (nx >= 0 ? -1 : 1) * 6.2, -38, 38);
|
||||
this.emitBallBounce(worldRef, fence);
|
||||
this.emitBallBounce(worldRef, source || rect.item || rect);
|
||||
}
|
||||
|
||||
resolveBallFenceBounce(fence, worldRef) {
|
||||
const rects = worldRef?.solidObstacleRects ? worldRef.solidObstacleRects(fence) : [];
|
||||
for (const rect of rects) this.resolveBallRectBounce(rect, worldRef, fence);
|
||||
}
|
||||
|
||||
emitBallBounce(worldRef, obstacle) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue