From 1f5b16090b5e1eadf0f0e5944a0c8327e5b05603 Mon Sep 17 00:00:00 2001 From: Schrottkatze Date: Sat, 23 Nov 2024 17:54:12 +0100 Subject: [PATCH] add basic (untested) animation thingythingthing --- src/game/player.rs | 68 ++++++++++++++++++++++++------------ src/game/player/animation.rs | 43 +++++++++++++++++++++++ 2 files changed, 89 insertions(+), 22 deletions(-) create mode 100644 src/game/player/animation.rs diff --git a/src/game/player.rs b/src/game/player.rs index 6d11747..b8b6b60 100644 --- a/src/game/player.rs +++ b/src/game/player.rs @@ -1,10 +1,15 @@ -use bevy::{prelude::*, sprite::MaterialMesh2dBundle}; +use std::{hash::Hash, time::Duration}; + +use bevy::{prelude::*, sprite::MaterialMesh2dBundle, utils::HashMap}; use bevy_rapier2d::prelude::*; use crate::{AppState, METER}; use super::set::IngameSet; + +mod animation; + #[derive(Component)] struct Player {} @@ -12,32 +17,51 @@ pub(super) fn player_plugin(app: &mut App) { app.add_systems(OnEnter(AppState::InGame), add_player.in_set(IngameSet)); } +#[derive(Hash, PartialEq, Eq, Default)] +enum PlayerAnimations { + #[default] + Idle, + Walk, +} + pub fn add_player( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, + mut texture_atlas_layouts: ResMut>, asset_server: Res, ) { - // TODO replace - commands.spawn(SpriteBundle { - texture: asset_server.load("assets/Blockgrau.png"), - ..Default::default() - }); + let tex_idle = asset_server.load("idle.png"); + let layout_idle = TextureAtlasLayout::from_grid(UVec2::splat(512), 2, 1, None, None); + let layout_idle_handle = texture_atlas_layouts.add(layout_idle); - commands - .spawn(( - Player {}, - MaterialMesh2dBundle { - mesh: meshes.add(Circle::new(20.)).into(), - material: materials.add(asset_server.load("test.png")), - transform: Transform::from_xyz(10., 10., 0.), - ..default() - }, - )) - //.insert(( - // RigidBody::Dynamic, - // Collider::cuboid(0.4 * METER, 0.9 * METER), - // Velocity::default(), - //)) - .insert(ActiveEvents::COLLISION_EVENTS); + let tex_walk = asset_server.load("walk.png"); + let layout_walk = TextureAtlasLayout::from_grid(UVec2::splat(512), 4, 1, None, None); + let layout_walk_handle = texture_atlas_layouts.add(layout_walk); + + let anims = animation::AnimationManager::default() + .insert( + PlayerAnimations::Idle, + animation::Animation::new( + TextureAtlas { + layout: layout_idle_handle, + index: 0, + }, + 2, + 4, + tex_idle, + ), + ) + .insert( + PlayerAnimations::Walk, + animation::Animation::new( + TextureAtlas { + layout: layout_walk_handle, + index: 0, + }, + 2, + 4, + tex_walk, + ), + ); } diff --git a/src/game/player/animation.rs b/src/game/player/animation.rs new file mode 100644 index 0000000..d7357e6 --- /dev/null +++ b/src/game/player/animation.rs @@ -0,0 +1,43 @@ +use bevy::prelude::*; +use std::time::Duration; + +use bevy::utils::HashMap; + +use std::hash::Hash; + +#[derive(Default)] +pub(crate) struct AnimationManager { + animations: HashMap, +} + +impl AnimationManager { + pub fn insert(mut self, which: Anim, anim: Animation) -> Self { + self.animations.insert(which, anim); + self + } +} + +pub(crate) struct Animation { + atlas: TextureAtlas, + max_index: usize, + fps: u8, + frame_timer: Timer, + tex: Handle, +} + +impl Animation { + pub fn new(atlas: TextureAtlas, length: usize, fps: u8, tex_handle: Handle) -> Self { + Self { + atlas, + max_index: length - 1, + fps, + frame_timer: Self::timer_from_fps(fps), + tex: tex_handle, + } + } + + // stolen from https://github.com/bevyengine/bevy/blob/5c759a1be800209f537bea31d32b8ba7e966b0c1/examples/2d/sprite_animation.rs#L53-L55 + pub(crate) fn timer_from_fps(fps: u8) -> Timer { + Timer::new(Duration::from_secs_f32(1.0 / (fps as f32)), TimerMode::Once) + } +}