../

Bevy Jam #1 data exploration

Published: , updated:


Intro

The first Bevy Jam offers an opportunity to look at how different people use Bevy (at least in the context of a game jam) - which features they use, which crates they use to augment Bevy, and also which asset types they use. This can help highlight commonly used features or dependencies that might encourage further development, or infrequently used or avoided features that may need better documentation, examples, or improvements.

Some summary highlights

Dependencies

These are the direct expressed dependencies of the game project, representing what the game developer directly interacted with. I somewhat-arbitrarily decided what were “game development-related” vs. general Rust or infrastructural crates.

Bevy-specific dependencies

These are 38 unique dependencies built to work directly with Bevy. Debugging (perhaps unsurprisingly?) was the most common category, and egui was a clear favourite. bevy_kira_audio was used for 9 of the 11 entries in the top 25 entries that had audio assets, showing a clear preference for skipping the built-in audio capabilities.

RankDependencyAll entriesTop 25 entriesCategoryDescription
1bevy-inspector-egui187DebuggingProvide ECS inspection via egui.
2bevy_kira_audio179AudioPlugin to use Kira, providing sound mixing and other features not available in the base audio plugin.
3heron155PhysicsErgonomic 2d/3d physics API using Rapier.
4bevy_asset_loader106AssetsPlugin to reduce boilerplate around asset loading, especially around game states transitions.
5bevy_egui105Debugging / UIPlugin to set up and manage egui usage
6bevy_prototype_lyon932D graphicsPlugin to use Lyon, a 2D graphics library in Rust using path tessellation.
6bevy_tweening93AnimationTweening animation plugin.
8benimator73AnimationPlugin for sprite sheet animation
8bevy_rapier2d73PhysicsPlugin to use Rapier’s 2D physics engine
10bevy_ecs_tilemap612D Games / TilemapsPlugin for tilemap rendering
11bevy_prototype_debug_lines50DebuggingPlugin providing a simple line drawing API
12bevy_embedded_assets32AssetsEmbeds assets into the binary for easier releases.
13bevy_ecs_ldtk312D Games / TilemapsPlugin to integrate with the LDtk 2D level editor
13bevy-web-resizer31RenderingAutomatically resizes app on the web to the size of the window
15bevy_framepace30RenderingPlugin to provide frame pacing and framelimiting
16bevy_console21DebuggingPlugin to support an on-screen debugging console
16bevy_loading21AssetsAsset loading progress tracking library
16bevy_mod_raycast213D GamesAllows easy 3D ray casting against meshes
16bevy_ninepatch21UISupport 9-patch images - let you have a UI that scales only the right parts of your images
16leafwing-input-manager21InputAn input manager providing an ergonomic interface over the lower-level input system in Bevy
21bevy_rapier3d20PhysicsPlugin to use Rapier’s 3D physics engine
21bevy_asset_ron20AssetsRegister arbitrary custom data to be loaded as an Asset, from files using the RON format.
23bevy-ui-build-macros11UIMacros to speed up the process of defining UIs
23bevy-debug-text-overlay11DebuggingConvenient debug text overlay plugin.
23bevy_mod_picking113D GamesPlugin for 3D mouse picking
23bevy-ui-navigation11UIUI navigation algorithm for the default UI library
23bevy-scene-hook11?Scene manager proof-of-concept
23bevy_easings11AnimationsEasings on components using interpolation.
23bevy_system_graph11?Utilities for creating strictly ordered execution graphs of systems
23bevy-egui-kbgp11Debugging / UIImproved keyboard and gamepad navigation and usage for egui
23bevy_polyline11RenderingPlugin that adds instanced rendering of Polylines
23bevy_ggrs11NetworkingPlugin for the GGRS P2P rollback networking library
33iyes_bevy_util10MiscellaneousMiscellaneous utilities from IyesGames
33bevy_ase10AssetsAsset loader for Asesprite files
33smooth-bevy-cameras10RenderingCollection of exponentially-smoothed camera controllers
33bevy_networking_turbulence10NetworkingNetworking plugin using on naia-socket and turbulence libraries.
33bevy_editor_pls10Debugging / CreationWIP editor-use-case tooling
33bevy_atmosphere10RenderingProcedural sky rendering plugin

