EN /HU | Login

Bevy

Bevy is an open source, data-driven game engine written in Rust. State lives in components, and plain Rust functions ("systems") run over them in parallel — this is ECS. There is no visual editor: a project is a Cargo crate, which fits a Makefile + CI workflow well. WebAssembly is first-class, so the same code runs natively and in the browser.

Website: https://bevyengine.org

Tutorials


Makefile

Native builds are plain cargo build. Web builds target wasm32-unknown-unknown and run wasm-bindgen for the JS glue. The index.html shell is downloaded at export time, so every game uses the same loader.

Templates are in bevy-tools: copy example-makefile.make to Makefile and set PROJECT to the crate name from Cargo.toml.

Version pinning matters. The wasm-bindgen CLI and the wasm-bindgen crate must be the same version:

TOML
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "=0.2.100"

Keep WASM_BINDGEN_VERSION in the Makefile in sync. The CI image (git.teletypegames.org/build/bevy-builder) ships the matching CLI — rebuild it with a new --build-arg WASM_BINDGEN_VERSION when you bump.

Variables

Variable Description Default
PROJECT Project / crate name bevydemo
WASM_BINDGEN_VERSION CLI version, must match Cargo.toml 0.2.100
BIN_DIR Native binary bin
DIST_DIR Exported artifacts dist
VERSION_FILE Version file for CI .version
INDEX_HTML_URL HTML shell bevy-tools web/index.html

Targets

SH
make build                   # cargo build --release -> bin/$(PROJECT)
make run                     # cargo run
make wasm                    # release wasm + wasm-bindgen -> dist/game.js, dist/game_bg.wasm
make export VERSION=1.0.0     # wasm + index.html zipped as bevydemo-1.0.0.html.zip
make watch                   # rebuild on change under src/ (needs fswatch)
make clean                   # remove bin/, dist/ and target/

make wasm needs the target and the CLI:

SH
rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli --version 0.2.100

VS Code

Copy example-tasks.json to .vscode/tasks.json. Tasks: Run (default, Cmd+Shift+B), Build & Run, Build WASM, Make build.

Generated artifacts

File Description
bin/bevydemo Native release binary
dist/game.js, dist/game_bg.wasm wasm-bindgen output (packaged, then removed)
bevydemo-<version>.html.zip Web build
bevydemo-<version>-win-x64.zip Windows build (mingw cross-compile)
bevydemo-<version>-linux-x64.zip Linux build (glibc)

Requirements

Local only: make, git, jq, zip, curl, the Rust toolchain with the wasm32-unknown-unknown target, a matching wasm-bindgen CLI, and fswatch for watch mode. CI images bring their own tools.


Pipeline

The pipeline is not in the game repo. Woodpecker asks the update server, and WarpEngine serves the whole config from /build/config (template lib/warp_engine/ci/woodpecker/platforms/bevy/pipeline.yaml.erb).

The repo needs three things:

YAML
# .woodpecker.yaml
platform: bevy
name: bevydemo   # only when the software name differs from the repo name
  • metadata.json
  • the application_token Woodpecker secret: a WarpEngine ApplicationToken with update + upload scopes

Builder images come from the update server's ci_platforms config. On teletypegames.org the builder is bevy-ttg: the bevy-builder image with the crates of every TTG Rust project preloaded into the cargo registry, so the build steps no longer download several hundred crates each (a new dependency is still downloaded as usual). The helper steps (version, upload, publish) run in the ci-tools image, which has git, jq, curl and zip preinstalled, so they install nothing. Preview the served pipeline:

SH
curl "https://teletypegames.org/build/config?platform=bevy"

Steps

Step What it does
1. version the engine's shared step (since WarpEngine 1.7): the version from metadata.json; on a tag a version tag has to match it; outside the repo's default branch and on a dev-<branch> tag dev-<version>-<branch>, with no version dev-<commit>; write .version
2. build in the builder image (bevy-ttg on teletypegames.org): wasm build + wasm-bindgen, packed as the versioned zip
3. binaries native linux-x64 (glibc) and win-x64 via mingw (x86_64-pc-windows-gnu)
4. upload on the tag only: web zip, binary zips and <name>-<version>.metadata.json via POST /build/upload, X-Update-Secret header
5. publish on the tag only: POST /build/publish?platform=bevy
6. tag the engine's shared step (since WarpEngine 1.9), after a push only: a new version in the source gets its v<version> tag, whose pipeline runs the steps marked on the tag only; a version tagged already releases nothing; a dev build moves the branch's dev-<branch> tag onto the commit, so the newest dev build is published. See Versions and releases on the WarpEngine page

Raising the version is the release: a push builds and tags, and the tag's pipeline uploads and publishes (WarpEngine 1.9). A push that leaves the version as it is only builds.

The builder image is a debian Rust toolchain with the wasm32-unknown-unknown and x86_64-pc-windows-gnu targets, mingw-w64 and the wasm-bindgen CLI preinstalled, built from builder.Dockerfile in bevy-tools.

Binary details:

  • An assets/ directory is packaged next to the binary — Bevy loads it at runtime, it is not embedded.
  • No mac build: darwin cross-compilation needs osxcross, the same planned toolchain as the ebitengine mac targets.
  • The API registers the <name>-<version>-<slug>.zip files as win_x64 / linux_x64 release assets.
  • A cold Bevy release build compiles several hundred crates, so expect a much longer build step than the other engines.

Demo project

bevy-demo — animated "TELETYPE GAMES" wave text on Bevy 0.16, the same demo as ebitengine-demo.