├── assets
├── coin.animation.yml
├── coin.png
└── README.md
├── .gitignore
├── .github
└── workflows
│ ├── create-release.yml
│ └── check.yml
├── .cargo
└── fast_compiles_config
├── release.toml
├── renovate.json
├── Cargo.toml
├── LICENSE-MIT
├── UNLICENSE
├── CHANGELOG.md
├── justfile
├── src
├── lib.rs
├── animation
│ ├── mod.rs
│ └── dto.rs
└── state.rs
├── examples
└── bevy.rs
├── README.md
└── CONTRIBUTING.md
/assets/coin.animation.yml:
--------------------------------------------------------------------------------
1 | mode: Repeat
2 | fps: 12
3 | frames: [0, 1, 2, 3, 4]
4 |
--------------------------------------------------------------------------------
/assets/coin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jcornaz/benimator/HEAD/assets/coin.png
--------------------------------------------------------------------------------
/assets/README.md:
--------------------------------------------------------------------------------
1 | # Credits
2 |
3 | Coin by [La Red Games](https://laredgames.itch.io/gems-coins-free) (CC0)
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Rust
2 | /target
3 | /Cargo.lock
4 | /.cargo/*.toml
5 |
6 | # IDE
7 | /.idea
8 | /.vscode
9 | *.iml
10 |
11 | # Operating systems
12 | .DS_Store
13 | .trashes
14 | *.db
15 |
16 | # Nodes tools
17 | /node_modules
18 |
--------------------------------------------------------------------------------
/.github/workflows/create-release.yml:
--------------------------------------------------------------------------------
1 | name: Create github release
2 |
3 | permissions:
4 | contents: write
5 |
6 | on:
7 | push:
8 | tags:
9 | - v[0-9]+.*
10 |
11 | jobs:
12 | create-release:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: actions/checkout@v4
16 | - uses: taiki-e/create-gh-release-action@v1
17 | with:
18 | changelog: CHANGELOG.md
19 | token: ${{ github.token }}
20 |
--------------------------------------------------------------------------------
/.cargo/fast_compiles_config:
--------------------------------------------------------------------------------
1 | # Copy the content of this file to `.cargo/config.toml`
2 |
3 | [target.x86_64-unknown-linux-gnu]
4 | linker = "clang"
5 | rustflags = ["-Clink-arg=-fuse-ld=lld"]
6 |
7 | [target.x86_64-apple-darwin]
8 | rustflags = ["-C", "link-arg=-fuse-ld=/usr/local/bin/zld"]
9 |
10 | [target.aarch64-apple-darwin]
11 | rustflags = ["-C", "link-arg=-fuse-ld=/opt/homebrew/bin/zld"]
12 |
13 | [target.x86_64-pc-windows-msvc]
14 | linker = "rust-lld.exe"
15 |
16 | [target.wasm32-unknown-unknown]
17 | runner = "wasm-server-runner"
18 |
--------------------------------------------------------------------------------
/.github/workflows/check.yml:
--------------------------------------------------------------------------------
1 | name: check
2 |
3 | on:
4 | push:
5 | branches: ["[0-9]+.x", main, rc, beta, alpha]
6 | pull_request:
7 | workflow_dispatch:
8 |
9 | jobs:
10 | verify:
11 | runs-on: ubuntu-24.04
12 | timeout-minutes: 10
13 | steps:
14 | - uses: actions/checkout@v4
15 | - uses: dtolnay/rust-toolchain@stable
16 | with:
17 | components: clippy, rustfmt
18 | - uses: Swatinem/rust-cache@v2
19 | - uses: taiki-e/install-action@v2
20 | with:
21 | tool: cargo-hack@0.5,just@1,cargo-msrv@0.16
22 | - run: just verify
23 |
--------------------------------------------------------------------------------
/release.toml:
--------------------------------------------------------------------------------
1 | allow-branch = ["main"]
2 | pre-release-commit-message = "release {{version}}"
3 |
4 | [[pre-release-replacements]]
5 | file = "CHANGELOG.md"
6 | search = "## \\[Unreleased\\]"
7 | replace = "## [Unreleased]\n\n\n## [{{version}}] - {{date}}"
8 | prerelease = true
9 | exactly = 1
10 |
11 | [[pre-release-replacements]]
12 | file = "CHANGELOG.md"
13 | search = "\\.\\.\\.HEAD"
14 | replace = "...v{{version}}"
15 | prerelease = true
16 | exactly = 1
17 |
18 | [[pre-release-replacements]]
19 | file = "CHANGELOG.md"
20 | search = "\\[Unreleased\\]:"
21 | replace = "[Unreleased]: https://github.com/jcornaz/beancount-parser/compare/v{{version}}...HEAD\n[{{version}}]:"
22 | prerelease = true
23 | exactly = 1
24 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": ["config:recommended"],
4 | "timezone": "Europe/Zurich",
5 | "schedule": ["after 10pm", "before 5:00am"],
6 | "packageRules": [
7 | {
8 | "matchPackageNames": "bevy",
9 | "enabled": false
10 | },
11 | {
12 | "matchCurrentVersion": ">=1.0.0",
13 | "matchUpdateTypes": [
14 | "minor",
15 | "patch"
16 | ],
17 | "automerge": true
18 | },
19 | {
20 | "matchCurrentVersion": ">=0.1.0 <1.0.0",
21 | "matchUpdateTypes": [
22 | "patch"
23 | ],
24 | "automerge": true
25 | },
26 | {
27 | "matchDepTypes": [
28 | "dev-dependencies"
29 | ],
30 | "automerge": true
31 | }
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "benimator"
3 | version = "4.1.3"
4 | edition = "2021"
5 | rust-version = "1.70"
6 | authors = ["Jonathan Cornaz"]
7 | license = "Unlicense OR MIT"
8 | description = "A sprite animation library for rust game development"
9 | repository = "https://github.com/jcornaz/benimator"
10 | keywords = ["game", "gamedev", "anmiation"]
11 | categories = ["game-development"]
12 |
13 | [package.metadata.docs.rs]
14 | all-features = true
15 |
16 | [features]
17 | default = []
18 |
19 | [dependencies]
20 | # Public dependencies (Present in the public API)
21 | serde = { version = "1.0.200", features = ["derive"], optional = true }
22 |
23 | [dev-dependencies]
24 | serde_yaml = { version = "0.9.34", default-features = false }
25 | rstest = { version = "0.21.0", default-features = false }
26 | bevy = { version = "0.12.1", default-features = false, features = ["bevy_asset", "bevy_winit", "bevy_render", "bevy_sprite", "bevy_core_pipeline", "png", "x11", "dynamic_linking"] }
27 | anyhow = "1.0.82"
28 | toml = "0.8.12"
29 |
30 | [build-dependencies]
31 | rustc_version = "0.4.0"
32 |
33 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Jonathan Cornaz
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/UNLICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6 |
7 |
8 | ## [Unreleased]
9 |
10 | ### Dependencies
11 |
12 | * Minimum supported rust version raised to `1.70`
13 |
14 |
15 | ## [4.1.3] - 2023-07-01
16 |
17 | ### Bug fixes
18 |
19 | * Fixed deserialization error of a "short form" frame list when using the toml crate.
20 |
21 |
22 | ### Thank you
23 |
24 | * @tguichaoua
25 |
26 |
27 | ## [4.1.2](https://github.com/jcornaz/benimator/compare/v4.1.1...v4.1.2) (2023-01-09)
28 |
29 |
30 | ### Documentation
31 |
32 | * **readme:** lower minimum support rust version to 1.60 ([909eaea](https://github.com/jcornaz/benimator/commit/909eaea4b8974872126961c2be0650aa5e3e5b85))
33 |
34 | ## [4.1.1](https://github.com/jcornaz/benimator/compare/v4.1.0...v4.1.1) (2023-01-08)
35 |
36 |
37 | ### Documentation
38 |
39 | * **readme:** fix build badge ([6ee96e7](https://github.com/jcornaz/benimator/commit/6ee96e719de6cef82eb04d4ca86e11cef3e011a1))
40 | * **readme:** remove build status badge ([dd9adc9](https://github.com/jcornaz/benimator/commit/dd9adc9aa0b4d47c7eabcfcbf954f9bc9e2e4ca7))
41 |
42 |
43 | [Unreleased]: https://github.com/jcornaz/beancount-parser/compare/v4.1.3...HEAD
44 | [4.1.3]: https://github.com/jcornaz/benimator/compare/v4.1.2...v4.1.3
45 |
46 |
--------------------------------------------------------------------------------
/justfile:
--------------------------------------------------------------------------------
1 | set dotenv-load
2 |
3 | @_choose:
4 | just --choose --unsorted
5 |
6 | # Perform all verifications (compile, test, lint, etc.)
7 | verify: test lint doc check-msrv
8 |
9 | # Watch the source files and run `just verify` when source changes
10 | watch:
11 | cargo watch --delay 0.1 --clear --why -- just verify
12 |
13 | # Run the tests
14 | test:
15 | cargo hack test --feature-powerset --optional-deps
16 |
17 | # Run the static code analysis
18 | lint:
19 | cargo fmt -- --check
20 | cargo hack clippy --feature-powerset --all-targets --optional-deps
21 |
22 | # Build the documentation
23 | doc *args:
24 | cargo doc --all-features --no-deps {{args}}
25 |
26 | # Open the documentation page
27 | doc-open: (doc "--open")
28 |
29 | # Run the given example
30 | run example:
31 | cargo run --all-features --example {{example}}
32 |
33 | # Make sure the MSRV is satisfiable
34 | check-msrv:
35 | cargo msrv verify
36 |
37 | # Clean up compilation output
38 | clean:
39 | rm -rf target
40 | rm -f Cargo.lock
41 | rm -rf node_modules
42 |
43 | # Install cargo dev-tools used by the `verify` recipe (requires rustup to be already installed)
44 | install-dev-tools:
45 | rustup install stable
46 | rustup override set stable
47 | cargo install cargo-hack cargo-watch cargo-msrv
48 |
49 | # Install a git hook to run tests before every commits
50 | install-git-hooks:
51 | echo '#!/usr/bin/env sh' > .git/hooks/pre-commit
52 | echo 'just verify' >> .git/hooks/pre-commit
53 | chmod +x .git/hooks/pre-commit
54 |
55 | release *args: verify
56 | cargo release {{args}}
57 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![warn(
2 | future_incompatible,
3 | nonstandard_style,
4 | rust_2018_idioms,
5 | missing_docs,
6 | clippy::pedantic
7 | )]
8 | #![cfg_attr(test, allow(clippy::needless_pass_by_value))]
9 | #![cfg_attr(nightly, feature(doc_auto_cfg))]
10 |
11 | //! A sprite animation library for rust game development
12 | //!
13 | //! Initially designed for [bevy], it is now engine agnostic.
14 | //!
15 | //! # Get started
16 | //!
17 | //! benimator assumes usage of texture atlas (or equivalent).
18 | //!
19 | //! An [`Animation`] contains the list of animation frames,
20 | //! each frame defined by an index.
21 | //!
22 | //! ```
23 | //! # use std::time::Duration;
24 | //! use benimator::*;
25 | //!
26 | //! // Create an animation
27 | //! let animation = Animation::from_indices(0..=3, FrameRate::from_fps(10.0));
28 | //!
29 | //! // Create a new animation state
30 | //! let mut state = State::new();
31 | //!
32 | //! // In the game loop, for each update, tell the state how much time has elapsed
33 | //! let delta_time = Duration::from_millis(250);
34 | //! state.update(&animation, delta_time);
35 | //!
36 | //! // Then get the current frame index.
37 | //! // (so that we can tell our engine to render the sprite at that index)
38 | //! assert_eq!(state.frame_index(), 2);
39 | //! ```
40 | //!
41 | //! Have a look at the [examples](https://github.com/jcornaz/benimator/tree/main/examples) for complete examples using the [bevy] game engine.
42 | //!
43 | //! [bevy]: https://bevyengine.org
44 |
45 | #[cfg(test)]
46 | #[macro_use]
47 | extern crate rstest;
48 |
49 | pub use animation::{Animation, Frame, FrameRate};
50 | pub use state::State;
51 |
52 | mod animation;
53 | mod state;
54 |
--------------------------------------------------------------------------------
/examples/bevy.rs:
--------------------------------------------------------------------------------
1 | use bevy::prelude::*;
2 |
3 | use benimator::FrameRate;
4 |
5 | // Create the animation component
6 | // Note: you may make the animation an asset instead of a component
7 | #[derive(Component, Deref)]
8 | struct Animation(benimator::Animation);
9 |
10 | // Create the player component
11 | #[derive(Default, Component, Deref, DerefMut)]
12 | struct AnimationState(benimator::State);
13 |
14 | fn main() {
15 | App::new()
16 | .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
17 | .add_systems(Startup, spawn)
18 | .add_systems(Update, animate)
19 | .run();
20 | }
21 |
22 | fn spawn(
23 | mut commands: Commands,
24 | asset_server: Res,
25 | mut textures: ResMut>,
26 | ) {
27 | // Don't forget the camera ;-)
28 | commands.spawn(Camera2dBundle::default());
29 |
30 | // Create an animation
31 | let animation = Animation(benimator::Animation::from_indices(
32 | 0..=4,
33 | FrameRate::from_fps(12.0),
34 | ));
35 |
36 | commands
37 | // Spawn a bevy sprite-sheet
38 | .spawn(SpriteSheetBundle {
39 | texture_atlas: textures.add(TextureAtlas::from_grid(
40 | asset_server.load("coin.png"),
41 | Vec2::new(16.0, 16.0),
42 | 5,
43 | 1,
44 | None,
45 | None,
46 | )),
47 | transform: Transform::from_scale(Vec3::splat(10.0)),
48 | ..Default::default()
49 | })
50 | // Insert the animation
51 | .insert(animation)
52 | // Insert the state
53 | .insert(AnimationState::default());
54 | }
55 |
56 | fn animate(
57 | time: Res