{"id":33934103,"url":"https://github.com/lukexor/pix-engine","last_synced_at":"2026-04-05T01:31:25.727Z","repository":{"id":36971305,"uuid":"244057366","full_name":"lukexor/pix-engine","owner":"lukexor","description":"pix_engine is a cross-platform graphics \u0026 UI library for simple games, visualizations, digital art, and graphics applications written in Rust, supporting SDL2 (and soon Web-Assembly!) renderers.","archived":false,"fork":false,"pushed_at":"2026-02-14T23:10:19.000Z","size":62558,"stargazers_count":36,"open_issues_count":9,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-15T06:27:14.516Z","etag":null,"topics":["game-engine","gamedev","graphics","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lukexor.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-02-29T23:34:06.000Z","updated_at":"2026-02-14T23:08:53.000Z","dependencies_parsed_at":"2023-02-12T13:00:54.250Z","dependency_job_id":"da7a2738-c05a-466f-ace2-a5a3b93be43f","html_url":"https://github.com/lukexor/pix-engine","commit_stats":{"total_commits":676,"total_committers":3,"mean_commits":"225.33333333333334","dds":0.09467455621301779,"last_synced_commit":"874d58639daceaf582bfd436f3e1f3bdb5cb4e0d"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/lukexor/pix-engine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukexor%2Fpix-engine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukexor%2Fpix-engine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukexor%2Fpix-engine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukexor%2Fpix-engine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lukexor","download_url":"https://codeload.github.com/lukexor/pix-engine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukexor%2Fpix-engine/sbom","scorecard":{"id":604922,"data":{"date":"2025-08-11","repo":{"name":"github.com/lukexor/pix-engine","commit":"6a5492a02fd97c672cd3d06f0fcb204110a326d4"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Code-Review","score":0,"reason":"Found 1/20 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/outdated.yml:1","Warn: topLevel 'contents' permission set to 'write': .github/workflows/release-pr.yml:11","Warn: no topLevel permission defined: .github/workflows/triage.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":0,"reason":"binaries present in source code","details":["Warn: binary detected: lib/msvc/dll/32/SDL2.dll:1","Warn: binary detected: lib/msvc/dll/32/SDL2_gfx.dll:1","Warn: binary detected: lib/msvc/dll/32/SDL2_image.dll:1","Warn: binary detected: lib/msvc/dll/32/SDL2_mixer.dll:1","Warn: binary detected: lib/msvc/dll/32/SDL2_ttf.dll:1","Warn: binary detected: lib/msvc/dll/32/libFLAC-8.dll:1","Warn: binary detected: lib/msvc/dll/32/libjpeg-9.dll:1","Warn: binary detected: lib/msvc/dll/32/libmodplug-1.dll:1","Warn: binary detected: lib/msvc/dll/32/libmpg123-0.dll:1","Warn: binary detected: lib/msvc/dll/32/libogg-0.dll:1","Warn: binary detected: lib/msvc/dll/32/libopus-0.dll:1","Warn: binary detected: lib/msvc/dll/32/libopusfile-0.dll:1","Warn: binary detected: lib/msvc/dll/32/libpng16-16.dll:1","Warn: binary detected: lib/msvc/dll/32/libtiff-5.dll:1","Warn: binary detected: lib/msvc/dll/32/libvorbis-0.dll:1","Warn: binary detected: lib/msvc/dll/32/libvorbisfile-3.dll:1","Warn: binary detected: lib/msvc/dll/32/libwebp-7.dll:1","Warn: binary detected: lib/msvc/dll/32/zlib1.dll:1","Warn: binary detected: lib/msvc/dll/64/SDL2.dll:1","Warn: binary detected: lib/msvc/dll/64/SDL2_gfx.dll:1","Warn: binary detected: lib/msvc/dll/64/SDL2_image.dll:1","Warn: binary detected: lib/msvc/dll/64/SDL2_mixer.dll:1","Warn: binary detected: lib/msvc/dll/64/SDL2_ttf.dll:1","Warn: binary detected: lib/msvc/dll/64/libFLAC-8.dll:1","Warn: binary detected: lib/msvc/dll/64/libjpeg-9.dll:1","Warn: binary detected: lib/msvc/dll/64/libmodplug-1.dll:1","Warn: binary detected: lib/msvc/dll/64/libmpg123-0.dll:1","Warn: binary detected: lib/msvc/dll/64/libogg-0.dll:1","Warn: binary detected: lib/msvc/dll/64/libopus-0.dll:1","Warn: binary detected: lib/msvc/dll/64/libopusfile-0.dll:1","Warn: binary detected: lib/msvc/dll/64/libpng16-16.dll:1","Warn: binary detected: lib/msvc/dll/64/libtiff-5.dll:1","Warn: binary detected: lib/msvc/dll/64/libvorbis-0.dll:1","Warn: binary detected: lib/msvc/dll/64/libvorbisfile-3.dll:1","Warn: binary detected: lib/msvc/dll/64/libwebp-7.dll:1","Warn: binary detected: lib/msvc/dll/64/zlib1.dll:1","Warn: binary detected: lib/msvc/lib/32/SDL2.lib:1","Warn: binary detected: lib/msvc/lib/32/SDL2_gfx.lib:1","Warn: binary detected: lib/msvc/lib/32/SDL2_image.lib:1","Warn: binary detected: lib/msvc/lib/32/SDL2_mixer.lib:1","Warn: binary detected: lib/msvc/lib/32/SDL2_ttf.lib:1","Warn: binary detected: lib/msvc/lib/32/SDL2main.lib:1","Warn: binary detected: lib/msvc/lib/32/SDL2test.lib:1","Warn: binary detected: lib/msvc/lib/64/SDL2.lib:1","Warn: binary detected: lib/msvc/lib/64/SDL2_gfx.lib:1","Warn: binary detected: lib/msvc/lib/64/SDL2_image.lib:1","Warn: binary detected: lib/msvc/lib/64/SDL2_mixer.lib:1","Warn: binary detected: lib/msvc/lib/64/SDL2_ttf.lib:1","Warn: binary detected: lib/msvc/lib/64/SDL2main.lib:1","Warn: binary detected: lib/msvc/lib/64/SDL2test.lib:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE-APACHE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE-APACHE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/lukexor/pix-engine/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/lukexor/pix-engine/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/lukexor/pix-engine/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/lukexor/pix-engine/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/outdated.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/lukexor/pix-engine/outdated.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/outdated.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/lukexor/pix-engine/outdated.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-pr.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/lukexor/pix-engine/release-pr.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-pr.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/lukexor/pix-engine/release-pr.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-pr.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/lukexor/pix-engine/release-pr.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-pr.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/lukexor/pix-engine/release-pr.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/triage.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/lukexor/pix-engine/triage.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/triage.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/lukexor/pix-engine/triage.yml/main?enable=pin","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   8 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":8,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Warn: required approving review count is 1 on branch 'main'","Warn: codeowners review is not required on branch 'main'","Info: status check found to merge onto on branch 'main'","Info: PRs are required in order to make changes on branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 11 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-21T01:21:27.820Z","repository_id":36971305,"created_at":"2025-08-21T01:21:27.820Z","updated_at":"2025-08-21T01:21:27.820Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31421869,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T00:25:07.052Z","status":"ssl_error","status_checked_at":"2026-04-05T00:25:05.923Z","response_time":60,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["game-engine","gamedev","graphics","rust"],"created_at":"2025-12-12T13:25:34.072Z","updated_at":"2026-04-05T01:31:25.715Z","avatar_url":"https://github.com/lukexor.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Engine\n\n[![Build Status]][build] [![Doc Status]][docs] [![Latest\nVersion]][crates.io] [![Downloads]][crates.io] [![License]][mit]\n\n[build status]: https://img.shields.io/github/actions/workflow/status/lukexor/pix-engine/ci.yml?branch=main\n[build]: https://github.com/lukexor/pix-engine/actions/workflows/ci.yml\n[doc status]: https://img.shields.io/docsrs/pix-engine?style=plastic\n[docs]: https://docs.rs/pix-engine/\n[latest version]: https://img.shields.io/crates/v/pix-engine?style=plastic\n[crates.io]: https://crates.io/crates/pix-engine\n[downloads]: https://img.shields.io/crates/d/pix-engine?style=plastic\n[license]: https://img.shields.io/crates/l/pix-engine?style=plastic\n[mit]: https://github.com/lukexor/pix-engine/blob/main/LICENSE-MIT\n\n📖 [Summary](#summary) - 🌆 [Screenshots](#screenshots) - 🚀 [Getting\nStarted](#getting-started) - 🛠️ [Features](#features) - ⚠️ [Known\nIssues](#known-issues) - 💬 [Contact](#contact)\n\n## Summary\n\n`pix_engine` is a cross-platform graphics \u0026 UI library for simple games,\nvisualizations, digital art, and graphics applications written in [Rust][],\nsupporting [SDL2][] (and soon [Web-Assembly][wasm]!) renderers.\n\nThe primary goal of this library is to be simple to setup and use for graphics\nor algorithm exploration and is not meant to be as fully-featured as other,\nlarger graphics libraries.\n\nIt is intended to be more than just a toy library, however, and can be used to\ndrive real applications. The [Tetanes][] [NES][] emulator, for example uses\n`pix_engine` for rendering, window and event handling.\n\nSome examples of things you can create with `pix-engine`:\n\n- 2D ray casting of scenes or objects.\n- 2D games like Asteroids, Tetris, Pong, or platformers including sound effects,\n  music and UI elements.\n- Simple 3D scenes or games.\n- Audio playback and capture applications.\n- User interfaces for basic applications or configuration.\n- Algorithm visualizations for sorting, searching, or particle simulations.\n- Image viewing and editing.\n- Visual art.\n\n### Minimum Supported Rust Version (MSRV)\n\nThe current minimum Rust version is `1.67.0`.\n\n## Screenshots\n\n\u003cimg width=\"48%\" alt=\"Asteroids\"\nsrc=\"https://raw.githubusercontent.com/lukexor/pix-engine/main/images/asteroids.png\"\u003e\u0026nbsp;\u0026nbsp;\u003cimg\nwidth=\"48%\" alt=\"Maze Generation \u0026 A* Search\"\nsrc=\"https://raw.githubusercontent.com/lukexor/pix-engine/main/images/maze.png\"\u003e\n\u003cimg width=\"48%\" alt=\"2D Raycasting\"\nsrc=\"https://raw.githubusercontent.com/lukexor/pix-engine/main/images/2d_raycasting.png\"\u003e\u0026nbsp;\u0026nbsp;\u003cimg\nwidth=\"48%\" alt=\"UI Widgets\"\nsrc=\"https://raw.githubusercontent.com/lukexor/pix-engine/main/images/gui.png\"\u003e\n\u003cimg width=\"48%\" alt=\"Fluid Simulation\"\nsrc=\"https://raw.githubusercontent.com/lukexor/pix-engine/main/images/fluid_simulation.png\"\u003e\u0026nbsp;\u0026nbsp;\u003cimg\nwidth=\"48%\" alt=\"Matrix Rain\"\nsrc=\"https://raw.githubusercontent.com/lukexor/pix-engine/main/images/matrix.png\"\u003e\n\n## Getting Started\n\n### Installing Dependencies\n\nFirst and foremost you'll need [Rust][] installed! Follow the latest directions\nat \u003chttps://www.rust-lang.org/learn/get-started\u003e.\n\nWhen building or running applications for a desktop target such as `macOS`,\n`Linux`, or `Windows` and not a [Web-Assembly][wasm] target, you must install\n[SDL2][] libraries. Note for windows: You may need to install\n[Visual Studio C++ Build Tools][vc++].\n\nThere are several options for installing `SDL2`, but these are the most common:\n\n- Install via [homebrew][] for `macOS`, a package management tool like `apt` for\n  `Linux` or `MSVC` for `Windows`.\n\nFor more details and installation options see the [rust-sdl2][] documentation.\n\n#### macOS, Linux, or Windows 10 Subsystem for Linux (homebrew)\n\n```sh\nbrew install sdl2 sdl2_gfx sdl2_image sdl2_mixer sdl2_ttf\n```\n\n#### Linux (package manager)\n\nNote: The minimum `SDL2` version is `2.0.20`. Some package managers may not have\nthe latest versions available.\n\n_Ubuntu_:\n\n```sh\nsudo apt-get install libsdl2-dev libsdl2-gfx-dev libsdl2-image-dev\nlibsdl2-mixer-dev libsdl2-ttf-dev\n```\n\n_Fedora_:\n\n```sh\nsudo dnf install SDL2-devel SDL2_gfx-devel SDL2_image-devel SDL2_mixer-devel SDL2_ttf-devel\n```\n\n_Arch_:\n\n```sh\nsudo pacman -S sdl2 sdl2_gfx sdl2_image sdl2_mixer sdl2_ttf\n```\n\n#### Windows (MSVC)\n\n1. Download the latest `SDL2` `MSVC` development libraries from\n   \u003chttps://www.libsdl.org/download-2.0.php\u003e e.g. (`SDL2-devel-2.0.20-VC.zip`).\n2. Download the latest `SDL2_image`, `SDL2_mixer`, and `SDL2_ttf` `MSVC`\n   development libraries from\n   \u003chttps://www.libsdl.org/projects/\u003e. e.g. (`SDL2_image-devel-2.0.5-VC.zip`).\n3. Unzip each `.zip` file into a folder.\n4. Copy library files:\n   - from: `lib\\x64\\`\n   \u003c!-- markdownlint-disable-next-line line-length --\u003e\n   - to: `C:\\Users\\{Username}\\.rustup\\toolchains\\{current toolchain}\\lib\\rustlib\\{current toolchain}\\lib`\n     where `{current toolchain}` is likely `stable-x86_64-pc-windows-msvc`.\n     - _Note_: If you don't use `rustup`, See [rust-sdl2][] for more info on\n       Windows installation.\n5. Copy all `dll` files:\n   - from: `lib\\x64\\`\n   - to: your `cargo` project next to `Cargo.toml`.\n\nMSVC binaries for SDL2 are also present in this repository under the `lib`\nfolder.\n\n### Creating Your Application\n\nCreating a visual or interactive application using `pix-engine` requires\nimplementing only a single method of the [`PixEngine`][pixengine] trait for your\napplication: [`PixEngine::on_update`][pixengine::on_update] which gets executed as\noften as possible. Within that function you'll have access to a mutable\n[`PixState`][pixstate] object which provides several methods for modifying\nsettings and drawing to the screen.\n\n[`PixEngine`][pixengine] provides additional methods that can be implemented to\nrespond to user events and handle application startup and teardown.\n\nHere's an example application which simply draws a circle following the mouse\nand renders it white or black depending if the mouse is held down or not:\n\n```rust no_run\nuse pix_engine::prelude::*;\n\nstruct MyApp;\n\nimpl PixEngine for MyApp {\n    // Set up application state and initial settings. `PixState` contains\n    // engine specific state and utility methods for actions like getting mouse\n    // coordinates, drawing shapes, etc. (Optional)\n    fn on_start(\u0026mut self, s: \u0026mut PixState) -\u003e PixResult\u003c()\u003e {\n        // Set the background to GRAY and clear the screen.\n        s.background(Color::GRAY);\n\n        // Change the font family to NOTO and size to 16 instead of using the\n        // defaults.\n        s.font_family(Font::NOTO)?;\n        s.font_size(16);\n\n        // Returning `Err` instead of `Ok` would indicate initialization failed,\n        // and that the application should terminate immediately.\n        Ok(())\n    }\n\n    // Main update/render loop. Called as often as possible unless\n    // `target_frame_rate` was set with a value. (Required)\n    fn on_update(\u0026mut self, s: \u0026mut PixState) -\u003e PixResult\u003c()\u003e {\n        // Set fill color to black if mouse is pressed, otherwise wite.\n        if s.mouse_pressed() {\n            s.fill(color!(0));\n        } else {\n            s.fill(color!(255));\n        }\n\n        // Draw a circle with fill color at the mouse position with a radius of\n        // 80.\n        let m = s.mouse_pos();\n        s.circle([m.x(), m.y(), 80])?;\n\n        Ok(())\n    }\n\n    // Clean up any state or resources before exiting such as deleting temporary\n    // files or saving game state. (Optional)\n    fn on_stop(\u0026mut self, s: \u0026mut PixState) -\u003e PixResult\u003c()\u003e {\n        Ok(())\n    }\n}\n\nfn main() -\u003e PixResult\u003c()\u003e {\n    let mut engine = Engine::builder()\n      .dimensions(800, 600)\n      .title(\"MyApp\")\n      .show_frame_rate()\n      .resizable()\n      .build()?;\n    let mut app = MyApp;\n    engine.run(\u0026mut app)\n}\n```\n\n## Features\n\n### Crate Feature Flags\n\nThe following features can be added to your `Cargo.toml` depending on your\nneeds. e.g.:\n\n```toml\n[dependencies.pix-engine]\nversion = \"0.6.0\"\ndefault-features = false\nfeatures = [\"serde\"]\n```\n\n- **serde** - Adds [serde][] `Serialize`/`Deserialize` implementations for all\n  enums/structs.\n\n- **backtrace** - Enables the `backtrace` feature for [anyhow][], which allows\n  printing backtraces based on environment variables outlined in\n  [std::backtrace][]. Useful for debugging.\n\n- **opengl** - Forces `sdl2` to use `opengl` as its renderer. This feature is\n  disabled by default, allowing `sdl2` to use whichever renderer it defaults to\n  on the target system. For example, macOS defaults to `metal`.\n\n### PixState\n\n[`PixState`][pixstate] is the global application context for the entire\n`pix-engine` lifecycle from setup to teardown. It contains all of the settings\nand methods required to draw pixels to the screen, manage windows, textures,\nrendering settings, etc. See [Creating Your\nApplication](#creating-your-application) for a brief introduction to the engine\nlifecycle methods and examples of using [`PixState`][pixstate].\n\n### Drawing\n\nAll of the drawing primitives for drawing shapes, text, or UI widgets are all\navailable on the [`PixState`][pixstate] instance. Some methods are only\navailable when the corresponding traits are in scope. Many traits are included\nby default in the [`prelude`](crate::prelude).\n\nSome examples:\n\n```rust ignore\n// Draw a circle at `(x, y)` coordinates`(0, 0)` with a radius of `80`.\ns.circle([0, 0, 80])?;\n\n// Draw a rectangle at `(x, y)` coordinates `(10, 20)` with a width `80` and a\n// height of `100`.\ns.rect([10, 20, 80, 100])?;\n```\n\nThere are also several convenience macros for creating shapes that can be used\nfor drawing, or storing inside a `struct`:\n\n```rust ignore\n// Create a triangle with points at `(x, y)` coordinates `(10, 20)`, `(30, 10)`,\n// `(20, 25)`.\nlet t = tri!([10, 20], [30, 10], [20, 25]);\n\n// Create a 3D point at `(x, y, z)` coordinates `(10, 20, 10)`.\nlet p = point!(10, 20, 10);\n\n// Create a square at point `p` with a width/height of `100`.\nlet r = square!(p, 100);\n```\n\n#### Textures\n\nTextures are simple a representation of pixels but have some extra flexibility:\n\n- They can be drawn to separately from the primary canvas being rendered.\n- They can be transformed, clipped, or modified.\n- They can be blended together and overlayed on each other.\n\nBy default, all drawing operations target the primary window canvas. Once drawn,\nthe pixels are static and can only be drawn over. Using textures allows you to\ncreate things like draggable elements, popups, animation sprites, etc.\n\nTo create a texture:\n\n```rust ignore\n// Create a texture with a width and height of 256, formatting as RGB with no\n// alpha channel. You can also provide `None` as the format which will inherit\n// the format of the current window.\nlet texture_id = s.create_texture(256, 256, PixelFormat::Rgb);\n\n// Draw to the texture. These changes are not visible in the window.\ns.set_texture_target(texture_id)?;\ns.background(Color::BLACK);\ns.text(\"Hello World!\");\ns.clear_texture_target();\n\n// Now draw the texture to the current canvas. Specifying `None` as the `src`\n// argument means use the entire texture size. The `dst` here is double the\n// original texture which has the effect of scaling the texture by 2.\ns.texture(texture_id, None, rect!(0, 0, 512, 512))?;\n\n// To clean up unused textures, simply delete them.\ns.delete_texture(texture_id)?;\n```\n\n### Audio\n\nA limited form of audio support is available, with wider support coming soon. By\ndefault, an audio queue is available that you can push samples to:\n\n```rust ignore\ns.resume_audio(); // Audio queue starts in a `Paused` state.\n\n// Some method generating `f32` samples between 0.0 and 1.0\nlet samples = generate_audio();\ns.enqueue_audio(\u0026samples);\n```\n\nThere is also an [`AudioCallback`](crate::prelude::AudioCallback) trait you can\nimplement for doing callback-based audio generation. See the `examples/` folder\nfor details. Using this callback you can also do limited audio recording and\nplayback with a microphone.\n\n### UI\n\n#### Overview\n\n`pix-engine` offers an immediate mode graphical user interface ([IMGUI][])\nlibrary which allows for rapid UI development that is performant and simple to\nsetup/iterate on. Some limitations:\n\n- Styling is limited to simple color themes and spacing.\n- No animations or graphical effects.\n- Limited layout constructs - more complicated layouts require carefully crafted\n  code.\n- Limited responsiveness for changes in viewport.\n\nMuch of the API design is inspired by [Dear ImGui][], but note the following differences:\n\n- There are no window rendering utilities or features. Instead, separate native\n  windows can be opened with UI elements rendered within. This approach\n  simplifies window management by leveraging the native window features like\n  minimize, maximize, resizing, etc.\n\n#### End-User Guide\n\n- `Tab`/`Shift-Tab` cycles focus through interactable elements.\n- `Enter`/`Return` on an active element simulates clicking on it.\n- `Ctrl+Click` (`Cmd+Click` on macOS) on a slider or drag box to edit the value\n  as text.\n  - Pressing `Tab`/`Escape`/`Return` exits editing mode.\n- The mouse wheel can scroll elements that are out of view.\n- Text Fields:\n  - `Ctrl+Backspace` (`Cmd+Backspace` on macOS) to delete all content.\n  - `Alt+Backspace` (`Option+Backspace` on macOS) to delete a single word.\n  - `Ctrl+X` (`Cmd+X` on macOS) to cut contents to the system clipboard.\n  - `Ctrl+C` (`Cmd+C` on macOS) to copy contents to the system clipboard.\n  - `Ctrl+V` (`Cmd+V` on macOS) to paste contents from the system clipboard.\n\n#### Programmer Notes\n\n- See `gui` in the `examples/` folder to get started.\n- The UI is generated in code with UI method calls executed on the `PixState`\n  instance in the `PixState::on_update` render loop which is called every frame.\n- Elements are rendered in-order from top-left, to bottom-right.\n- Unless explicitly changed, each element will position itself below the\n  previous element. Calling `PixState::same_line` will shift position to the\n  right of the previous element.\n\n#### Windows\n\nAs your application grows, you may find the need to have different views open\nsimultaneously. This can be done by opening up additional windows to render\ninto. Each window has it's own canvas, while sharing the global `PixState`\ncontext settings. The API is very similar to working with textures.\n\n```rust ignore\n// Create a window with size of 800x600.\nlet window_id = s\n  .window()\n  .dimensions(800, 600)\n  .title(\"My Window\")\n  .position_centered()\n  .build()?;\n\n// Draw to the window. These changes are immediately visible in the window.\ns.set_window_target(window_id)?;\ns.background(Color::BLACK);\ns.fill(Color::RED);\ns.text(\"Hello World!\");\ns.reset_window_target();\n\n// A user can either close the window with the `X` button, `Ctrl-W`, `Alt-F4`,\n// etc. or you can close it programatically.\ns.close_window(window_id)?;\n```\n\n**Note:** One thing to consider when creating and managing widnows is that when\na window gets closed, its ID becomes invalid. Attempting to draw in an invalid\nwindow will return an error. Thus, most window creation will also require\nremoving invalid window IDs from their application:\n\n```rust ignore\nfn on_window_event(\n    \u0026mut self,\n    _s: \u0026mut PixState,\n    window_id: WindowId,\n    event: WindowEvent,\n) -\u003e PixResult\u003c()\u003e {\n    if event == WindowEvent::Close \u0026\u0026 self.popup_window == Some(window_id) {\n      self.popup_window = None;\n    }\n    Ok(())\n}\n```\n\n### Logging\n\nThis library uses the [log][] crate. To leverage\nlogging in your application, choose one of the supported logger implementations\nand initialize it in your `main` function.\n\nExample using [env_logger][]:\n\n```rust ignore\nfn main() -\u003e PixResult\u003c()\u003e {\n    env_logger::init();\n\n    let mut engine = Engine::builder()\n      .dimensions(800, 600)\n      .title(\"MyApp\")\n      .build()?;\n    let mut app = MyApp;\n    engine.run(\u0026mut app)\n}\n```\n\n## Known Issues\n\nSee the [github issue tracker][].\n\n## License\n\nLicensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE][])\n- MIT license ([LICENSE-MIT][])\n\nat your option.\n\n## Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall be\ndual licensed as above, without any additional terms or conditions.\n\n## Contact\n\nFor issue reporting, please use the [github issue tracker][]. You can also\ncontact me directly at \u003chttps://lukeworks.tech/contact/\u003e.\n\n## Credits\n\nThis has been a true passion project for several years and I can't thank the\nopen source community enough for the all the amazing content and support.\n\nA special shout out to the following projects which heavily inspired the\nimplementation and evolution of this crate:\n\n- [OneLoneCoder][] and the [olcPixelGameEngine][].\n- [The Coding Train][] and [p5js][].\n- [Dear ImGui][]\n\n[rust]: https://www.rust-lang.org/\n[sdl2]: https://crates.io/crates/sdl2/\n[vc++]: https://visualstudio.microsoft.com/visual-cpp-build-tools/\n[homebrew]: https://brew.sh/\n[rust-sdl2]: https://github.com/Rust-SDL2/rust-sdl2#sdl20-development-libraries\n[log]: https://crates.io/crates/log\n[env_logger]: https://crates.io/crates/env_logger\n[wasm]: https://www.rust-lang.org/what/wasm\n[tetanes]: https://crates.io/crates/tetanes\n[nes]: https://en.wikipedia.org/wiki/Nintendo_Entertainment_System\n[pixengine]: crate::prelude::PixEngine\n[pixengine::on_update]: crate::prelude::PixEngine::on_update\n[pixstate]: crate::prelude::PixState\n[serde]: https://crates.io/crates/serde\n[anyhow]: https://crates.io/crates/anyhow\n[std::backtrace]: https://doc.rust-lang.org/std/backtrace/index.html#environment-variables\n[github issue tracker]: https://github.com/lukexor/pix-engine/issues\n[license-apache]: http://www.apache.org/licenses/LICENSE-2.0\n[license-mit]: http://opensource.org/licenses/MIT\n[onelonecoder]: https://github.com/OneLoneCoder/\n[olcpixelgameengine]: https://github.com/OneLoneCoder/olcPixelGameEngine\n[the coding train]: https://www.youtube.com/channel/UCvjgXvBlbQiydffZU7m1_aw\n[p5js]: https://p5js.org/\n[imgui]: http://www.johno.se/book/imgui.html\n[dear imgui]: https://github.com/ocornut/imgui\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukexor%2Fpix-engine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flukexor%2Fpix-engine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukexor%2Fpix-engine/lists"}