Unsurprisingly, most entries used randomness, and most (43/55) used the rand crate. Perhaps surprisingly, many entries had no non-Bevy dependencies beyond that crate.

RankDependencyAll entriesTop 25 entriesCategoryDescription
1rand4519RandomnessRandom number generation with multiple generators across multiple generation types
2noise21NoiseProcedural noise generation library covering gradient, fBm, and Worley noise
2pathfinding21PathfindingImplementations of several pathfinding, flow, and graph algorithms
2fastrand21RandomnessPRNG using Wyrand
2big-brain21AIUtility AI library for games
2rand_chacha21RandomnessCryptographically secure random number generation using ChaCha
7spirv-std20RenderingThe rust-gpu ecosystem, allowing Rust as a language for GPU graphics and compute shaders. (Also spirv-builder, spirv-std-macros)
8alea11RandomnessPRNG using Wyrand
8splines11?Spline interpolation
8tiled11LevelsManaging maps build with the Tiled map editor (or something else that supports that format)
8ggrs11NetworkingP2P rollback networking library
8impacted11Physics2D collision testing (has Bevy interop through optional features)
8interpolation11Animation+Interpolating between two numbers (finding points between on some non-uniform scale, often curves)
8getrandom11RandomnessUse operating system-sourced random data
8matchbox_socket11NetworkingP2P WebRTC networking for rust wasm applications
15names10RandomnessRandom name generation

Bevy feature usage

Plugins and features

PluginAll entriesTop 25 entriesDescription
DefaultPlugins5622The default set of commonly used built-in plugins
NodeBundle3315Bevy UI’s node-based UI element
FrameTimeDiagnosticsPlugin105A plugin that populates diagnostics about frame time and fps
LogDiagnosticsPlugin84A plugin that outputs diagnostics to logs
FixedTimestep81Used for attaching actions at a fixed time step, rather than time taken for frames.
MaterialMesh2dBundle31Custom 2D material (custom shaders)
MaterialPlugin21Custom material (3D)

Cameras

This one is a bit of a stretch - just looked at whether PerspectiveCameraBundle or OrthographicCameraBundle were present (preferring perspective), and if ::new_2d() or ::new_3d() were used (preferring the latter).

CameraAll entriesTop 25 entries
Orthographic (2D)4317
Perspective (3D)104
Orthographic (3D)10

Assets

Asset Categories

Unsurprisingly, most entries used fonts and images. Fewer than half of games used audio. Using external level editors was infrequent, as well as imported shaders.

Asset CategoryAll entriesTop 25 entries
Font4719
Image4418
Audio2511
Model95
Level42
Shader42
Data31

Font asset formats

Fonts were the most frequently used asset category, and roughly 50 unique font faces were used over all entries, while the top 25 entries used roughly 25 different font faces. Fira Sans (13) and Fira Mono (9) were the only faces used by more than 2 entries.

Asset FormatAll entriesTop 25 entries
TrueType (ttf)4417
OpenType74

Image asset formats

PNG dominates for plain images/textures, while Aseprite is the infrequently used sprite format.

Asset FormatAll entriesTop 25 entries
PNG4217
Aseprite51
JPEG22
Gimp (xcf)10
.ico10

Audio asset formats

Asset FormatAll entriesTop 25 entries
Ogg189
Wav113
Mp31

Model asset formats

The binary GLTF variant is preferred, although not many entries used 3D model assets

Asset FormatAll entriesTop 25 entries
GLTF Binary (glb)95
GLTF JSON (gltf)32
Blender11

Level asset formats

Not many projects used level assets authored externally, but LDtk was slightly preferred over Tiled.

Asset FormatAll entriesTop 25 entries
LDtk31
Tiled11

Shader asset formats

Asset formatAll entriesTop 25 entries
WGSL22
SPIR-V20

Game dependency and asset data

