Add a 4th template: classic Snake

New templateType "snake" alongside quiz/clicker/maze — additive, not a
redesign, so it's wired through every existing per-template
enumeration point (schema, types unions, scene factory, builder
dispatch on create/edit/AI-review pages, template icon maps) following
the pattern each already established.

games.templateType is a plain SQLite text column with a TypeScript-
only enum (no SQL DDL behind it) — confirmed via drizzle-kit generate
that adding "snake" produces zero migration, same as every in-place
template redesign this session.

Bounded arena (no maze-style wall authoring — keeps the builder trivial:
width/height/startLength/targetLength/wrapAround, nothing else).
Movement is a self-rescheduling delayedCall loop rather than a fixed
interval, since the step interval itself shrinks as the snake grows;
speed curve sanity-checked standalone before wiring it in. Discrete
per-cell snapping (not tweened, unlike the maze's glide) — that's the
authentic blocky Snake feel, not a shortcut. Standard collision rule:
the tail cell is excluded from the self-collision check unless this
step eats food, since the tail is vacating that cell.

Progress resumes the exact live state (body/direction/food/score) —
Snake has no natural level-boundary checkpoint the way the other three
templates do, so unlike their coarse-grained resume this restores
precisely.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
This commit is contained in:
ogrechkoandClaude Sonnet 5 committed 2026-08-01 03:49:26 +00:00
1 parent c035650063
commit a61ef772db
12 files changed
+477 -6

No files matched your search

@@ -4,6 +4,7 @@ import { TEMPLATE_TYPES, TEMPLATE_LABELS, type TemplateType } from "@/lib/games/
import { QuizBuilder } from "@/components/builders/quiz-builder";
import { ClickerBuilder } from "@/components/builders/clicker-builder";
import { MazeBuilder } from "@/components/builders/maze-builder";
import { SnakeBuilder } from "@/components/builders/snake-builder";
export default async function ManualCreatePage({ params }: { params: Promise<{ template: string }> }) {
const { template } = await params;
@@ -23,6 +24,7 @@ export default async function ManualCreatePage({ params }: { params: Promise<{ t
{templateType === "quiz" && <QuizBuilder mode="create" />}
{templateType === "clicker" && <ClickerBuilder mode="create" />}
{templateType === "maze" && <MazeBuilder mode="create" />}
{templateType === "snake" && <SnakeBuilder mode="create" />}
</div>
);
}