Side-panel arcade: 18 offline mini-games to play while the model thinks.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:lhh010/dsh-minigames
GitHub-sourced plugins run build scripts on your machine at install time. Only install sources you trust, and pin a commit (github:owner/repo#sha).
README
简体中文 | English
Mini-games panel on the right side of the DSH Web UI: a slacking-off companion for killing time while waiting for model replies or fixing bugs.
- Collapsed state: a slim vertical bar (🎮) at the right edge of the browser, taking up no space.
- Expanded state: click to have it occupy the right half of the window (50vw by default; drag its left edge to resize between 360px–80vw), then freely pick a game inside the panel.
- Games (all offline, zero asset files, Canvas-rendered):
- 🦖 Dino Run — the classic Chrome T-Rex (day/night/rain);
- 🧱 Tetris — classic falling-block line clearing;
- 🛡️ Tank Battle (with AI) — 2D tank combat, enemy tracking + line-of-sight firing, 3 waves total;
- 💎 Match-3 — click to clear four-connected same-color blocks; pass levels by reaching target scores that increase level by level;
- 🔢 Huarong Pass — 16-tile number puzzle (15-puzzle); slide tiles into order; the faster you are, the higher the score;
- 🐍 Snake — classic snake; crossing a boundary makes you emerge from the opposite side (toroidal map);
- 🔢 2048 — slide with arrow keys to merge numbers; merging into 2048 wins;
- 💣 Minesweeper — left-click to reveal, right-click to flag, double-click a number to auto-expand its surroundings;
- 🃏 Memory Match — flip two to pair them up; fewer moves mean a higher score;
- ⚫ Gomoku vs AI — 15×15; the AI both attacks and blocks you;
- 🦘 Hop — hold to charge, release to jump; the closer your landing, the more points;
- 🧱 Breakout — move the paddle to bounce the ball; clearing a wall advances to the next level with increasing ball speed;
- 🔨 Whack-a-Mole — 30-second timed clicking; hit +1, miss −1;
- ⚫ Othello vs AI — 8×8 Othello; corners matter most; auto-passes when no move is available;
- 🐦 Flappy — click/space to flap through pipe gaps; the farther, the higher the score;
- 🧩 Sudoku — 9×9 standard sudoku; D key switches difficulty; filling with no conflicts wins;
- 🟡 Pac-Man — classic maze munching; power pellets let you eat the ghosts back;
- 🎯 Aim Training — FPS aim practice: locked mouse turns the view to track a 3D drifting target; left-click shoots with recoil.
- Reserved extension interface: a game registry (
registerGame) — adding a game only requires implementing one interface. - Experience details: games auto-pause when the panel collapses or the tab is switched, and resume when you come back; each game's high score is stored in localStorage; keyboard input only takes effect after clicking the game area and never hijacks the chat input box.
- Responsive sizing: the game canvas adapts to the panel's real available space (toolbar + canvas + control hints always display fully with no scrollbars; browser zoom and panel drag-resizing reflow automatically), with width/height caps of 960px.
Version compatibility
Compatible with DSH snapshot0810 (snapshots/20260810T155924Z), snapshot0811 (snapshots/20260811T152241Z), and the final snapshot snapshot0812 (snapshots/20260812T172954Z-final): it is a pure browser-side bundle (the node half is only a loader placeholder), with client metadata declared as nested dsh.client — snapshot0810's ClientModuleHostService reads only that field, and a top-level dshClient is silently ignored (no logs, no errors, and the plugin never enters the boot graph). Verified against 0810 on a live instance; boot verification passed on live instances of 0811 and the final 0812 snapshot (see below).
npm release compatibility: compatible with the DSH npm release @deepseek-ai/dsh@0.0.1-rc.5 (dist-tag next, i.e. the npm release of the final snapshot snapshot0812; npm exec -p @deepseek-ai/dsh@0.0.1-rc.5 -- dsh --profile web --port <port> accesses the pinned version and starts it in lib production mode), while also staying compatible with @deepseek-ai/dsh@0.0.1-rc.2 (the npm release of snapshot0811). Tested against the npm rc.5 baseline: after dsh web starts, the window.__DSH_BOOT__ manifest includes @dsh-external/dsh-minigames, and /plugins/@dsh-external/dsh-minigames/client.js returns 200; typecheck, build, and 201 unit tests pass. Note: starting with 0811 the vendored cordis was renamed to @deepseek-ai/cordis (npm releases no longer publish a vendored package under the cordis name). This plugin's source imports cordis only as types (src/index.ts, src/client/index.tsx, src/invariant.ts), and the type imports plus peer/devDependencies have been migrated to @deepseek-ai/cordis (peer ^4.0.1-rc.1, which is 4.0.1-rc.4 on the npm rc.5 baseline) — the build output (lib/*.js) has zero cordis runtime imports, a plain npm install no longer raises ERESOLVE, and --legacy-peer-deps is unnecessary.
0811 compatibility notes (snapshot0811, verified on a live instance)
- Bundle mechanism unchanged: 0811 still supports the composite bundle-layer mechanism
dsh.bundle.patch→cordis.patch.yml(this plugin's profile bundle install method stays the same); clientdsh.clientmetadata discovery and thewindow.__ModuleLoader__loading protocol are both unchanged. - cordis rename: 0811 renamed the vendored cordis from
cordis@4.0.0-rc.7to@deepseek-ai/cordis@4.0.1-rc.1. This plugin imports cordis only as types, and the build output has zero cordis runtime imports — the rename does not affect runtime loading of already-built bundles; on the npm baseline, typecheck of the barecordisimport resolving to the publiccordispackage still passes; see the alignment suggestion above. - Live-instance boot verification: after web starts on snapshot0811 (
snapshots/20260811T152241Z), thewindow.__DSH_BOOT__manifest includes@dsh-external/dsh-minigames,/plugins/@dsh-external/dsh-minigames/client.jsreturns 200, and the right-side panel (🎮 mini-games) renders as verified on a live instance. typecheck and 201 unit tests pass against the 0811 baseline.
0812/final snapshot compatibility notes (snapshots/20260812T172954Z-final, verified on a live instance)
- cordis rename in effect: this plugin has migrated its type-only imports (
src/index.ts,src/client/index.tsx) andpeerDependencies/devDependenciesto@deepseek-ai/cordis(^4.0.1-rc.1;@deepseek-ai/cordis@4.0.1-rc.4on the npm rc.5 baseline) — the build output (lib/*.js) has zero cordis runtime imports, typecheck is fully green for npm rc.5 consumers, andnpm installneeds no--legacy-peer-deps. - Bundle mechanism unchanged: the final snapshot still supports the composite bundle-layer mechanism
dsh.bundle.patch→cordis.patch.yml; clientdsh.clientmetadata discovery and thewindow.__ModuleLoader__loading protocol are unchanged; the panel depends on no host services or layout slots (a puredocument.bodyportal), decoupling it from the main framework's version. - Live-instance boot verification: after web starts on the final snapshot (
snapshots/20260812T172954Z-final), thewindow.__DSH_BOOT__manifest includes@dsh-external/dsh-minigamesand/plugins/@dsh-external/dsh-minigames/client.jsreturns 200; the boot manifest after startingdsh webas an npm rc.5 consumer also includes this plugin. typecheck, build, and 201 unit tests pass against the final-snapshot baseline.
Changelog
2026-08-11 · v0.3.2 — Dino Run character polish
- 🦖 Dino: redrawn from the classic pixel matrix — big head facing right, upturned tail, streamlined body, two running legs (tucked while jumping), white pixel eye; near-black in day, inverted to white at night
- 🐦 Bird: rounded body + forward-reaching head + pointed beak + flapping wings + tail, dual color palettes
- 🌵 Cactus: rounded dome + bent arms + vertical rib lines + top highlight; same for the two-cactus variant
- Verification: typecheck and 201 unit tests pass; live-loading verification passes
2026-08-11 · v0.3.1 — Aim Training becomes FPS-style, plus polish across games
- 🎯 Aim Training FPS-ified: Pointer Lock mouse capture (cursor hidden), crosshair fixed at screen center, mouse-delta view rotation (with pitch; vertical direction fixed), 3D drifting target (lateral movement + height floating), left-click shooting (recoil kicks the view up then it recovers + random lateral sway that decays + visible bullet tracers and hit sparks), first-person rifle viewmodel in the bottom-right, muzzle flash on firing, pause/start overlay hints
- 🔨 Whack-a-Mole: 3×3 → 5×5 (25 holes), up to 5 moles up at once
- 🟡 Pac-Man: mouth complement animation (open/close), ghost walking and eye-turning, grid-aligned movement (no more center/wall jitter), snapping back to center on wall hits without getting stuck, opening ghost grace period, ghost spawn points moved to both ends of the upper corridor
- Removed: 🏓 Pong
- Verification: typecheck and 201 unit tests pass; live-loading verification passes
2026-08-11 · v0.3.0 — 6 new mini-games (18 total, Pong removed afterwards)
- New games: 🔨 Whack-a-Mole (up to 3 up at once), ⚫ Othello vs AI, 🐦 Flappy, 🧩 Sudoku (three difficulties + timer), 🟡 Pac-Man (dual-ghost AI + power pellets)
- Removed: 🏓 Pong (poor gameplay experience)
- Verification: typecheck and 189 unit tests pass; live-loading verification passes
2026-08-11 · v0.2.0 — 7 new mini-games and detail polish
- New games (12 total): 🐍 Snake (toroidal crossing), 🔢 2048, 💣 Minesweeper (double-click expand), 🃏 Memory Match, ⚫ Gomoku vs AI, 🦘 Hop, 🧱 Breakout
- Snake: crossing a boundary continues from the mirrored position on the opposite side instead of dying against a wall
- Minesweeper: double-click an already-revealed number; when the flagged count around it equals the number, the remaining unrevealed cells auto-open
- Verification: typecheck and 128 unit tests pass; live-loading verification passes
2026-08-11 · v0.1.1 — snapshot0810 adaptation and panel responsive-sizing fix
- Migration: package.json client metadata migrated from top-level
dshClientto nesteddsh.client(inject kept as-is) - Fix: no more vertical scrollbar when the panel's available height is insufficient —
.dmg-bodyswitched to a flex column layout, the game area gets the real available height, and the canvas adapts as a whole ("toolbar + canvas + control hints") (previously the canvas height was determined by its own content, creating circular measurement; on narrow windows the canvas overflowed and triggered a scrollbar) - Bigger: canvas display width cap 640 → 960, games render larger on big panels
- Verification: typecheck and 70 unit tests pass; verified on a live DSH snapshot0810 instance plus multiple viewports (1600×900 / 1536×864 / 1366×640 / 1280×600 / 1024×600 / 960×540 / 1600×500) with no scrollbars
Gameplay and details
🦖 Dino Run
- Space / ↑ / click to jump, ↓ to duck; speed increases with score (
320 + score×0.15) up to a 760 px/s cap — the longer you run, the faster you go. - Score = distance moved ÷ 10, growing continuously (roughly 50–150 points/second).
- Obstacles: single cacti / double cacti / three bird types —
- High-flying bird: passes over the standing dino's head — punishes random jumping;
- Low-flying bird: duck to dodge, or jump to the apex to clear it;
- Ground-hugging bird: hugs the ground, only jumping dodges it (ducking is useless).
- Denser obstacles later on: spawn intervals shrink with score (1.1–2.4s → 0.5–1.2s).
- Day/night switches every 800 points: day (beige) ↔ night (inverted white).
- Rain mechanic: from every 1000 points, a 300-point window (1000–1300, 2000–2300, …) — slanting rain + mist that obscures the view, plus random lightning with full-screen white flashes.
- Score reporting is throttled to once per 10 points to avoid frequent panel refreshes.
🧱 Tetris
- ←→ move, ↑/X rotate (Z counterclockwise), space hard drop, C hold, P pause.
- Standard 10×20 board, 7 tetrominoes (T/S/Z/J/L rotate within a 3×3 matrix without truncation), ghost piece, next/hold previews, level acceleration (one level per 10 lines).
- The canvas scales with the panel (devicePixelRatio hi-DPI); when height is insufficient it shrinks to preserve aspect ratio without truncating the top.
🛡️ Tank Battle (with AI)
- WASD/arrow keys to move (free steering — the hull can turn while hugging walls), space to fire, P pause, R restart.
- The collision box is slightly smaller than one cell (32×32 → 26×26), letting you pass through slightly narrow lanes; hitting a wall snaps you back onto the grid lines, and driving straight snaps you to grid boundaries — no getting stuck half-way.
- The scene overlays translucent grid lines so lane directions are obvious at a glance.
- Enemy AI: greedy tracking + line-of-sight shooting; the 2-cell-wide spawn opening doesn't block them; 3 waves total (5 tanks each).
- Explosion effects, spawn-invincibility flashing, track animations, wave/lives HUD.
💎 Match-3
- Click any tile to clear all same-color tiles connected to it in four directions (diagonals don't count);
- The more you clear at once, the higher the score (quadratic:
score = 10 × cleared²); - After clearing, gems above fall freely to fill gaps (with fall animations, clear flashes, and floating score text); no new gems are added within a level;
- Reaching the target score passes the level, and the target increases by +400 per level (800 → 1200 → 1600 → …);
- No same-color group ≥2 and target unmet → game over (R restarts); mouse click and arrow keys + space are supported.
- Supports mouse click/drag and keyboard (arrow keys + space).
🔢 Huarong Pass
- 16-tile number puzzle (15-puzzle): a 4×4 board with 15 numbered tiles + 1 empty slot;
- Shuffling is done via random valid slides from the solved state, guaranteeing every puzzle is solvable;
- Click a tile in the same row/column as the empty slot (multiple tiles can be pushed at once); or slide with arrow keys (tiles slide into the empty slot in the arrow's direction);
- Tiles slide with interpolation animation, and tiles in their correct positions turn green automatically;
- Scored by fastest time (
max(0, 1000 − time×2)): the shorter the time, the higher the score; - The HUD shows moves + elapsed time; on completion it shows moves/time; R or a click reshuffles.
🐍 Snake
- Arrow keys / WASD to move, R restart, P pause.
- 16×12 grid; eating food grows the snake and scores +1.
- Toroidal map: crossing any boundary makes you emerge at the mirrored position on the opposite side instead of dying against a wall; the only way to die is hitting your own body (the tail cell about to move out doesn't count).
- Filling the entire board wins (
overis then flagged as a win state).
🔢 2048
- Arrow keys / WASD to slide and merge, R restart, P pause; on-screen direction buttons are also supported.
- 4×4 board; when equal numbers slide into each other they merge into double and score points (merge points accumulate into the total);
- After every valid move a new tile spawns at random (90% are 2s, 10% are 4s);
- Merging into 2048 wins (
won); when no move or merge direction remains, the game is over; - Scoring: the values produced by merges accumulate (the merge that creates 2048 alone is +2048).
💣 Minesweeper
- Left-click to reveal, right-click to flag/unflag, double-click an already-revealed number to auto-expand, R restart, P pause.
- 9×9 board with 10 mines; the first click is always safe (mines are placed outside a 3×3 safe zone);
- A revealed 0 auto-flood-expands its surroundings; revealing every safe cell wins (
won); - Double-click expand (chord): when the number of flags around a cell equals that number, the remaining unrevealed cells auto-open — if a flag was wrong, hitting a mine ends the game and reveals all mines;
- Timer and fastest time: timing starts at the first click (shown live in the HUD's top-right) and stops when sweeping finishes;
scored by time (
max(0, 1000 − time×2)) and reported, with the panel keeping the best score = fastest clear time; the faster, the higher the score.
🃏 Memory Match
- Click to flip cards, R restart, P pause.
- 4×4 grid with 8 symbol pairs; two matching cards clear, clearing all wins (
finished); - Mismatched cards flip back automatically; fewer moves mean a higher score
(
max(0, 500 − moves×5)).
⚫ Gomoku vs AI
- Click to place a stone (black moves first), R restart, P pause.
- 15×15 board; five in a row (horizontal/vertical/diagonal) wins; a full board is a draw;
- AI strategy: first make its own five → then block your five → otherwise pick by the "attack ×1.1 + defense" heuristic scoring (only considering spots near existing stones);
- The AI pauses about 0.5s to think, simulating a human rhythm.
🦘 Hop
- Hold to charge (the power bar rises), release to jump, R restart, P pause.
- High arc: a noticeably tall jump, with a ground shadow and the block tilting forward mid-air for a strong jump feel.
- Charge determines jump distance and air time; landing on the next platform advances +1 point, and landing closer to the platform's center earns an extra +2/+1 points;
- Landing back on the current platform costs nothing and play continues; missing (falling off) ends the game (with a falling animation);
- Mixed gap and width distribution: near gaps (55–105) ≈ 40%, medium (105–140) ≈ 35%, far (140–160) ≈ 25%; platform widths vary — narrow (42–52) ≈ 30%, normal (56–64) ≈ 40%, wide (72–88) ≈ 30%; narrow platforms are harder to land on precisely;
- Full charge clears the farthest platform (jump distance ≈ 202), but full charge overshoots near/medium platforms — you must adjust the charge to the actual gap and width instead of always maxing out.
🧱 Breakout
- Mouse / ←→ to move the paddle, R restart, P pause.
- 480×320 viewport: a 5-row × 8-column brick wall; the ball breaks bricks on contact for +10×level points;
- The paddle's bounce angle varies with where the ball hits (hitting the edges sends the ball at a steeper angle);
- Clearing a wall advances to the next level: the wall rebuilds and ball speed increases (
250 + level×20); - 3 lives; losing the ball costs one, and the game ends when they run out.
- Color mechanic: each row of bricks has a fixed color (clearing bricks doesn't change it); the ball takes on the color of the brick it clears, clearing same-color bricks scores ×3, and consecutive same-color clears can chain into high scores.
🔨 Whack-a-Mole
- 30-second timer: click the moles that pop up, R restart, P pause.
- 5×5 grass field (25 holes), up to 5 moles up at once, each retracting after 0.9–1.6s;
- Hit +1, miss −1 (floor of 0 points); the game ends when time runs out.
⚫ Othello vs AI
- Click to place a stone (black moves first), R restart, P pause.
- 8×8 Othello: placing a stone flips the opponent's stones it sandwiches; when no move is available you auto-pass, and when neither side can move whoever has more stones wins;
- Legal spots show hint dots; AI heuristics: prioritize corners, avoid corner-adjacent cells, favor edges, and also weigh the current flip count and center mobility.
🐦 Flappy
- Click / space / ↑ / W to flap, R restart, P pause.
- Gravity pulls you down; each pipe pair passed scores +1; speed rises slightly with score;
- Hitting a pipe, the ground, or the ceiling ends the run; the bird has pitch and flapping animations.
🧩 Sudoku
- Click to select a cell, 1–9 to fill / 0 or Backspace to clear, arrow keys move the cursor;
- D key cycles difficulty (easy 45 givens / normal 35 / hard 30), R starts a new puzzle;
- Givens are dark and immutable; player entries are blue and conflicts highlight red;
- Filling the grid with no conflicts wins; scored by time (
max(0, 1000 − time×2)), the faster, the higher the score, and the panel keeps your fastest time.
🟡 Pac-Man
- Arrow keys / WASD to move (turning only at intersections), R restart, P pause.
- 15×19 maze: dots +10, power pellets +50 and turn the ghosts blue and edible (eating a ghost +200);
- Ghosts chase the player (and flee during power); ghosts have a 1.5s grace period at the start and after respawn during which they don't collide, so no instant death; touching a normal ghost costs a life, and the game ends when all 3 are gone; eating every dot clears the level.
🎯 Aim Training
- Mouse turns the view (crosshair fixed at screen center), left-click to shoot, R restart, P pause.
- First-person scene: sky + a perspective ground grid, the horizon moves with pitch, and a held rifle viewmodel in the bottom-right;
- The target drifts in 3D inside a large world (random lateral direction changes, vertical height floating, bouncing off walls), projected into the view, shrinking with distance;
- Locking on (crosshair held over the target) scores continuously (10 points/second); shooting a hit scores +20, firing has recoil (the view kicks up then recovers) and random lateral sway (quickly decaying), and bullets are visible: a glowing tracer flies from the muzzle toward the target (hit) or into the distance (miss), with an explosion spark at the hit point and a muzzle flash;
- 30-second timer; at the end it shows the total score and shot accuracy.
Installation
Prerequisites: a built DSH 20260808+ snapshot and pnpm.
git clone https://github.com/lhh010/dsh-minigames.git # 或直接使用本目录
cd dsh-minigames
pnpm install
pnpm build
# 装入当前 web profile(自动写入依赖并加入 dsh.profile.bundles)
dsh plugin --profile web add /绝对路径/to/dsh-minigames
# 可选:确认组合配置只出现一个插件行
dsh --profile web --dump-config | grep dsh-minigames
Plugin-set changes take effect after restarting dsh web. To uninstall:
dsh plugin --profile web remove @dsh-external/dsh-minigames
This repository ships both
dsh.plugin.json(registry-channel manifest) andcordis.patch.yml(official profile bundle channel); install through one of them — never enable both at once.
Usage
- Open the DSH Web UI (
dsh web); a slim 🎮 bar appears at the page's right edge. - Click the bar → the panel expands to occupy the right half of the window.
- Click a game card to start;
Ppauses,Rrestarts (after the round ends), and clicking "Choose Game" returns to the selection list. - Click "Collapse" again to fold back into the bar (the game auto-pauses and progress is kept).
Development
pnpm install
pnpm run typecheck # tsc --noEmit
pnpm run test # vitest 纯逻辑单测(189 个:引擎/棋盘/世界模型/三消/华容道/贪吃蛇/2048/扫雷/翻牌/五子棋/跳一跳/打砖块/打地鼠/黑白棋/Flappy/数独/吃豆人/跟枪/注册表)
pnpm run build # tsc 声明 + tsdown:lib/index.js(node half)+ lib/client.js(浏览器 bundle)
Build artifacts (committed with the source, consistent with dsh-web-panel):
lib/index.js— the node half (loader-line implementation, logging only; client-plugin scanning relies on this line existing).lib/client.js— the browser bundle,window.__ModuleLoader__.load({ id: '@dsh-external/dsh-minigames', factory }); the id must match thenameinpackage.json(client-modules use the package name as the compose key).lib/types/— declaration files.
Architecture
src/
index.ts node half(loader 行实现)
invariant.ts 不变式伴生文件
client/
index.tsx 客户端插件:DOM portal 挂载面板(ctx.effect 管理生命周期)
app.css 面板样式(全部 dmg- 前缀,随 bundle 注入 <style>)
panel/Panel.tsx 折叠条 / 展开面板 / 游戏选择器 / GameArea 生命周期
games/
types.ts 游戏扩展接口(MiniGameDefinition / MiniGameInstance)
registry.ts 注册表(registerGame / getGames / getGame)
focus.ts 键盘焦点门控(避免劫持聊天输入)
canvas-fit.ts 画布按宿主自适应缩放(devicePixelRatio,防截断)
index.ts 内置游戏注册点
dino/ 纯逻辑(引擎:物理/计分/昼夜/雨天/生成密度)+ 渲染 + 游戏定义
tetris/ 纯逻辑(棋盘:旋转/消行/暂存/等级)+ 渲染 + 游戏定义
tanks/ 纯逻辑(世界:网格/转向吸附/AI/波次/特效)+ 渲染 + 游戏定义
match3/ 纯逻辑(三消:四连通/落体/目标分/关卡)+ 渲染 + 游戏定义
huarong/ 纯逻辑(华容道:滑动/打乱/解状态)+ 渲染 + 游戏定义
snake/ 纯逻辑(贪吃蛇:环面穿越/自撞/成长)+ 渲染 + 游戏定义
game2048/ 纯逻辑(2048:滑动合并/生成/胜负判定)+ 渲染 + 游戏定义
minesweeper/ 纯逻辑(扫雷:布雷/洪水展开/标旗/双击展开)+ 渲染 + 游戏定义
memory/ 纯逻辑(翻牌:配对/步数)+ 渲染 + 游戏定义
gomoku/ 纯逻辑(五子棋:落子/胜负/启发式 AI)+ 渲染 + 游戏定义
hop/ 纯逻辑(跳一跳:蓄力/落地判定/计分)+ 渲染 + 游戏定义
breakout/ 纯逻辑(打砖块:挡板/碰撞/关卡/球速)+ 渲染 + 游戏定义
whack/ 纯逻辑(打地鼠:计时/冒头/得分)+ 渲染 + 游戏定义
othello/ 纯逻辑(黑白棋:翻转/让位/终局/启发式 AI)+ 渲染 + 游戏定义
flappy/ 纯逻辑(Flappy:重力/柱子/碰撞/计分)+ 渲染 + 游戏定义
sudoku/ 纯逻辑(数独:生成/挖洞/冲突/计时)+ 渲染 + 游戏定义
pacman/ 纯逻辑(吃豆人:迷宫/移动/幽灵 AI/力量豆)+ 渲染 + 游戏定义
aimtrack/ 纯逻辑(跟枪:视角转向/三维漂移/射击后坐/晃动/命中率)+ 渲染 + 游戏定义
tests/ 纯逻辑单元测试
The panel depends on no host services or layout slots (a pure document.body portal), so:
- it is decoupled from the main framework's version,
dsh.client.injectis empty, and the client has zero@deepseek-aidependencies; - no matter how the DSH layout changes (left column / right column / collapsed), there is no conflict.
Adding a New Game (Reserved Interface)
Implement MiniGameDefinition (src/client/games/types.ts):
import { registerGame, type MiniGameDefinition } from './index.ts'
const myGame: MiniGameDefinition = {
id: 'my-game', // 唯一 id(作为选中记忆与最高分 key)
title: '我的游戏',
icon: '🎯',
description: '一句话介绍',
controls: ['空格:跳跃', 'P:暂停'], // 画布下方的按键图例
create(host, options) {
// 在 host 内创建 <canvas>;返回实例:
return {
start() {}, // 启动/恢复主循环
pause() {}, // 暂停(面板折叠/切标签页/用户暂停时调用)
resume() {}, // 恢复
destroy() {}, // 释放 rAF/键盘监听等
}
},
}
registerGame(myGame)
The instance returned by create has its lifecycle driven by the panel: when switching games, the old instance is destroy()ed first, then
the new one is create()d; pause() is called when the panel collapses, the tab hides, or the user pauses.
Scores are reported via options.onScore?.(score) (called only when they change); the panel handles display and
high-score persistence. It's recommended to split game logic into pure-function modules (no DOM/timers), covered
by unit tests just like the existing games.
Known Limitations and Roadmap
- Keyboard control depends on the game area's focus; after clicking the chat input you must click back into the game area to keep playing (intentional).
- Tank Battle's AI uses greedy tracking + line-of-sight shooting with no pathfinding; obstacle avoidance and different armor types could be added later.
- Match-3's and the block/tank games' level progress is not saved across sessions (only high scores persist).
- Dino's rain and day/night are purely visual atmosphere and don't affect gameplay logic.
Links
More in this category
Nagi-ovo/dsh-ads★ 318
Parody ads in 2005-Chinese-web style: sidebar banners, in-chat feeds, corner popups, and a close button whose hit area is smaller than it looks. All fictional.
vlln/whale-girl★ 121
Desktop pet (QQ-pet style): floats in the corner, draggable, feedable, playable.
omdsh-dev/dsh-gomoku★ 12
Play Gomoku against the AI, or let two AIs battle it out.
AnacondaKC/dsh-stock-market★ 11
Fixes the bug where your account can't lose money while you code.
hellodigua/dsh-emoji★ 11
Automatically add emojis to AI replies.
william-jin-cmu/dsh-stickers★ 10
Bidirectional sticker reactions between user and agent.