Hacktoberfest Open-Source AI Challenge — Week 2: Side Hustle submission*
Duck Evac (鸭鸭大撤离) is a complete, playable 2D top-down extraction shooter: drop in, loot, fight enemy ducks, extract alive. Every line of its code was generated with DeepSeek V4.1 (open weights, MIT license); every sprite was generated with MiniMax (open weights). No human drew a pixel, no human hand-wrote the engine — one person directed two open models and shipped a real game. It's now heading to TapTap (China's indie mobile store) for commercial release.
- Code: key systems pasted in the Code section below (a GitHub repo will follow after the deadline rush)
- Demo: 67 seconds of real gameplay, captured from the running web build
- Art: 100% original duck IP — zero copyrighted assets, zero takedown risk
The problem: one person, a whole game
I wanted to ship a commercial indie game solo. The math every solo dev knows:
- Code: a real game engine is thousands of lines — game loop, 8-direction sprite rendering, enemy AI, HUD, minimap, mobile touch controls. Months of work for one person.
- Art: 42 sprites (3 playable duck skins, 6 bosses, soldiers, guns, menu art) in one consistent flat-cartoon style. Commissioning that costs more than the game will ever earn; drawing it myself was never an option.
- The trap: closed models could do it, but per-token pricing turns "iterate 200 times on the boss fight" into a budget meeting. Open weights remove the meter: iterate forever, pay nothing per token.
The bet: open-weight models are now good enough that one person can direct them like a team — a coder and an art department — and ship.
What I built
Duck Evac is a 2D top-down search-strike-extract shooter:
- 搜 (Loot) — scavenge buildings for weapons and supplies, backpack with 6 slots
- 打 (Fight) — WASD + mouse aim on desktop; virtual joystick + fire/skill/melee/slide buttons on mobile; enemy ducks patrol and attack, bosses guard the extraction zone
- 撤离 (Extract) — reach the extraction point before the timer runs out, or lose everything
Tech: Vite + React 19 + TypeScript, Canvas rendering with auto-resolution scaling, ~6,300-line game engine, 8-direction sprite system with runtime chroma-keying (AI art ships on white/green backgrounds; the engine cuts it out at load). Runs in the browser today; Android APK build in testing, TapTap submission in progress.
How the open models built it
Code — DeepSeek V4.1 (open weights, MIT). The entire codebase: the engine, the sprite pipeline, the HUD/minimap, the mobile control layer, the build scripts. The sprite system below is a good example of what it produced unprompted — region-growing background removal with separate tolerances for JPEG noise, gradient backgrounds, and enclosed white regions, plus per-sheet frame-order correction so a mislabeled sprite sheet doesn't need regeneration:
/** 抠除颜色容差平方(JPEG 压缩噪声余量) */
const CUT_TOL2 = 52 * 52;
/** 区域生长局部色差容差平方:背景渐变相邻像素色差极小,可一路传播;轮廓线深色跳变被挡住 */
const LOCAL_TOL2 = 15 * 15;
/** 区域生长全局约束平方:局部传播只允许发生在与背景参考足够近的像素上,
防止穿过轮廓断口漏进角色身体(浅色身体脱色 bug 根因) */
const GROW_BOUND2 = 90 * 90;
That's not boilerplate — that's a model reasoning about failure modes (light-colored bodies desaturating through contour gaps) and engineering around them.
Art — MiniMax (open weights). All 42 assets: 3 player duck skins (beret + backpack, steel helmet, red cap), 6 bosses (chicken, cat, dog, goose, weasel, fox — each with 8-direction sheets), soldier/ghost variants, guns, menu background. One flat-cartoon style, dark olive + beak-yellow tactical palette, held across every sheet:
// 美术素材:生成的角色 / Boss 立绘与主菜单背景(暗橄榄 + 鸭喙黄战术风)
export const CHARACTER_ART: Record<string, string> = {
balanced: '.../aadkwds4vvmpi_ve_miaoda', // 阿黄:贝雷帽+背包
tank: '.../aadkwdtzotijo_ve_miaoda', // 铁头:钢盔
scout: '.../aadkwdu52jwci_ve_miaoda', // 快羽:红棒球帽
};
My job was art direction and integration: prompt the style once, hold it across 42 assets, wire the sheets into the engine's 8-direction system. The models did the drawing and the coding.
Demo
🎬 Watch the 67-second gameplay demo: https://youtube.com/shorts/vcrDhp-KuGg?si=RlrnwNCgE5lc5Tkz
67 seconds of real gameplay from the running web build: WASD movement, mouse-aim shooting, duck-vs-duck combat with +20 kill popups, "press E to loot" prompts, full HUD (health/ammo/timer/minimap). No scripted trailer — this is the game playing.
Code
The full repo will be public after the deadline rush. The two systems above are the heart of it:
-
Sprite pipeline (
src/game/sprites.ts, 530 lines) — loads AI-generated 2×2 sprite sheets, chroma-keys white backgrounds and olive base discs via region growing, normalizes to 8-direction transparent sprites. Ships with per-sheetdiagOrdercorrection: if the model mislabels frame order on one sheet, you fix four numbers instead of regenerating. -
Engine (
src/game/engine.ts, ~6,300 lines) — game loop, enemy AI (patrol/chase/attack states), collision, HUD, minimap, desktop + mobile input layers. -
Art manifest (
src/game/art.ts, 69 lines) — every AI asset indexed by character/boss/weapon id, with commented rollback URLs for each art revision. The whole visual history of the project in one file.
Everything above was generated by open-weight models. My commits are prompts, selections, and wiring.
Who would pay for this, and why
- Indie devs who can't afford artists: 42 consistent sprites for $0 in marginal cost. The art department is now a prompt and a style bible.
- Solo devs who can't afford a team: a 6,300-line engine written by an open model you can self-host. The per-token meter is gone, so iteration 200 costs the same as iteration 1.
- The game itself: Duck Evac is heading to TapTap as a commercial release. The side hustle isn't the tooling — it's the game the tooling made possible.
The pitch: open weights turned a two-person studio (coder + artist) into one person with two models. Duck Evac is the receipt.
Top comments (0)