RankTitleDependenciesImage AssetsAudio AssetsModel AssetsOther Assets
1Petty Partybevy_kira_audio, randAseprite: 1, Png: 26Ogg: 26Ttf: 2
2¿Quién es el Mechaburro?bevy-inspector-egui, bevy_kira_audio, leafwing-input-manager, noise, randPng: 23Ogg: 1, Wav: 12Glb: 12, Gltf: 4Ttf: 4
3Chaz
4Warlock’s Gambitbevy-debug-text-overlay, bevy-inspector-egui, bevy-scene-hook, bevy-ui-build-macros, bevy-ui-navigation, bevy_kira_audio, bevy_mod_raycast, enum-map, fastrandJpeg: 1, Png: 25Ogg: 10Glb: 2Otf: 1
5Cheaters Never Winbevy-inspector-egui, bevy_kira_audio, bevy_loading, bevy_ninepatch, bevy_rapier2d, bevy_tweening, rand, ron, serdePng: 75Ogg: 19Otf: 1, Ttf: 4
6Undoingfutures-lite, itertools, randPng: 23Ogg: 6Ttf: 1
7Bringing a Mirror to a Lazor Fight
8Beelinebenimator, impacted, rand, strum, strum_macrosPng: 27Tsv: 8, Ttf: 1
9Unfair Coloring Competitionasync-channel, async-compat, base64, bevy_egui, bevy_prototype_lyon, futures-lite, getrandom, graphql_client, js-sys, rand, reqwest, serde, tokio, wasm-bindgen, wasm-bindgen-futuresPng: 3Ttf: 1
10Cleansebevy_asset_loader, bevy_easings, bevy_egui, bevy_embedded_assets, bevy_rapier2d, rand, strum, tracingPng: 21Ogg: 8Wgsl: 2
11Redistrictingbevy-inspector-egui, randTtf: 2
12Confluence of Futilitybevy_asset_loader, bevy_console, bevy_egui, bevy_kira_audio, bevy_polyline, bevy_tweening, bitflags, heron, pathfinding, rand, splinesJpeg: 20Ogg: 57Glb: 8, Gltf: 7Ttf: 2, Wgsl: 5
13Foretoldbevy_egui, bevy_kira_audio, bevy_mod_picking, randPng: 18Wav: 2Blender: 3, Glb: 12Ttf: 1
14The Last Climbbevy_ecs_ldtk, bevy_kira_audio, console_error_panic_hook, randPng: 17Ogg: 13Ldtk: 2, Ttf: 1
15A Janitor’s Nightmarebevy-web-resizer, bevy_asset_loader, bevy_ggrs, bevy_system_graph, bytemuck, derive_more, ggrs, log, matchbox_socket, rand, rand_chacha, web-sysPng: 32Ttf: 4
16GerrymanderingrandPng: 3Otf: 1
17Tug of Ballbevy-inspector-egui, bevy_extensions, bevy_prototype_lyon, bevy_time, bevy_tweening, big-brain, heron, interpolation, randPng: 20Otf: 1, Ttf: 2
18Typey Birbbevy-inspector-egui, bevy_asset_loader, randOgg: 7Glb: 2Ttf: 1
19Build A Better BuddyrandPng: 18Ttf: 4
20Earth Escapebevy_embedded_assets, heron, image, rand, wasm-bindgen, winit
21Immune
22Power UnLichetedalea, bevy_asset_loader, bevy_ecs_tilemap, bevy_kira_audio, heron, itertoolsPng: 14Wav: 6Ttf: 1
23Pogo Hurdlingbenimator, bevy-egui-kbgp, bevy_asset_loader, bevy_kira_audio, bevy_rapier2d, embed-resource, rand, winitPng: 3Ttf: 1
24Super unfair multiball Pong (bevy-jam#1)bevy-inspector-egui, bevy_prototype_lyon
25Brave Crabbenimator, heron, instant, rand, tiledPng: 6Tiled: 3, Ttf: 1
26UnfairAdvantage
27Fortunabevy-inspector-egui, bevy_asset_loader, bevy_ecs_ldtk, bevy_framepace, randPng: 12Ldtk: 1, Otf: 1
28Stars iobevy-inspector-egui, bevy-web-resizer, bevy_prototype_lyon, rand, rand_distrPng: 3Ttf: 1
29pong-fighterbenimator, bevy_asset_loader, bevy_kira_audio, heron, ordered-float, rand, wasm-bindgenPng: 8Wav: 7
30Protect your believers!
31Attack of the Fluorescent SquaresPng: 4Ttf: 1
32Angry Apesbevy_embedded_assets, bevy_prototype_lyon, instant, lyon_tessellation, rand, rand_distrPng: 37Ttf: 1
33Double Dodge!randTtf: 2
34Bevy Tagbevy_kira_audio, bevy_prototype_lyon, bevy_tweening, heron, randWav: 5Otf: 1, Ttf: 1
35shitty bot gameanyhow, bevy_asset, enum-repr, serde, serde_jsonJson: 1, Ttf: 2
36Wasting Timebevy_asset_loader, bevy_rapier2dPng: 9Otf: 1, Ttf: 1
37Hivemindbevy_console, bevy_ecs_tilemap, bevy_egui, bevy_prototype_debug_lines, bitflags, float-ord, nanoserde, noise, randPng: 59Ttf: 2
38Dog Life
39Bevy Sports: Unfair Tennis
40Marmalade
41Quick Warriorbenimator, bevy-inspector-egui, bevy_ecs_tilemap, embed-resource, heron, rand, winitAseprite: 5, Png: 40Ttf: 1
42Nothing Movesbevy_tweening, randPng: 1Ttf: 1
43Life of a Mini Boss
44Unfair Boss Chaosbevy-inspector-egui, bevy_prototype_debug_lines, bevy_rapier2d, console_error_panic_hook, futures, futures-lite, md5, rand, serde, serde_derive, wasm-bindgen, wasm-bindgen-futures, web-sysPng: 3Wav: 1Ttf: 1
45duelbevy_rapier2d, instant, randPng: 12Mp3: 6, Ogg: 6Ttf: 2
46Unfaireumbevy-web-resizer, bevy_kira_audio, randPng: 12Wav: 6Ttf: 1
47Whack A Bevybevy_egui, egui, rand, rand_chachaPng: 14
48Absconderbenimator, bevy_asset_loader, bevy_asset_ron, bevy_kira_audio, bevy_loading, bevy_ninepatch, bevy_prototype_debug_lines, bevy_tweening, enum-iterator, heron, iyes_bevy_util, rand, serde
49Bavy Ballsbevy_rapier3d, rand, smooth-bevy-camerasPng: 1Ogg: 1Ttf: 1
50Unfair Snek
51Bounce
52Car Con Calamity: Aviation Humiliation
53ROYAL BATTLE BEVYSTEINbevy_mod_raycast, big-brain, bitflags, bytemuck, clap, futures, heron, image, names, rand, rocket, serde, serde_json, tokio, wgpuPng: 6Glb: 1Ttf: 1
54Rise Above
55StickyfastrandGlb: 1, Gltf: 1Ttf: 4
56Ad_Optbenimator, bevy-inspector-egui, bevy_ase, bevy_rapier2d, embed-resource, image, winitAseprite: 7, Ico: 1Ttf: 1
57☄ Super Kaizen Overloaded ☄anyhow, bevy-inspector-egui, bevy_atmosphere, bevy_kira_audio, bevy_prototype_debug_lines, bevy_tweening, heron, leafwing-input-manager, parking_lot, rand, serde, serde_jsonPng: 10Ogg: 4, Wav: 1Glb: 1Json: 1, Ttf: 3
58Ravecrab Card Battlerbevy_asset_ron, bevy_kira_audio, rand, serdePng: 11Ogg: 2, Wav: 2Ttf: 1
59Slime Hordebevy-inspector-egui, bevy_ecs_tilemap, bevy_editor_pls, bevy_egui, bevy_prototype_lyon, heron, pathfinding, rand, sha2Png: 8Ogg: 1Ttf: 2
60Rusty Pirates
61Webwelho
62Bevy Cursed Tombanyhow, bevy-inspector-egui, bevy_ecs_tilemap, bevy_egui, bevy_kira_audio, heron, rand, xshellPng: 6Ogg: 1, Wav: 1Ttf: 1
63Dicey Dungeonsbevy_egui, directories-next, num-complex, num-traits, rand, ron, serdeAseprite: 11, Png: 11, Xcf: 1Wav: 1Ttf: 1
64Unfair game without Advantage
65You’re a Heckin’ Wizard
66Space Wizard Power Tournamentbevy_ecs_ldtk, bevy_ecs_tilemap, bevy_egui, bevy_prototype_lyonPng: 3Ldtk: 1
67You, eh?arboard, bytemuck, egui, once_cell, thread_local, version-sync, webbrowser, wgpu, winitPng: 2
68Sunflower PickingrandOgg: 1
69bevy-jamanyhow, bevy-inspector-egui, bevy_framepace, bevy_tweening, bytemuck, heron, parity-scale-codec, rand, spirv-builder, spirv-std, spirv-std-macros, xflags, xshellPng: 1Spirv: 1, Ttf: 6
70Injectanyhow, bevy-inspector-egui, bevy_framepace, bevy_tweening, bytemuck, heron, parity-scale-codec, rand, spirv-builder, spirv-std, spirv-std-macros, xflags, xshellPng: 1Spirv: 1, Ttf: 6
71Yo ho ho, and an alien gun!bevy_prototype_debug_lines, bevy_rapier3d, randOgg: 5Glb: 4Ttf: 1
72Birds and Crustaceansbevy-inspector-egui, bevy_kira_audio, bevy_networking_turbulence, bevy_prototype_lyon, cfg-if, glam, instant, num-traits, rand, serde, serde_json, shared, structoptPng: 4Ogg: 5Ttf: 1
73ROOMBA SNAIL DEFENCEanyhow, flume, futures, futures-util, serde, serde_json, tokio, tokio-stream, warpAseprite: 10, Png: 11Ttf: 1
74No Colider

Methodology

This ended up being a single Rust binary that does all the work, with caching of external data to both be a good citizen and to speed up iteration. There are two main phases of collection - fetching information from itch.io, and then looking at the source code - and then reporting.

itch.io data

Itch.io was the platform used to host the jam, and while it doesn’t have official APIs for getting jam data. Luckily, the entries page is actually built client-side, and fetches the data for the entries via JSON - https://itch.io/jam/316945/entries.json. Note that this URL has the jam ID in it (316945, not the vanity name (bevy-jam-1). This entries page (and the data that backs it) doesn’t include rankings, which is on the results page. The results page renders server-side, but there happens to be an easily-guessed JSON file with the data - https://itch.io/jam/316945/results.json. Both of these could be fetched without authentication, so they could be fetched from code, and deserialized using serde_json. For all URL retrieval, reqwest was used, with a simple on-disk cache to prevent fetching the same resource more than once, and a sleep between fetches (both of which are probably easy to do with middleware).

The Bevy Jam encouraged, but did not require, source code to be provided for the software. Unfortunately, Itch.io doesn’t appear to provide a way to structurally denote things like a link to the source code, and so none of the internal APIs provide any such thing. There are two URLs available from here per entry - the entry page specific to this jam, and the general game page. The entry page doesn’t appear to have any useful information on it, but the general game page has freeform information from the game’s developers, as well as potentially download links. Using the scraper crate, all the links in the downloaded game pages could be examined for potentially being a link to a code hosting platform. GitHub appeared to be the only platform used for the jam. (It’s possible some entries used download links, but a spot-check showed these were largely used for binaries.)

Source data

With homogenous usage of Git repositories for code, the git2 crate could be used to fetch the repositories (with a simple on-disk cache). The cargo-metadata crate could be used to extract the dependencies from the Cargo.toml files (with a simple fix-up for one case where the file was named the lower case cargo.toml). Asset data could be found using the walkdir crate to traverse the source code, focusing on any assets folders. Finally, the grep crate from ripgrep could be used to find simple regex patterns in files to discover use of particular cameras, plugins, and so forth.

Reporting

This was largely done with plain text, although for the main table, the comrak crate was used to generate the Markdown table in Markdown.

Further work

In an ideal world, something like Tree Sitter could be used to examine the source code to be able to answer questions like “what are all the structs used from bevy modules by this repository”, or look at initialization for particular structs to tell if they’re configured for 2D or 3D usage.

There was another Rust game jam using the Itch.io platform, the Rusty Game Jam, which could probably be evaluated using very similar approaches. Trying to do this for something like Ludum Dare would require a different approach - besides being a different platform, only a small subset of entries use Rust, and it may be hard to discover this. Perhaps this could be attempted by using a compiled list of Rust games from a source like Reddit or Twitter.