OhMyGame
OhMyGame is the open-source studio for making games with AI. Design, build, playtest, and publish games in one app, with your own model keys.
3D action game / browser SPA — documentation
Translation pending
GamesTypeScript · CSSGitHub @FlopsstuffOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
It is allowed to rob caravans
Translation pending
Loading the full README.
Read the full README ↗🎮 Live app: https://korovany.aimost.pl/ · 📚 Docs: https://flopsstuff.github.io/korovany/
3D action game / browser SPA.
Stack: TypeScript · React 19 · Babylon.js · Redux Toolkit · Vite 6. App deploys to Cloudflare Pages; docs deploy to GitHub Pages — both via GitHub Actions.
git lfs install # one time per machine (binary assets use Git LFS)
npm install
npm run dev # dev server (http://localhost:5173)
npm test # run the test suite (Vitest)
npm run build # type-check + production build into ./dist
npm run preview # serve the production build locally
npm run docs:dev # preview the documentation site
These apply to every contributor — human or agent. Full version:
docs/guide/project-rules.md. For automated
contributors see AGENTS.md and CLAUDE.md.
strict, no any. React function components only; 3D via
Babylon.js; shared state via Redux Toolkit slices in src/store/.flo-<issue>-<slug>); keep main green and deployable;
reference the issue in commits.npm test
runs in CI and must pass.docs/ in the same change;
it auto-publishes to GitHub Pages..gitattributes): source binaries in
/assets, bundled assets in src/assets/.src/app/ app shell & composition src/store/ Redux Toolkit store + slices
src/engine/ Babylon Engine/Scene lifecycle src/scenes/ Babylon scenes & canvas wrapper
src/game/ engine-agnostic game logic src/components/ reusable React UI
src/assets/ bundled assets src/hooks/ shared React hooks
assets/ source binaries (Git LFS) src/types/ shared types
public/ static files served as-is docs/ VitePress docs → GitHub Pages
See docs/guide/architecture.md for where new code belongs.
The game renders into a full-window 3D canvas — the document never scrolls
and there is no max-width container (src/styles/global.css resets
html/body/#root and hides overflow). React overlays sit above the canvas for
the HUD, main menu, and pause screen. The app boots into the main menu; New
Game enters play, Continue resumes the latest save (see
Saving progress), ESC toggles playing ⇄ paused, M
(or the HUD Travel button) opens the world map (see
World map & fast-travel), and B spends a carried
bandage to stop bleeding from a severed limb (see
docs/guide/health-system.md).
The Babylon Engine/Scene lifecycle lives in src/engine/,
not inline in a component. createGameEngine(canvas) owns engine + scene
creation, the high-DPI resize handler (setHardwareScalingLevel(1 / devicePixelRatio)
so the canvas stays crisp on retina), the render loop, and dispose().
src/scenes/GameCanvas.tsx is a thin React wrapper
that mounts the engine against a ref'd canvas and disposes it on unmount.
New Game drops the player into the forest with a HUD objective — Raid 3
caravans — and a running Score (kills + loot). Raiding all three caravans
shows an explicit win screen; dying shows a lose screen. Both offer
Restart (a fresh run) and Main Menu. The win/lose decision is a pure,
unit-tested state machine (src/game/objective/objectiveMachine.ts) that drives
the app phase into won/lost; per-run progress and score live in
gameSlice. Full details: docs/guide/objective-loop.md.
A bottom-centre minimap radar shows the player (with a facing indicator), the
caravans to raid (gold), and threats (red) on a top-down map of the play area, so
the objective is always findable. Live positions stay scene-owned and are pushed
to the HUD on a throttled ~10 Hz bridge (no per-frame Redux/React updates). Full
details: docs/guide/minimap.md.
The world has four zones (Human lands, Empire, Forest, Mountains). During
play, press M or click the HUD Travel button to open the world-map overlay
and fast-travel between the zones that have a playable scene. Selecting a
zone shows a Travel/Cancel confirm; on confirm the player is teleported to that
zone's spawn and its scene is mounted.
E3.1 ships Forest (the vertical slice) and a Human-lands stub as
available; Empire and Mountains are listed but locked until their scenes
exist. The zone registry lives in src/game/world/ and the
current zone id is persisted in saves. Full details:
docs/guide/world-map.md (lore/layout targets in
docs/guide/world-specs.md).
Raiding caravans (the "грабить корованы" loop) drops loot the player collects into a carried inventory, shown in a HUD panel below the health bar while playing (E3.4).
itemId → count map plus one equipped slot
lives in src/game/economy/; the Redux integration is
src/store/inventorySlice.ts. Item display
names/flags come from the static catalog in
src/game/economy/items.ts — the save stores only
ids + counts, so adding a lootable good is a catalog entry with no schema bump.pickUpLoot({ itemId, count });
the HUD panel reflects the carried stacks, marks the equipped item, and shows an
explicit empty state before any loot is collected.Money is gold pieces — and gold is just a carried item, so looted coin is
spendable coin (no separate wallet, no save-schema bump). Each catalog item has a
base value; merchants sell at that value and buy back at a markdown.
buy / sell
transactions move goods + gold and return a typed success/failure result —
both in src/game/economy/.buyItem / sellItem reducers and selectGold /
selectInventory selectors in
src/store/inventorySlice.ts. Failed trades are
a no-op.docs/guide/economy.md.Binary game assets (GLB models, textures, audio) are stored in Git LFS — run
git lfs install once before cloning or committing.
meshy-3d skill: python tools/meshy-3d/meshy.py …
(text/image → GLB via the Meshy API; needs MESHY_API_KEY). See
tools/meshy-3d/SKILL.md.public/models/; Cloudflare
Pages serves them from its CDN at /models/<name>.glb.loadModel(scene, '/models/x.glb')
(src/scenes/modelLoader.ts), which normalizes
scale (longest side ≈ 2 units) and grounds the model on import. The returned
root is a clean placement node; scene code may set root.position without
erasing the internal grounding offset.Rationale and the import contract: docs/decisions/0001-asset-hosting.md
and 0002-glb-import-contract.md.
Player progress survives a browser reload. A small versioned snapshot — the
player's transform (position + yaw), health (current + max), zone id,
carried inventory, and character progression — is persisted to the browser's
IndexedDB (korovany-save database, one autosave slot).
clearSave(), or clearing the site's browser data).
Nothing is uploaded; saves are local to the browser.The schema is forever — fields are never renamed; format changes bump
SAVE_VERSION and add a migration. SAVE_VERSION is currently 3 (v2 added
inventory; v3 added progression; older saves migrate forward with empty /
baseline values). Full details, slot
model, and the test approach (fake-indexeddb):
docs/guide/save-system.md.
The game gives audible feedback for every action — enemy hit, enemy kill,
player taking damage, swing, win, and lose — through a tiny raw Web Audio bus
(src/game/audio/). SFX are synthesized procedurally (no
sample files, no Git LFS payload, no third-party licensing); the bus subscribes
to the existing combat event bridge rather than scattering playback calls.
Escape). Both persist
across reloads in localStorage under the korovany-audio key
({ muted, volume }; default { false, 0.7 }).AudioContext is created/resumed only on the first user gesture
(click or keypress) to respect browser autoplay policy — no autoplay warnings.Full design, the event map, and how to add a sound:
docs/guide/audio.md.
Two independent targets, both on push to main (details:
docs/operations/deployment.md):
.github/workflows/deploy.yml
(cloudflare/wrangler-action). PRs build + test but don't deploy. The deploy
step skips gracefully until the Cloudflare secrets exist, then activates
automatically; workflow_dispatch allows manual runs..github/workflows/docs.yml (VitePress).| Secret | What it is |
|---|---|
CLOUDFLARE_API_TOKEN | Cloudflare API token with the Cloudflare Pages: Edit permission |
CLOUDFLARE_ACCOUNT_ID | Your Cloudflare account ID |
Stored as GitHub Actions secrets (not project env vars) because the deploy
runs on GitHub's runners. Full credential playbook:
docs/operations/cloudflare-deploy.md.