Skip to content

Commit

Permalink
0.15 wip
Browse files Browse the repository at this point in the history
  • Loading branch information
merwaaan committed Dec 15, 2024
1 parent 478419a commit 7070ad2
Show file tree
Hide file tree
Showing 24 changed files with 529 additions and 802 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 2.0.0 - 2024-12-14

### Added

- Add support for Bevy 0.15

### Removed

- Remove `Sprite3dBundle` and `Sprite3dBundle`.
Thanks to required components, simply adding a `Sprite3d` component will just work.

## 1.0.0 - 2024-11-20

### Added
Expand All @@ -11,7 +22,7 @@

### Fixed

- Fixed some timing bugs due to the internal use of u32 instead of std::time::Duration
- Fix some timing bugs due to the internal use of u32 instead of std::time::Duration

## 0.4.3 - 2024-11-11

Expand Down
14 changes: 6 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,23 @@ resolver = "2"
exclude = ["assets/example.gif", "assets/example3d.gif"]

[dependencies]
bevy = { version = "0.14.0", default-features = false, features = [
bevy = { version = "0.15.0", default-features = false, features = [
"bevy_pbr",
"bevy_sprite",
] }
# Temporary dep until the bevy_image export is fixed
# https://github.com/bevyengine/bevy/issues/16563
bevy_internal = { version = "0.15", features = [ "bevy_image" ]}

[dev-dependencies]
approx = "0.5.1"
bevy = { version = "0.14.0", default-features = true }
bevy = { version = "0.15.0", default-features = true }
clap = { version = "4.5.16", features = ["derive"] }
divan = "0.1.14"
iyes_perf_ui = "0.3.0"
iyes_perf_ui = { git = "https://github.com/IyesGames/iyes_perf_ui.git", rev = "d8f3cbb2ec486b85a86b21e1aa32dcebd26ac884" }
rand = "0.8.5"

[profile.test]
inherits = "release"

[[bench]]
name = "basic"
harness = false

[lints]
clippy.type_complexity = "allow"
41 changes: 15 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,26 +66,23 @@ fn setup(
//
// See the `composition` example for more details.

// Spawn a sprite using Bevy's built-in SpriteBundle
// Spawn a sprite using Bevy's built-in Sprite

let texture = assets.load("character.png");
let image = assets.load("character.png");

let layout = atlas_layouts.add(spritesheet.atlas_layout(96, 96));
let atlas = TextureAtlas {
layout: atlas_layouts.add(spritesheet.atlas_layout(96, 96)),
..default()
};

commands.spawn((
SpriteBundle {
texture,
..default()
},
TextureAtlas {
layout,
..default()
},
Sprite::from_atlas_image(image, atlas),

// Add a SpritesheetAnimation component that references our newly created animation
SpritesheetAnimation::from_id(animation_id),
));

commands.spawn(Camera2dBundle::default());
commands.spawn(Camera2d);
}
```

Expand Down Expand Up @@ -155,14 +152,7 @@ fn setup(mut commands: Commands, mut library: ResMut<AnimationLibrary>) {
// ... omitted: load the sprite's texture and create an atlas

commands.spawn((
SpriteBundle {
texture,
..default()
},
TextureAtlas {
layout,
..default()
},
Sprite::from_atlas_image(image, atlas),
SpritesheetAnimation::from_id(animation_id),
));
}
Expand Down Expand Up @@ -190,7 +180,7 @@ fn spawn_enemies(mut commands: Commands, mut library: ResMut<AnimationLibrary>)
let animation_id = library.register_animation();

commands.spawn((
SpriteBundle { /* .... */ },
Sprite::from_atlas_image(/* .... */),
SpritesheetAnimation::from_id(animation_id),
));
}
Expand Down Expand Up @@ -235,7 +225,7 @@ fn spawn_enemies(mut commands: Commands, library: Res<AnimationLibrary>) {
if let Some(animation_id) = libray.animation_with_name("enemy running") {
for _ in 0..100 {
commands.spawn((
SpriteBundle { /* .... */ },
Sprite::from_atlas_image(/* .... */),
SpritesheetAnimation::from_id(animation_id),
));
}
Expand All @@ -249,9 +239,7 @@ fn spawn_enemies(mut commands: Commands, library: Res<AnimationLibrary>) {

This crate also makes it easy to integrate 3D sprites into your games, which is not supported by Bevy out of the box.

[Sprite3dBundle](https://docs.rs/bevy_spritesheet_animation/latest/bevy_spritesheet_animation/components/sprite3d/struct.Sprite3dBundle.html) contains all the necesary components to enable 3D sprites. Use [Sprite3dBuilder](https://docs.rs/bevy_spritesheet_animation/latest/bevy_spritesheet_animation/components/sprite3d/struct.Sprite3dBuilder.html) to easily create one of those.

Animating a 3D sprite is the same as animating 2D sprites: simply attach a [SpritesheetAnimation](https://docs.rs/bevy_spritesheet_animation/latest/bevy_spritesheet_animation/components/spritesheet_animation/struct.SpritesheetAnimation.html) component to your entity.
Animating a 3D sprite is the same as animating 2D sprites: simply spawn a [Sprite3d](https://docs.rs/bevy_spritesheet_animation/latest/bevy_spritesheet_animation/components/sprite3d/struct.Sprite3d.html) instead of Bevy-s built-in Sprite and attach a [SpritesheetAnimation](https://docs.rs/bevy_spritesheet_animation/latest/bevy_spritesheet_animation/components/spritesheet_animation/struct.SpritesheetAnimation.html) component to the entity.

```rust
fn spawn_character(mut commands: Commands, mut library: ResMut<AnimationLibrary>) {
Expand Down Expand Up @@ -283,13 +271,14 @@ For more examples, browse the [examples/](examples) directory.
| [parameters](examples/parameters.rs) | Shows the effect of each animation parameter |
| [character](examples/character.rs) | Shows how to create a controllable character with multiple animations |
| [events](examples/events.rs) | Shows how to react to animations reaching points of interest with events |
| [headless](examples/headless.rs) | Shows how to setup a headless Bevy app without rendering |
| [headless](examples/headless.rs) | Shows how to run animations in a headless Bevy app without rendering |
| [stress](examples/stress.rs) | Stress test with thousands of animated sprites (either 2D or 3D) |

# Compatibility

| bevy | bevy_spritesheet_animation |
| ---- | -------------------------- |
| 0.15 | 2.0.0 |
| 0.14 | 0.2.0 |
| 0.13 | 0.1.0 |

Expand Down
100 changes: 0 additions & 100 deletions benches/basic.rs

This file was deleted.

79 changes: 40 additions & 39 deletions examples/3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ fn main() {
DefaultPlugins.set(ImagePlugin::default_nearest()),
SpritesheetAnimationPlugin::default(),
))
.add_systems(Startup, setup)
.add_systems(Startup, spawn_sprites)
.add_systems(Update, (update_on_keypress, orbit, draw_gizmos))
.run();
}

fn setup(
fn spawn_sprites(
mut commands: Commands,
mut library: ResMut<AnimationLibrary>,
mut atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
assets: Res<AssetServer>,
) {
// 3D sprites require a 3D camera

commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.0, 1000.0, 4000.0).looking_at(Vec3::ZERO, Dir3::Y),
..default()
});
commands.spawn((
Camera3d::default(),
Transform::from_xyz(0.0, 1000.0, 4000.0).looking_at(Vec3::ZERO, Dir3::Y),
));

