sprite_sheet/
sprite_sheet.rs1use bevy::prelude::*;
5
6fn main() {
7 App::new()
8 .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest())) .add_systems(Startup, setup)
10 .add_systems(Update, animate_sprite)
11 .run();
12}
13
14#[derive(Component)]
15struct AnimationIndices {
16 first: usize,
17 last: usize,
18}
19
20#[derive(Component, Deref, DerefMut)]
21struct AnimationTimer(Timer);
22
23fn animate_sprite(
24 time: Res<Time>,
25 mut query: Query<(&AnimationIndices, &mut AnimationTimer, &mut Sprite)>,
26) {
27 for (indices, mut timer, mut sprite) in &mut query {
28 timer.tick(time.delta());
29
30 if timer.just_finished()
31 && let Some(atlas) = &mut sprite.texture_atlas
32 {
33 atlas.index = if atlas.index == indices.last {
34 indices.first
35 } else {
36 atlas.index + 1
37 };
38 }
39 }
40}
41
42fn setup(
43 mut commands: Commands,
44 asset_server: Res<AssetServer>,
45 mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
46) {
47 let texture = asset_server.load("textures/rpg/chars/gabe/gabe-idle-run.png");
48 let layout = TextureAtlasLayout::from_grid(UVec2::splat(24), 7, 1, None, None);
49 let texture_atlas_layout = texture_atlas_layouts.add(layout);
50 let animation_indices = AnimationIndices { first: 1, last: 6 };
52
53 commands.spawn(Camera2d);
54
55 commands.spawn((
56 Sprite::from_atlas_image(
57 texture,
58 TextureAtlas {
59 layout: texture_atlas_layout,
60 index: animation_indices.first,
61 },
62 ),
63 Transform::from_scale(Vec3::splat(6.0)),
64 animation_indices,
65 AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
66 ));
67}