← back to Animals
dog-park: arrow-key movement + Auto walk toggle (button/T-key), human input cancels auto
4071c18ce4b248847b78282c6e9ddd4cd82d7639 · 2026-05-13 11:46:30 -0700 · SteveStudio2
Files touched
M public/dogpark/dogpark.jsM public/dogpark/index.html
Diff
commit 4071c18ce4b248847b78282c6e9ddd4cd82d7639
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Wed May 13 11:46:30 2026 -0700
dog-park: arrow-key movement + Auto walk toggle (button/T-key), human input cancels auto
---
public/dogpark/dogpark.js | 60 +++++++++++++++++++++++++++++++++++++++++++----
public/dogpark/index.html | 8 +++++--
2 files changed, 62 insertions(+), 6 deletions(-)
diff --git a/public/dogpark/dogpark.js b/public/dogpark/dogpark.js
index 8d6c3fb..7f70d75 100644
--- a/public/dogpark/dogpark.js
+++ b/public/dogpark/dogpark.js
@@ -821,6 +821,8 @@ function sendChat() {
}
chatSend.addEventListener('click', sendChat);
chatInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') sendChat(); });
+// Auto-walk HUD button — toggles the same flag the 'T' key drives.
+document.getElementById('autoBtn')?.addEventListener('click', () => setAutoMode(!autoMode));
setInterval(updateProximityHud, 200);
// ── State sync ────────────────────────────────────────────────────────────
@@ -943,19 +945,50 @@ function applyState(msg) {
// ── Local control ────────────────────────────────────────────────────────
const keys = new Set();
+// Map arrow keys onto WASD slots so the existing movement code stays single-
+// path. Anything that isn't an arrow falls through unchanged so 'shift', 'c',
+// 'p', etc. still work.
+const _aliasKey = (k) => ({
+ arrowup: 'w', arrowdown: 's', arrowleft: 'a', arrowright: 'd',
+}[k] || k);
+// "Auto" mode — chooses a random target inside the park and wanders toward it,
+// re-picking when close or after ~6s. Any human keypress cancels Auto so users
+// can grab the controls back instantly. Toggled via the HUD button or 'T' key.
+let autoMode = false;
+let _autoTarget = null;
+let _autoUntil = 0;
+function setAutoMode(on) {
+ autoMode = !!on;
+ const btn = document.getElementById('autoBtn');
+ if (btn) {
+ btn.textContent = autoMode ? '⏸ Stop auto' : '▶ Auto walk';
+ btn.classList.toggle('on', autoMode);
+ }
+ if (!autoMode) _autoTarget = null;
+}
window.addEventListener('keydown', (e) => {
if (e.repeat) return;
- keys.add(e.key.toLowerCase());
- if (e.key.toLowerCase() === 'c') {
+ // Don't capture keys when typing in the chat or join inputs.
+ const tag = (e.target?.tagName || '').toLowerCase();
+ if (tag === 'input' || tag === 'textarea' || tag === 'select') return;
+ const k = e.key.toLowerCase();
+ keys.add(_aliasKey(k));
+ // Movement input from a human cancels auto-walk immediately.
+ if (autoMode && ['w','a','s','d','arrowup','arrowdown','arrowleft','arrowright'].includes(k)) {
+ setAutoMode(false);
+ }
+ if (k === 'c') {
if (ws?.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ t:'call' }));
addLog('🗣 Called dog');
}
- } else if (e.key.toLowerCase() === 'p') {
+ } else if (k === 'p') {
cameraMode = (cameraMode + 1) % 2;
+ } else if (k === 't') {
+ setAutoMode(!autoMode);
}
});
-window.addEventListener('keyup', (e) => keys.delete(e.key.toLowerCase()));
+window.addEventListener('keyup', (e) => keys.delete(_aliasKey(e.key.toLowerCase())));
renderer.domElement.addEventListener('click', (e) => {
// Throw a ball/frisbee in the direction the camera faces, with mouse-y for arc
@@ -992,6 +1025,25 @@ function step(dt) {
if (keys.has('s')) mz += 1;
if (keys.has('a')) mx -= 1;
if (keys.has('d')) mx += 1;
+ // Auto-walk: pick a random point inside the park and stride toward it.
+ // Re-pick when within 1.2u or after the 6s deadline. Human input above
+ // already wins because setAutoMode(false) fires on keydown.
+ if (autoMode && !mx && !mz) {
+ const nowMs = performance.now();
+ const dxT = (_autoTarget?.x ?? myX) - myX;
+ const dzT = (_autoTarget?.z ?? myZ) - myZ;
+ const distT = Math.hypot(dxT, dzT);
+ if (!_autoTarget || distT < 1.2 || nowMs > _autoUntil) {
+ _autoTarget = {
+ x: (Math.random() - 0.5) * (PARK_HALF * 1.6),
+ z: (Math.random() - 0.5) * (PARK_HALF * 1.6),
+ };
+ _autoUntil = nowMs + 6000;
+ } else {
+ mx = dxT / distT;
+ mz = dzT / distT;
+ }
+ }
if (mx || mz) {
const len = Math.hypot(mx, mz);
mx /= len; mz /= len;
diff --git a/public/dogpark/index.html b/public/dogpark/index.html
index 12185e2..b12e339 100644
--- a/public/dogpark/index.html
+++ b/public/dogpark/index.html
@@ -41,6 +41,9 @@
#avatar-link:hover{background:#fdf5e6;border-color:#d4a04a;color:#5a4020}
#hud{position:fixed;bottom:14px;left:14px;background:rgba(0,0,0,.55);padding:10px 14px;border-radius:10px;font-size:12px;line-height:1.6}
#hud kbd{background:#fff;color:#000;padding:1px 6px;border-radius:4px;font-family:ui-monospace,Menlo,monospace;font-size:11px;margin:0 2px}
+ #autoBtn{background:rgba(212,160,74,.18);color:#f4f1ea;border:1px solid #d4a04a;padding:.4em .9em;border-radius:6px;font:inherit;font-size:12px;font-weight:600;cursor:pointer;letter-spacing:.04em}
+ #autoBtn:hover{background:rgba(212,160,74,.32)}
+ #autoBtn.on{background:#d4a04a;color:#0e0e10}
#counter{position:fixed;top:50px;left:14px;background:rgba(0,0,0,.55);padding:8px 12px;border-radius:8px;font-size:12px}
#log{position:fixed;bottom:14px;right:14px;width:240px;max-height:140px;overflow:auto;background:rgba(0,0,0,.55);padding:8px 12px;border-radius:8px;font-size:11px;line-height:1.5}
#chatbar{position:fixed;left:50%;bottom:24px;transform:translateX(-50%) translateY(120%);background:rgba(14,14,16,.92);border:1px solid #d4a04a;border-radius:14px;padding:10px 14px;display:flex;align-items:center;gap:12px;z-index:60;backdrop-filter:blur(10px);box-shadow:0 12px 40px rgba(0,0,0,.5);transition:transform 220ms cubic-bezier(.2,.7,.2,1);min-width:380px}
@@ -147,9 +150,10 @@
</div>
<div id="log" style="display:none"></div>
<div id="hud" style="display:none">
- <div><kbd>W</kbd><kbd>A</kbd><kbd>S</kbd><kbd>D</kbd> walk · <kbd>Shift</kbd> run · <kbd>C</kbd> call dog</div>
+ <div><kbd>W</kbd><kbd>A</kbd><kbd>S</kbd><kbd>D</kbd> or <kbd>↑</kbd><kbd>↓</kbd><kbd>←</kbd><kbd>→</kbd> walk · <kbd>Shift</kbd> run · <kbd>C</kbd> call dog</div>
<div><kbd>Click</kbd> throw ball · <kbd>Shift+Click</kbd> throw frisbee</div>
- <div><kbd>P</kbd> first/third person</div>
+ <div><kbd>P</kbd> first/third person · <kbd>T</kbd> auto walk</div>
+ <div style="margin-top:6px"><button id="autoBtn" type="button">▶ Auto walk</button></div>
</div>
<script type="importmap">
← 3aa2726 dog-park: brand logo upper-left, hamburger nav upper-right w
·
back to Animals
·
snapshot: backup uncommitted work (1 files) 9a24d54 →