// Create an animation as usual

Expand All @@ -43,60 +43,61 @@ fn setup(

let animation_id = library.register_animation(animation);

// Create an image and an atlas layout like you would for any Bevy sprite
// Create an image and a texture atlas like you would for any Bevy sprite

let texture = assets.load("character.png");
let image = assets.load("character.png");

let atlas_layout = atlas_layouts.add(spritesheet.atlas_layout(96, 96));
let atlas = TextureAtlas {
layout: atlas_layouts.add(spritesheet.atlas_layout(96, 96)),
..default()
};

// Spawn 3D sprites

// A few 3D sprites orbiting around the center with various parameters

let sprite_builders = [
Sprite3dBuilder::from_image(texture.clone()),
Sprite3dBuilder::from_image(texture.clone()).with_flip(true, false),
Sprite3dBuilder::from_image(texture.clone()).with_flip(false, true),
Sprite3dBuilder::from_image(texture.clone()).with_flip(true, true),
Sprite3dBuilder::from_image(texture.clone()).with_anchor(Anchor::BottomLeft),
Sprite3dBuilder::from_image(texture.clone()).with_anchor(Anchor::BottomCenter),
Sprite3dBuilder::from_image(texture.clone()).with_anchor(Anchor::BottomRight),
Sprite3dBuilder::from_image(texture.clone()).with_anchor(Anchor::CenterLeft),
Sprite3dBuilder::from_image(texture.clone()).with_anchor(Anchor::Center),
Sprite3dBuilder::from_image(texture.clone()).with_anchor(Anchor::CenterRight),
Sprite3dBuilder::from_image(texture.clone()).with_anchor(Anchor::TopLeft),
Sprite3dBuilder::from_image(texture.clone()).with_anchor(Anchor::TopCenter),
Sprite3dBuilder::from_image(texture.clone()).with_anchor(Anchor::TopRight),
Sprite3dBuilder::from_image(texture.clone()).with_custom_size(Vec2::new(100.0, 400.0)),
let sprites = [
Sprite3d::from_atlas_image(image.clone(), atlas.clone()),
Sprite3d::from_atlas_image(image.clone(), atlas.clone()).with_flip(true, false),
Sprite3d::from_atlas_image(image.clone(), atlas.clone()).with_flip(false, true),
Sprite3d::from_atlas_image(image.clone(), atlas.clone()).with_flip(true, true),
Sprite3d::from_atlas_image(image.clone(), atlas.clone()).with_anchor(Anchor::BottomLeft),
Sprite3d::from_atlas_image(image.clone(), atlas.clone()).with_anchor(Anchor::BottomCenter),
Sprite3d::from_atlas_image(image.clone(), atlas.clone()).with_anchor(Anchor::BottomRight),
Sprite3d::from_atlas_image(image.clone(), atlas.clone()).with_anchor(Anchor::CenterLeft),
Sprite3d::from_atlas_image(image.clone(), atlas.clone()).with_anchor(Anchor::Center),
Sprite3d::from_atlas_image(image.clone(), atlas.clone()).with_anchor(Anchor::CenterRight),
Sprite3d::from_atlas_image(image.clone(), atlas.clone()).with_anchor(Anchor::TopLeft),
Sprite3d::from_atlas_image(image.clone(), atlas.clone()).with_anchor(Anchor::TopCenter),
Sprite3d::from_atlas_image(image.clone(), atlas.clone()).with_anchor(Anchor::TopRight),
Sprite3d::from_atlas_image(image.clone(), atlas.clone())
.with_custom_size(Vec2::new(100.0, 400.0)),
];

for (i, builder) in sprite_builders.iter().enumerate() {
let sprite_count = sprites.len();

for (i, sprite) in sprites.into_iter().enumerate() {
commands.spawn((
builder.clone().with_atlas(atlas_layout.clone()).build(),
sprite,
SpritesheetAnimation::from_id(animation_id),
Orbit {
start_angle: i as f32 * std::f32::consts::TAU / sprite_builders.len() as f32,
start_angle: i as f32 * std::f32::consts::TAU / sprite_count as f32,
},
));
}

// A non-animated 3D sprite in the center

commands.spawn(
Sprite3dBuilder::from_image(texture.clone())
.with_atlas(atlas_layout.clone())
.with_color(Color::linear_rgb(1.0, 0.0, 0.0))
.build(),
Sprite3d::from_atlas_image(image.clone(), atlas.clone())
.with_color(Color::linear_rgb(1.0, 0.0, 0.0)),
);

// Help text

commands.spawn(TextBundle::from_section(
"C: random colors\nX: flip on X\nY: flip on Y\nA: random anchors\nS: random sizes\nR: reset",
TextStyle {
font_size: 30.0,
..default()
},
commands.spawn((Text(
"C: random colors\nX: flip on X\nY: flip on Y\nA: random anchors\nS: random sizes\nR: reset".to_owned()),
TextFont::from_font_size(30.0)
));
}

Expand Down Expand Up @@ -166,8 +167,8 @@ struct Orbit {

fn orbit(time: Res<Time>, mut query: Query<(&Orbit, &mut Transform)>) {
for (orbit, mut transform) in &mut query {
transform.translation.x = (orbit.start_angle + time.elapsed_seconds()).cos() * 1500.0;
transform.translation.z = (orbit.start_angle + time.elapsed_seconds()).sin() * 1500.0;
transform.translation.x = (orbit.start_angle + time.elapsed_secs()).cos() * 1500.0;
transform.translation.z = (orbit.start_angle + time.elapsed_secs()).sin() * 1500.0;
}
}

Expand Down
Loading

0 comments on commit 7070ad2

Please sign in to comment.