Setting to stop the camera drifting toward the pointer (t7)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -379,7 +379,7 @@ Saves in IndexedDB, world files (export / import) and the blueprint library.
|
|||||||
Starting, loading and quitting a game; modal dialogs; the pause menu.
|
Starting, loading and quitting a game; modal dialogs; the pause menu.
|
||||||
- functions: showLoading, enterGame, startNewWorld, startFromSave, quitToTitle, refreshContinue, anyModal, openModal, closeModal, closeAllModals, topModal, dialog, openPause, renderWorlds
|
- functions: showLoading, enterGame, startNewWorld, startFromSave, quitToTitle, refreshContinue, anyModal, openModal, closeModal, closeAllModals, topModal, dialog, openPause, renderWorlds
|
||||||
|
|
||||||
### src/ui/settings.js (122 lines)
|
### src/ui/settings.js (123 lines)
|
||||||
The settings screen.
|
The settings screen.
|
||||||
- functions: openSettings, renderSettings, applySettings, toggleFullscreen, confirmWipe
|
- functions: openSettings, renderSettings, applySettings, toggleFullscreen, confirmWipe
|
||||||
- variables: SET_TABS, setTab
|
- variables: SET_TABS, setTab
|
||||||
|
|||||||
@@ -4,6 +4,15 @@ What agents have done, newest first. Add an entry for every piece of work: the d
|
|||||||
note or request it was for, what changed, the files touched, the tests run, and anything left
|
note or request it was for, what changed, the files touched, the tests run, and anything left
|
||||||
open or not verified. Keep each entry short; the git history has the details.
|
open or not verified. Keep each entry short; the git history has the details.
|
||||||
|
|
||||||
|
## 2026-10-24: t7 Option to turn off smooth pan following the mouse (Claude Code, Codex)
|
||||||
|
|
||||||
|
- New setting `cameraLead` (Display: "Camera looks toward the pointer", on by default):
|
||||||
|
`src/ui/state.js`, `src/ui/settings.js`; `src/ui/loop.js` gives the camera no look-ahead when
|
||||||
|
it is off (mouse and gamepad).
|
||||||
|
- `test/play.py`: the toggle saves; with it off the camera stays on the bot with the mouse in a
|
||||||
|
corner; with it on the camera moves toward the corner.
|
||||||
|
- Tests: headless suites and `play.py` pass; `t_smooth` half-resolution flake as before.
|
||||||
|
|
||||||
## 2026-10-24: t9 Script to run the local server for testing (Claude Code, Codex)
|
## 2026-10-24: t9 Script to run the local server for testing (Claude Code, Codex)
|
||||||
|
|
||||||
- New `tools/serve.py`: builds, serves `dist/` on 127.0.0.1 (port 8000, or the next free one up
|
- New `tools/serve.py`: builds, serves `dist/` on 127.0.0.1 (port 8000, or the next free one up
|
||||||
|
|||||||
+2
-2
@@ -45,8 +45,8 @@ function frame(now) {
|
|||||||
} else acc = 0;
|
} else acc = 0;
|
||||||
drainEvents();
|
drainEvents();
|
||||||
let lookX = 0, lookY = 0;
|
let lookX = 0, lookY = 0;
|
||||||
if (GAME.usingPad) { lookX = GAME.padAim.x * 0.5; lookY = GAME.padAim.y * 0.5; }
|
if (SET.cameraLead && GAME.usingPad) { lookX = GAME.padAim.x * 0.5; lookY = GAME.padAim.y * 0.5; }
|
||||||
else if (GAME.mouse.in && toolId() !== 'build' && !GAME.paste && !GAME.selDrag && !selModeHeld()) { const dpr = R.canvas.width / window.innerWidth; lookX = (GAME.mouse.x - window.innerWidth / 2) * dpr / R.zp; lookY = (GAME.mouse.y - window.innerHeight / 2) * dpr / R.zp; }
|
else if (SET.cameraLead && GAME.mouse.in && toolId() !== 'build' && !GAME.paste && !GAME.selDrag && !selModeHeld()) { const dpr = R.canvas.width / window.innerWidth; lookX = (GAME.mouse.x - window.innerWidth / 2) * dpr / R.zp; lookY = (GAME.mouse.y - window.innerHeight / 2) * dpr / R.zp; }
|
||||||
// hold the camera's look-ahead still while dragging out a line, box or blueprint
|
// hold the camera's look-ahead still while dragging out a line, box or blueprint
|
||||||
// While dragging, the camera stays put unless the bot itself is flying, so the
|
// While dragging, the camera stays put unless the bot itself is flying, so the
|
||||||
// grid under the cursor does not slide around mid-line.
|
// grid under the cursor does not slide around mid-line.
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const SET_TABS = {
|
|||||||
{ k: 'cursorLabel', label: 'Name next to the cursor', d: 'Shows what you are pointing at right beside the cursor.', type: 'toggle' },
|
{ k: 'cursorLabel', label: 'Name next to the cursor', d: 'Shows what you are pointing at right beside the cursor.', type: 'toggle' },
|
||||||
{ k: 'showPerf', label: 'Performance stats', d: 'Frame time, simulation time and active areas.', type: 'toggle' },
|
{ k: 'showPerf', label: 'Performance stats', d: 'Frame time, simulation time and active areas.', type: 'toggle' },
|
||||||
{ k: 'cameraSmooth', label: 'Camera smoothing', type: 'range', min: 0, max: 0.95, step: 0.05, fmt: v => Math.round(v * 100) + '%' },
|
{ k: 'cameraSmooth', label: 'Camera smoothing', type: 'range', min: 0, max: 0.95, step: 0.05, fmt: v => Math.round(v * 100) + '%' },
|
||||||
|
{ k: 'cameraLead', label: 'Camera looks toward the pointer', d: 'The view drifts toward the mouse or right stick. Turn off to keep the bot centred.', type: 'toggle' },
|
||||||
{ k: 'shake', label: 'Screen shake', type: 'toggle' },
|
{ k: 'shake', label: 'Screen shake', type: 'toggle' },
|
||||||
],
|
],
|
||||||
Graphics: [
|
Graphics: [
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
// ---------- Settings ----------
|
// ---------- Settings ----------
|
||||||
const SET_DEFAULT = {
|
const SET_DEFAULT = {
|
||||||
zoom: 12, integerScale: true, renderScale: 1, uiScale: 1, fpsCap: 0, showPerf: false, shake: true, cameraSmooth: 0.7,
|
zoom: 12, integerScale: true, renderScale: 1, uiScale: 1, fpsCap: 0, showPerf: false, shake: true, cameraSmooth: 0.7, cameraLead: true,
|
||||||
look: 'smooth', lighting: 'full', lightEvery: 1, ambient: 0.12, daylight: 1, glow: 'low', grain: 1, incandescence: true, particles: true,
|
look: 'smooth', lighting: 'full', lightEvery: 1, ambient: 0.12, daylight: 1, glow: 'low', grain: 1, incandescence: true, particles: true,
|
||||||
thermalPalette: 'inferno', simSpeed: 1, maxSteps: 3,
|
thermalPalette: 'inferno', simSpeed: 1, maxSteps: 3,
|
||||||
volMaster: 0.8, volMusic: 0.5, volSfx: 0.8, muted: false, muteUnfocused: true,
|
volMaster: 0.8, volMusic: 0.5, volSfx: 0.8, muted: false, muteUnfocused: true,
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
---
|
---
|
||||||
id: t7
|
id: t7
|
||||||
title: Option to turn off smooth pan following the mouse
|
title: Option to turn off smooth pan following the mouse
|
||||||
status: Todo
|
status: Review
|
||||||
created: 2026-10-24
|
created: 2026-10-24
|
||||||
updated: 2026-10-24T04:41:45Z
|
updated: 2026-10-24T05:15:28Z
|
||||||
|
order: 1
|
||||||
|
report: |
|
||||||
|
(agent) New setting: Settings > Display > "Camera looks toward the pointer". Turn it off and
|
||||||
|
the camera stays centred on the bot instead of drifting toward the mouse (or right stick).
|
||||||
|
It is on by default for new players; your choice is saved in the browser.
|
||||||
|
To check: turn it off, move the mouse to a screen corner while flying: the view shouldn't move.
|
||||||
---
|
---
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|||||||
@@ -121,6 +121,31 @@ with sync_playwright() as p:
|
|||||||
ev("SET.zoom = 4; resizeRender(); R.snapNext = true;") # the rest of this play-through was laid out at zoom 4
|
ev("SET.zoom = 4; resizeRender(); R.snapNext = true;") # the rest of this play-through was laid out at zoom 4
|
||||||
ev(f"SET.look = '{look}'"); pg.wait_for_timeout(200)
|
ev(f"SET.look = '{look}'"); pg.wait_for_timeout(200)
|
||||||
check(f'the {look} look is drawing', ev('R.smoothOn') == (look == 'smooth'), ev('[SET.look, R.smoothOn, SM.ok]'))
|
check(f'the {look} look is drawing', ev('R.smoothOn') == (look == 'smooth'), ev('[SET.look, R.smoothOn, SM.ok]'))
|
||||||
|
# Camera lead changes the view, not the bot or its aim.
|
||||||
|
mouse = ev('[GAME.mouse.x, GAME.mouse.y]')
|
||||||
|
ev("openSettings('Display')")
|
||||||
|
pg.screenshot(path=str(out / '00-camera-settings.png'))
|
||||||
|
pg.click('#set-cameraLead')
|
||||||
|
check('camera lead toggle saves its value', ev("!SET.cameraLead && JSON.parse(localStorage.getItem('deepgrain.settings')).cameraLead === false"))
|
||||||
|
pg.keyboard.press('Escape')
|
||||||
|
paused = ev('GAME.paused')
|
||||||
|
ev("GAME.paused = true; SET.cameraLead = false; $('cards').replaceChildren()") # cards cover the corner
|
||||||
|
pg.mouse.move(1240, 740); pg.wait_for_timeout(1000)
|
||||||
|
check('camera test pointer reaches the world', ev('GAME.mouse.in && GAME.mouse.x === 1240 && GAME.mouse.y === 740'))
|
||||||
|
camera_offset = """(() => {
|
||||||
|
const v = viewCells(), x = bot.x + bot.w / 2 - v.w / 2, y = bot.y + bot.h / 2 - v.h / 2;
|
||||||
|
const tx = v.w >= W ? (W - v.w) / 2 : Math.max(0, Math.min(W - v.w, x));
|
||||||
|
const ty = v.h >= H ? (H - v.h) / 2 : Math.max(0, Math.min(H - v.h, y));
|
||||||
|
return [R.camX - tx, R.camY - ty];
|
||||||
|
})()"""
|
||||||
|
centred = ev(camera_offset)
|
||||||
|
check('camera stays centred with pointer lead off', all(abs(d) < 2 for d in centred), centred)
|
||||||
|
ev('SET.cameraLead = true')
|
||||||
|
pg.wait_for_timeout(1000)
|
||||||
|
led = ev(camera_offset)
|
||||||
|
check('camera leads toward the pointer when enabled', all(b - a > 2 for a, b in zip(centred, led)), led)
|
||||||
|
pg.mouse.move(*mouse)
|
||||||
|
ev(f'GAME.paused = {json.dumps(paused)}; saveSettings()')
|
||||||
def cell_to_screen(x, y):
|
def cell_to_screen(x, y):
|
||||||
return ev(f'(() => {{ const dpr = R.canvas.width / innerWidth; const s = worldToScreenPx({x}+0.5, {y}+0.5); return [s.x/dpr, s.y/dpr]; }})()')
|
return ev(f'(() => {{ const dpr = R.canvas.width / innerWidth; const s = worldToScreenPx({x}+0.5, {y}+0.5); return [s.x/dpr, s.y/dpr]; }})()')
|
||||||
def blk(bx, by): return cell_to_screen(bx * 4 + 2, by * 4 + 2)
|
def blk(bx, by): return cell_to_screen(bx * 4 + 2, by * 4 + 2)
|
||||||
|
|||||||
Reference in New Issue
Block a user