yuuna-engine
v0.7.0
Published
A lightweight, state-machine-based TypeScript game engine for quick prototypes. Runs directly in the browser.
Maintainers
Readme
Yuuna
Live demo & playground · GitHub
A lightweight, state-machine-based TypeScript game engine — drop it into a
page and it's running, no editor or build step required. You describe your
game as a state, a render(state) function, and a
nextState({ state, event, keyboard }) function — Yuuna owns the render
loop, input handling, and canvas drawing.
Install
npm install yuuna-engineQuick start
Add a canvas with id="yuuna" to your page:
<canvas id="yuuna"></canvas>Then describe your game as state + render + nextState:
import { runEngine } from "yuuna-engine";
// The shape of your game's data — whatever it takes to fully describe
// what's on screen and how it behaves
type GameState = { cookies: number };
// What that state looks like before anything has happened yet
const initialState: GameState = { cookies: 0 };
runEngine<GameState>({
initialState,
// Given the current state, what should be drawn this frame? Called
// every frame — always derive the picture from state, instead of
// reaching for the canvas directly.
render: (state) => ({
renderables: [
{
type: "TEXT",
text: `${state.cookies} cookies`,
color: "black",
position: { x: 100, y: 50 },
},
{
type: "CIRCLE",
id: "cookie",
isClickable: true,
color: "brown",
position: { x: 50, y: 50 },
radius: 25,
},
],
}),
// Given the current state and something that just happened, what's the
// next state? Called once per event (a click, a frame tick, ...) — the
// only place game logic lives.
nextState: ({ state, event }) => {
if (event.tag === "CLICK" && event.id === "cookie") {
return { cookies: state.cookies + 1 };
}
return state;
},
});Concepts
- Renderables — declarative shapes drawn each frame:
RECTANGLE,CIRCLE,TEXT,SPRITE,ANIMATED_SPRITE,LINE, andGROUP. Give one anidplusisClickable/isHoverableto make it interactive. - Events —
nextStatereceives oneGameEventper call:TIME,CLICK,HOVER_IN,HOVER_OUT,MOUSE_MOVE,MOUSE_LEAVE,MUSIC_END, or aCUSTOMevent of a type you define yourself, for reporting things like an asyncfetch()resolving back into your state machine. - Keyboard, camera, sprites & animation, sound effects & music,
canvas config, and mechanics pipelines all follow the same idea:
small, focused props and functions
runEngine/nextStatetake, that compose with everything above instead of replacing it.
This README stays intentionally thin — the full concept-by-concept reference, with every option and example, lives on the wiki. The playground also has a small, focused example for most of these you can run and edit directly.
Templates
Prefer a working starting point over typing the quick start out by
hand? Grab one from templates/:
- blank — a single
index.html, zero install — open it in a browser and it runs. - npm — TypeScript + a dev server with hot reload (via Vite), for a real local project.
- neutralino-desktop — the
npmtemplate wrapped in Neutralino to run as a native desktop window.
npx degit lucy-dot-exe/yuuna/templates/blank my-game
# or: npx degit lucy-dot-exe/yuuna/templates/npm my-game
# or: npx degit lucy-dot-exe/yuuna/templates/neutralino-desktop my-gamedegit copies the folder without
its git history — no cloning or forking the whole engine repo needed.
Each template's own README has more on running it once copied.
Made with Yuuna
- Yuuna's Heroes — a game made using Yuuna.
Development
yarn install
yarn build # builds lib/ (npm package) and dist/bundle.js (landing page)
yarn watch # rebuild on changedist/index.html is the landing page — it loads dist/bundle.js in the
browser via a global Yuuna object and embeds a live Monaco editor so
visitors can edit and run a game directly on the page.
Assets
The examples' art/sound/music lives in dist/resources/, gitignored
rather than committed — this repo being open source doesn't make every
asset in it free to redistribute. runEngine() falls back to a
generated placeholder for any image that isn't there (and simply plays
nothing for missing audio) instead of failing, so the examples still
run without them — just with placeholder art in place of the real
thing. Drop the real files in locally (or restore them from wherever
you got this repo from) to see them for real.
Currently used:
- Free Pixel Food! by Henry Software — the food icons in the Food Clicker and Sprites examples. CC0; credited here by choice, not requirement.
License
MIT © lucy-dot-exe
