Second game mode selectable at dog select (host-authoritative online): - js/sim_arena.js: top-down sim, same export surface as sim.js — x/y plane plus a z hop axis (Space / comma); KOs by knocking dogs into abyss pits - js/mapgen_arena.js: mirrored symmetric arenas — walls, pits, center clearing, guaranteed spawn-to-center corridors, crystals/spikes/launch pads, mirrored saw pairs; fallback pit pair since pits are the only KO mechanic - specials re-imagined per dog: zoom dash, ram + hop-slam, zip-leash slingshot, blink, hover (floats over pits/saws/spikes) - render: arena tiles with wall shadows + void pits, top-down dog drawing with z-lift over a ground shadow; new fall event/sfx - B.HOP input bit so 'up' can mean north in top-down (Space also jumps in side view); mode toggle UI + mode carried in start/rematch net messages Tested: arena mapgen determinism/symmetry/connectivity + chaotic matches + pit/hop scenarios headless; local chaos + full P2P arena match (host mode flip syncs to client) in two headless browsers with zero page errors.
31 lines
1.2 KiB
JavaScript
31 lines
1.2 KiB
JavaScript
// Keyboard → input bitmasks. Two local slots; netplay merges both slots so the
|
|
// online player can use either WASD or arrows.
|
|
import { B } from './consts.js';
|
|
|
|
const MAPS = [
|
|
{ KeyA: B.L, KeyD: B.R, KeyW: B.U | B.JUMP, KeyS: B.D, KeyF: B.ATK, KeyG: B.SPC, KeyH: B.ITM, Space: B.HOP },
|
|
{ ArrowLeft: B.L, ArrowRight: B.R, ArrowUp: B.U | B.JUMP, ArrowDown: B.D, KeyK: B.ATK, KeyL: B.SPC, Semicolon: B.ITM, Comma: B.HOP },
|
|
];
|
|
|
|
const bits = [0, 0];
|
|
const down = new Set();
|
|
|
|
const PREVENT = new Set(['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Space']);
|
|
|
|
export function initInput() {
|
|
window.addEventListener('keydown', (e) => {
|
|
if (e.target && e.target.tagName === 'INPUT') return; // leave text fields alone
|
|
if (PREVENT.has(e.code)) e.preventDefault();
|
|
if (down.has(e.code)) return;
|
|
down.add(e.code);
|
|
for (let s = 0; s < 2; s++) if (MAPS[s][e.code]) bits[s] |= MAPS[s][e.code];
|
|
});
|
|
window.addEventListener('keyup', (e) => {
|
|
down.delete(e.code);
|
|
for (let s = 0; s < 2; s++) if (MAPS[s][e.code]) bits[s] &= ~MAPS[s][e.code];
|
|
});
|
|
window.addEventListener('blur', () => { bits[0] = 0; bits[1] = 0; down.clear(); });
|
|
}
|
|
|
|
export function getBits(slot) { return bits[slot]; }
|
|
export function getMergedBits() { return bits[0] | bits[1]; }
|