3 releases

new 0.2.2 Dec 14, 2024
0.2.1 Dec 14, 2024
0.2.0 Dec 14, 2024

#471 in Rust patterns

Download history 267/week @ 2024-12-09

267 downloads per month

MIT license

13KB

animatron

Companion macro here

Fancy way to describe animation loops in a single array coz cache friendly. This is a lie, all it does is loop over array indices. You can probably use it for other things.

                                                                       
                    DECLARING THE ENUM                                 
                                                                       
                                                                       
       ╔═══════╦═══════╦═══════╦═══════╦═══════╦═══════╗               
       ║       ║       ║       ║       ║       ║       ║▐▌             
       ║   012345   ║▐▌             
       ╚═══════╩═══════╩═══════╩═══════╩═══════╩═══════╝▐▌             
        ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▘             
                           [usize; 6]                                  
                                                                       
                                                                       
     pub enum Variant {                pub trait AnimationLoop {       
         Idle,           implements                                    
         Rising, ━━━━━━━━━━━━━━━━━━━━━▶    fn page() -> (usize, usize);
         Falling,                                                      
     }                                 }                               
                                                                       
                                                                       
                    MAPPING TO idx/offset                              
                                                                       
       ╔═══════╦═══════╦═══════╦═══════╦═══════╦═══════╗               
       ║       ║       ║       ║       ║       ║       ║▐▌             
       ║   012345   ║▐▌             
       ╚═══════╩═══════╩═══════╩═══╤═══╩═══════╩═══════╝▐▌             
        ▀▀▀▀▀▀▀▀▀▀▀│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▘             
                   └───────┬───────┘                                   
                           ╵                                           
              Idle::pages(); // (offset: 1, size: 3)                   
                                                                       
                                                                       
                                                                       
       ╔═══════╦═══════╦═══════╦═══════╦═══════╦═══════╗               
       ║       ║       ║       ║       ║       ║       ║▐▌             
       ║   012345   ║▐▌             
       ╚═══════╩═══════╩═══════╩═══╤═══╩═══╤═══╩═══════╝▐▌             
        ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀│▀▀▀▀▀▀▀│▀▀▀▀▀▀▀▀▀▀▀▀▀▘             
                                   └───┬───┘                           
                                       ╵                               
              Rising::pages(); // (offset: 3, size: 2)                 
                                                                       
                                                                       
                                                                       
                                                                       
                   FLIPPING THROUGH SPRITES                            
                                                                       
                                                                       
                                   ┌───────┐                           
                                   │       │                           
       ╔═══════╦═══════╦═══════╦═══╧═══╦═══▼═══╦═══════╗               
       ║       ║       ║       ║       ║       ║       ║▐▌             
       ║   012345   ║▐▌             
       ╚═══════╩═══════╩═══════╩═══════╩═══════╩═══════╝▐▌             
        ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▘             
                                                                       
              animation_state.variant; // Variant::Rising              
              animation_state.idx; // 3                                
              animation_state.wrapping_next_idx(); //  4               
                                                                       
                                                                       
                       VARIANT TRANSITION                              
                                                                       
                                                                       
                                       ┏━━━━━━━━━━━┓                   
                                       ┃           ┃                   
                                   ┌───┸───┐       ┃                   
       ╔═══════╦═══════╦═══════╦═══╧═══╦═══╧═══╦═══▼═══╗               
       ║       ║       ║       ║       ║       ║       ║▐▌             
       ║   012345   ║▐▌             
       ╚═══════╩═══════╩═══════╩═══════╩═══════╩═══════╝▐▌             
        ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▘             
                                                                       
              animation_state.variant;              // Variant::Rising 
              animation_state.transition_variant(); // ()              
              animation_state.variant;              // Variant::Falling
              animation_state.idx;                  // 5               
                                                                       
                                                                       

Usage

  1. Create an enum to define animation loops
#[derive(Clone, PartialEq)]
pub enum PlayerAnimationVariant {
    Idle,
    Rising,
    Falling,
}
  1. Implement AnimationLoop for the enum
impl AnimationLoop for PlayerAnimationVariant {
    fn page(&self) -> (usize, usize) {
        match self {
            // return values (idx_offset, loop_size) describe the animation loop
            PlayerAnimationVariant::Idle => (0, 3),
            PlayerAnimationVariant::Rising => (2, 2),
            PlayerAnimationVariant::Falling => (4, 4),
        }
    }
}
  1. Create a struct to store current animation state
pub struct PlayerAnimationState {
    pub variant: PlayerAnimationVariant,
    pub idx: usize,
}
  1. And finally:

Option 1. use the handy macro here

#[derive(AnimationTransitionMacro)]
pub struct PlayerAnimationState {
    /// This is needed to tell the compiler the type of your variant enum
    #[variant]
    pub variant: PlayerAnimationVariant,
    pub idx: usize,
}

Option 2. Or Implement AnimationTransition for the newly created struct yourself

impl AnimationTransition<PlayerAnimationVariant> for PlayerAnimationState {
    fn wrapping_next_idx(&mut self) -> usize {
        // This is example implementation, you can choose to update the page however you like
        let current_idx = self.idx;
        let (offset, size) = self.variant.page();

        self.idx = offset + (current_idx + 1) % size;

        self.idx
    }

    fn transition_variant(&mut self, to: PlayerAnimationVariant) {
        let (offset, _) = to.page();
        self.variant = to;
        self.idx = offset;
    }
}

Dependencies

~235KB