No description
  • JavaScript 87%
  • CSS 8.6%
  • HTML 3.7%
  • Shell 0.7%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-22 22:14:00 -04:00
.forgejo/ISSUE_TEMPLATE docs: add roadmap, conventions and issue templates 2026-10-22 00:42:10 -04:00
deploy docs + deploy: README (run, port, tests, layout), staging run/stop scripts and htaccess for ag1.ndev1.com 2026-10-22 22:14:00 -04:00
docs docs: add roadmap, conventions and issue templates 2026-10-22 00:42:10 -04:00
games Block Drop: SRS rotation/kicks, seeded 7-bag, hold, T-spins, 100 levels with garbage, patterns and specials, colour-assist sprites 2026-10-22 22:14:00 -04:00
server server: zero-dependency static server, /games/<slug>/ redirects, rewarded-ad token stub with rate limiting 2026-10-22 22:14:00 -04:00
shared site: home page, fonts, palette and thumbnails from designWench's art kit 2026-10-22 22:14:00 -04:00
site site: home page, fonts, palette and thumbnails from designWench's art kit 2026-10-22 22:14:00 -04:00
test tests: level validity/determinism, hex collisions, SRS/line clears/bag, storage, server, headless bot runs 2026-10-22 22:14:00 -04:00
.gitignore chore: package.json (no deps), gitignore, robots.txt 2026-10-22 22:14:00 -04:00
package.json chore: package.json (no deps), gitignore, robots.txt 2026-10-22 22:14:00 -04:00
play.html shared shell: fixed-timestep loop, scaling, keyboard/touch/mouse/gamepad input, localStorage scores/progress, ad placeholders + simulated rewarded continue, level select, colour-assist toggle 2026-10-22 22:14:00 -04:00
README.md docs + deploy: README (run, port, tests, layout), staging run/stop scripts and htaccess for ag1.ndev1.com 2026-10-22 22:14:00 -04:00
robots.txt chore: package.json (no deps), gitignore, robots.txt 2026-10-22 22:14:00 -04:00

NetDagger Arcade

Retro-inspired single-player HTML5 arcade games (plain JS, HTML5 canvas, CSS) with ad-supported continues. No dependencies: no npm install, no build step. The browser loads ES modules straight from disk, and the server uses only Node built-ins.

Game Path Levels Issue
Hex Breaker (Breakout/Arkanoid-style, hex bricks) /games/hex-breaker/ 1–100 #20
Block Drop (falling blocks, SRS rotation, 7-bag) /games/block-drop/ 1–100 #27

Run it

node server/index.js          # or: npm start
# -> http://127.0.0.1:8080/

Needs Node 18 or newer (staging runs 24). Environment variables:

Var Default Meaning
PORT 8080 listen port (staging: 3108)
HOST 127.0.0.1 bind address; 0.0.0.0 to expose on the LAN
TRUST_PROXY unset 1 = take the client IP from X-Forwarded-For (behind Apache)
REWARD_MIN_WATCH_MS 5000 minimum simulated-ad watch time before a reward can be claimed
REWARD_COOLDOWN_MS 0 per-client gap between rewards
REWARD_TTL_MS 600000 reward token lifetime

URLs

  • / is the home page (site/index.html, designWench's portal), with ad slots home-top and home-bottom.
  • /games/<slug>/ redirects with a 302 to /play.html?game=<slug> (other query params are kept).
  • play.html?game=<slug>&level=N starts a given level, which must already be unlocked. Add &dev=1 to unlock every level locally.
  • /api/health, POST /api/reward/start, and POST /api/reward/claim make up the rewarded-ad token stub (same-origin JSON, rate-limited).

The server only serves play.html, robots.txt, ads.txt (when present), shared/, games/ and the contents of site/. The repository files (server/, test/, docs/, *.md, dotfiles) are never served.

Tests

node --test                   # or: npm test

The tests cover the following:

  • Level validity and determinism for all 200 levels. Every Hex Breaker level is clearable: no breakable brick is sealed in by steel.
  • Hex collisions, SRS rotation and kicks, line clears, garbage, and the 7-bag.
  • Storage, the fixed-timestep loop, and scaling.
  • The reward store and the rate limiter.
  • The HTTP server: the static allowlist, redirects, and the reward flow.
  • Headless bot runs of both games.

Layout

server/            zero-dependency HTTP server + reward-token stub
shared/            game shell: loop, scaling, input (keys/touch/mouse/gamepad), storage, audio, sprites, ads
play.html          the game page (canvas, ad placeholders, level select, continue modal)
site/              home page, CSS, fonts, thumbnails (from the art kit)
games/index.json   game registry
games/<slug>/      manifest.json, game.js (+ pure logic modules), assets/*.png
deploy/            run.sh / stop.sh / htaccess for staging
test/              node:test suites

Game interface

game.js default-exports a class with init(ctx, api), update(dt) (fixed 1/60 s), render(alpha), onReward(type) and destroy(). api provides:

  • level, carry, input, keys, sprites, audio, settings()
  • rng(salt) (seeded per game, level and salt)
  • highScore(), setScore(), levelComplete({score, carry}), gameOver({score})

Levels

  • Hex Breaker (games/hex-breaker/levels.js):
    • Levels 1–10 are hand-made. Levels 11–100 come from a seeded generator with 8 layout patterns, moving rows, and hard (2–5 HP), steel and power-up bricks.
    • A flood-fill check and repair step guarantees every breakable brick can be reached.
    • Ball speed rises and paddle width shrinks with level.
    • Power-ups: wide, sticky, multi-ball, laser, slow, extra life.
  • Block Drop (games/block-drop/levels.js):
    • Gravity runs from 1 s/row down to 0.018 s/row. Line goals and garbage rows grow with level.
    • Preset patterns appear on levels ending in 3 and 7. Rising garbage starts at level 35.
    • Every 10th level is a special: dig, quads, survive, and finally 40 lines at level 100.
    • Lock delay is 500 ms, falling to 300 ms.

Art

Sprites load from games/<slug>/assets/<name>.png, using the names listed in manifest.json → sprites. They are drawn with image smoothing off. If a sprite is missing, the game falls back to canvas shapes, so the games still work with an empty assets/ folder. The art comes from designWench's kit (/workspace/arcade-art). Do not run its _build/build.py, because it wipes the kit folder. Block Drop has a colour-assist mode that uses the lettered mino-*-cb sprites. Toggle it with the Assist button or the K key; the setting is saved.

Deploy (staging: https://ag1.ndev1.com on rori)

This follows the Hexosphere pattern used on bg1:

git clone ssh://git@git.nd-server0.com:2222/NetDagger/arcade.git ~/apps/arcade   # first time; later: git pull
~/apps/arcade/deploy/run.sh        # starts node on 127.0.0.1:3108 if not already running
~/apps/arcade/deploy/stop.sh       # stop (cron restarts it within a minute)
cp ~/apps/arcade/deploy/htaccess ~/ag1.ndev1.com/.htaccess

The crontab has two entries, alongside the hexosphere ones:

* * * * * $HOME/apps/arcade/deploy/run.sh >/dev/null 2>&1
@reboot $HOME/apps/arcade/deploy/run.sh >/dev/null 2>&1

Logs and the PID file live in ~/apps/arcade/run/. An optional ~/apps/arcade/.env (in KEY=value format) overrides the defaults: PORT=3108, HOST=127.0.0.1, TRUST_PROXY=1. After a git pull, run deploy/stop.sh && deploy/run.sh.