{"id":13733147,"url":"https://github.com/Bombfuse/emerald","last_synced_at":"2025-05-08T09:31:46.874Z","repository":{"id":37020902,"uuid":"253070632","full_name":"Bombfuse/emerald","owner":"Bombfuse","description":"A 2D rust game engine focused on portability.","archived":true,"fork":false,"pushed_at":"2024-11-24T19:53:19.000Z","size":16472,"stargazers_count":554,"open_issues_count":28,"forks_count":13,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-07T01:06:10.323Z","etag":null,"topics":["2d","game-development","game-engine","gamedev","physics","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Bombfuse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-04T18:26:36.000Z","updated_at":"2025-04-14T23:05:46.000Z","dependencies_parsed_at":"2023-12-19T12:06:45.967Z","dependency_job_id":"bb5e344d-e247-4f68-9971-656674085964","html_url":"https://github.com/Bombfuse/emerald","commit_stats":{"total_commits":299,"total_committers":11,"mean_commits":"27.181818181818183","dds":0.274247491638796,"last_synced_commit":"1dfebcda33499e32cf6a4fcbc010417213b567de"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bombfuse%2Femerald","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bombfuse%2Femerald/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bombfuse%2Femerald/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bombfuse%2Femerald/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Bombfuse","download_url":"https://codeload.github.com/Bombfuse/emerald/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253036510,"owners_count":21844223,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["2d","game-development","game-engine","gamedev","physics","rust"],"created_at":"2024-08-03T03:00:38.332Z","updated_at":"2025-05-08T09:31:45.572Z","avatar_url":"https://github.com/Bombfuse.png","language":"Rust","funding_links":[],"categories":["Game engines"],"sub_categories":[],"readme":"![Emerald](./assets/banner_large.png)\n[![Crates.io](https://img.shields.io/crates/v/emerald.svg)](https://crates.io/crates/emerald)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)\n[![Discord chat](https://img.shields.io/discord/829494628771168296.svg?label=discord%20chat)](https://discord.gg/NHsz38AhkD)\n\n\n# The Cross Platform Engine\n\nEmerald is designed to be as lightweight as possible, while remaining a fully-featured and cross-platform game engine.\n\nThe api is simple and powerful, giving you direct access to physics, audio, graphics, game worlds, and asset loading.\n\n## Supported Platforms\n\u003cdiv\u003e\n    \u003cimg alt=\"MacOS\" src=\"./assets/apple.svg\" width=32\u003e\n    \u003cimg alt=\"Linux\" src=\"./assets/linux.svg\" width=32\u003e\n    \u003cimg alt=\"Windows\" src=\"./assets/windows.svg\" width=32\u003e\n    \u003cimg alt=\"RaspberryPi\" src=\"./assets/raspberrypi.svg\" width=32\u003e\n\u003c/div\u003e\n\n\n--- Work in progress ---\n\u003cdiv\u003e\n    \u003cimg alt=\"Android\" src=\"./assets/android.svg\" width=32\u003e\n    \u003cimg alt=\"HTML5\" src=\"./assets/webassembly.svg\" width=32\u003e\n\u003c/div\u003e\n--------------------------\n\n\n\n## Asset Loading\n```rust\nlet my_sprite = emd.loader()\n    .sprite(\"my_sprite.png\")\n    .unwrap();\n\nlet my_audio = emd.loader()\n    .sound(\"my_sound.wav\")\n    .unwrap();\n```\n\n\n## Physics\n\n### Creating Bodies\n```rust\n    let entity = emd.world().spawn((Transform::from_translation((0.0, 0.0))));\n\n    let body_handle = emd.world().physics().build_body(\n        entity,\n        RigidBodyBuilder::dynamic()\n    );\n\n\n    emd.world().physics().build_collider(\n        body_handle,\n        ColliderDesc::cuboid(6.0, 6.0)\n    );\n\n    // You can alternatively build both the entity and body at once.\n    let (entity, body_handle) = emd.world()\n        .spawn_with_body(\n            (Transform::from_translation((0.0, 0.0))),\n            RigidBodyBuilder::dynamic()\n        )?;\n```\n\n### Physics Stepping\n\n```rust\n\n    emd.world()\n        .physics()\n        .step();\n```\n\nYou decide when physics steps!\nThis makes it very easy to \"pause\" the game without needing to alter any data.\n\n## Graphics\n\nThe default method to draw the game is to draw all of the entities in the current world. However, you can write your own `draw` function if you need to do more!\n\n```rust\nfn draw(\u0026mut self, mut emd: Emerald) {\n    emd.graphics().begin();\n\n    emd.graphics().draw_world();\n\n    emd.graphics().render();\n}\n```\n\n## Audio\n```rust\nlet my_sound = emd.loader().sound(\"sounds/my_song.ogg\")?;\n\nemd.audio().mixer(\"background_music\")?.play_and_loop(my_sound);\n```\n\n## ECS\n\nEmerald uses the [Entity Component System](https://en.wikipedia.org/wiki/Entity_component_system) paradigm for creating, managing, and updating game entities.\n\nEmerald uses [Hecs](https://github.com/Ralith/hecs) under the hood for  fast entity iteration, and a remarkably clean query Api.\n\nMore detailed features can be found in the [Hecs documentation](https://docs.rs/hecs/).\n\n```rust\nfor (id, (sprite, mut position)) in emd.world().query::\u003c(\u0026Sprite, \u0026mut Position)\u003e().iter() {\n    position.x += 10.0;\n}\n```\n\n## [Aseprite](https://www.aseprite.org/)\n\nEmerald has built in aseprite loading and rendering. Simply load in the file, then tell it which animations to play.\n\n```rust\nlet mut aseprite = emd.loader().aseprite(\"my_sprite.aseprite\").unwrap();\n\naseprite.play(\"some_aseprite_animation\");\n\nemd.world().spawn((aseprite, Position::zero()));\n```\n\nAlternatively, Emerald can load a sprite sheet exported from aseprite.\n\n```rust\nlet mut aseprite = emd.loader()\n    .aseprite_with_animations(\"my_texture.png\", \"my_animation.json\").unwrap();\n```\n\nExport settings\n![Preferred export settings](./assets/aseprite_settings.png)\n\n\n\n## [WASM](https://webassembly.org/) (WIP, PROBABLY BROKEN RIGHT NOW)\n\n### Build\n\n`cargo build --target wasm32-unknown-unknown`\n\n### Asset Loading\n\nIn order to keep a clean, simple API, and avoid network requests for assets. Emerald takes the approach of packing all necessary assets into the WASM binary.\n\nThis same method can be used to pack all assets into the game binary regardless of which platform you target.\n\nUse the `pack_asset_bytes` function to load data into the engine.\n\n```rust\nfn initialize(\u0026mut self, mut emd: Emerald) {\n    /// Pack all game files into WASM binary with path references\n    /// so that the regular file loading Api is supported.\n    #[cfg(target_arch = \"wasm32\")]\n    {\n        emd.loader()\n            .pack_asset_bytes(\n                \"bunny.png\",\n                include_bytes!(\".bunny.png\").to_vec()\n            );\n    }\n\n    /// We can now load texture/sprites via the normal Api,\n    /// regardless of which platform we're targeting.\n    let sprite = emd.loader()\n        .sprite(\"bunny.png\")\n        .unwrap();\n    \n    // Default transform at 0.0, 0.0\n    let mut transform = Transform::default();\n\n    self.count = 1000;\n    emd.world().spawn_batch(\n        (0..1000).map(|_| {\n            transform.translation.x += 6.0;\n            transform.translation.y += 1.0;\n            let mut s = sprite.clone();\n            (transform.clone(), s, Vel { x: 5.0, y: 3.0 })\n        })\n    );\n}\n```\n\n## Android (WIP, PROBABLY BROKEN RIGHT NOW)\n\n### Asset Loading\n\nAdd following to `Cargo.toml` and load assets as usual:\n```\n[package.metadata.android]\nassets = \"YOUR_ASSETS_DIRECTORY/\"\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FBombfuse%2Femerald","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FBombfuse%2Femerald","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FBombfuse%2Femerald/lists"}