Spaces:
Running
Running
Smooth the joystick camera-follow (exponential ease via panTo)
Browse filesThe follow was a hard snap (flyTo ms=0 each frame; re-issuing the easeInOutQuad
tween would have lagged heavily instead). Added chunkedMap.panTo(wx,wy) — a
direct, clamped camera set with no tween — and the Game now lerps the camera
toward the hero each frame with a ~0.12s time constant (frame-rate independent).
Verified: the camera glides behind the hero with a small, stable trailing lag
(~5px) and eases on start/stop instead of snapping.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- web/comboBattler.js +14 -3
- web/mapSandbox.js +12 -1
web/comboBattler.js
CHANGED
|
@@ -273,6 +273,17 @@ function createChunkedMap(pixi, host, config) {
|
|
| 273 |
flyAnim = { fromX: camera.x, fromY: camera.y, fromZ: zoom, toX: wx, toY: wy, toZ, t: 0, dur: Math.max(1, ms), resolve };
|
| 274 |
});
|
| 275 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 276 |
function bindInput() {
|
| 277 |
const canvas = app.canvas;
|
| 278 |
const local = (cx, cy) => {
|
|
@@ -523,7 +534,7 @@ function createChunkedMap(pixi, host, config) {
|
|
| 523 |
ctx = null;
|
| 524 |
texCache.clear();
|
| 525 |
}
|
| 526 |
-
return { ready, regenerate, destroy, onChange, getSnapshot, getCamera, tileIndexAt, biomeAt: biomeAt2, getBounds, zoomBy, flyTo, setEnabled, onTick, getEntityLayer, getApp, screenToWorld, worldToScreen, tile: TILE9 };
|
| 527 |
}
|
| 528 |
|
| 529 |
// ../auto-battler/src/render/tileAutotile.js
|
|
@@ -6194,8 +6205,8 @@ function mountComboBattler(pixi, host, opts = {}) {
|
|
| 6194 |
dead = true;
|
| 6195 |
}
|
| 6196 |
if (joy.active && p && p.alive) {
|
| 6197 |
-
const w = fieldToWorld(p.x, p.y);
|
| 6198 |
-
map.
|
| 6199 |
}
|
| 6200 |
spawnFn && spawnFn(dt);
|
| 6201 |
R.syncActors(battle, dtMS, battle.t);
|
|
|
|
| 273 |
flyAnim = { fromX: camera.x, fromY: camera.y, fromZ: zoom, toX: wx, toY: wy, toZ, t: 0, dur: Math.max(1, ms), resolve };
|
| 274 |
});
|
| 275 |
}
|
| 276 |
+
function panTo(wx, wy) {
|
| 277 |
+
if (flyAnim) {
|
| 278 |
+
const r = flyAnim.resolve;
|
| 279 |
+
flyAnim = null;
|
| 280 |
+
r && r();
|
| 281 |
+
}
|
| 282 |
+
camera.x = wx;
|
| 283 |
+
camera.y = wy;
|
| 284 |
+
clampCamera();
|
| 285 |
+
cameraDirty = true;
|
| 286 |
+
}
|
| 287 |
function bindInput() {
|
| 288 |
const canvas = app.canvas;
|
| 289 |
const local = (cx, cy) => {
|
|
|
|
| 534 |
ctx = null;
|
| 535 |
texCache.clear();
|
| 536 |
}
|
| 537 |
+
return { ready, regenerate, destroy, onChange, getSnapshot, getCamera, tileIndexAt, biomeAt: biomeAt2, getBounds, zoomBy, flyTo, panTo, setEnabled, onTick, getEntityLayer, getApp, screenToWorld, worldToScreen, tile: TILE9 };
|
| 538 |
}
|
| 539 |
|
| 540 |
// ../auto-battler/src/render/tileAutotile.js
|
|
|
|
| 6205 |
dead = true;
|
| 6206 |
}
|
| 6207 |
if (joy.active && p && p.alive) {
|
| 6208 |
+
const cam = map.getCamera(), w = fieldToWorld(p.x, p.y), k = 1 - Math.exp(-dt / 0.12);
|
| 6209 |
+
map.panTo(cam.x + (w.x - cam.x) * k, cam.y + (w.y - cam.y) * k);
|
| 6210 |
}
|
| 6211 |
spawnFn && spawnFn(dt);
|
| 6212 |
R.syncActors(battle, dtMS, battle.t);
|
web/mapSandbox.js
CHANGED
|
@@ -273,6 +273,17 @@ function createChunkedMap(pixi, host, config) {
|
|
| 273 |
flyAnim = { fromX: camera.x, fromY: camera.y, fromZ: zoom, toX: wx, toY: wy, toZ, t: 0, dur: Math.max(1, ms), resolve };
|
| 274 |
});
|
| 275 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 276 |
function bindInput() {
|
| 277 |
const canvas = app.canvas;
|
| 278 |
const local = (cx, cy) => {
|
|
@@ -523,7 +534,7 @@ function createChunkedMap(pixi, host, config) {
|
|
| 523 |
ctx = null;
|
| 524 |
texCache.clear();
|
| 525 |
}
|
| 526 |
-
return { ready, regenerate, destroy, onChange, getSnapshot, getCamera, tileIndexAt, biomeAt: biomeAt2, getBounds, zoomBy, flyTo, setEnabled, onTick, getEntityLayer, getApp, screenToWorld, worldToScreen, tile: TILE11 };
|
| 527 |
}
|
| 528 |
|
| 529 |
// ../auto-battler/src/engine/rng.js
|
|
|
|
| 273 |
flyAnim = { fromX: camera.x, fromY: camera.y, fromZ: zoom, toX: wx, toY: wy, toZ, t: 0, dur: Math.max(1, ms), resolve };
|
| 274 |
});
|
| 275 |
}
|
| 276 |
+
function panTo(wx, wy) {
|
| 277 |
+
if (flyAnim) {
|
| 278 |
+
const r = flyAnim.resolve;
|
| 279 |
+
flyAnim = null;
|
| 280 |
+
r && r();
|
| 281 |
+
}
|
| 282 |
+
camera.x = wx;
|
| 283 |
+
camera.y = wy;
|
| 284 |
+
clampCamera();
|
| 285 |
+
cameraDirty = true;
|
| 286 |
+
}
|
| 287 |
function bindInput() {
|
| 288 |
const canvas = app.canvas;
|
| 289 |
const local = (cx, cy) => {
|
|
|
|
| 534 |
ctx = null;
|
| 535 |
texCache.clear();
|
| 536 |
}
|
| 537 |
+
return { ready, regenerate, destroy, onChange, getSnapshot, getCamera, tileIndexAt, biomeAt: biomeAt2, getBounds, zoomBy, flyTo, panTo, setEnabled, onTick, getEntityLayer, getApp, screenToWorld, worldToScreen, tile: TILE11 };
|
| 538 |
}
|
| 539 |
|
| 540 |
// ../auto-battler/src/engine/rng.js
|