summaryrefslogtreecommitdiff
path: root/src/animations.rs
blob: 21e05c7a6ba7b667daf1b8f91584485f050f61ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use ggez::graphics::spritebatch::SpriteBatch;
use rand::Rng;
use std::collections::HashMap;
use std::time::Instant;

use crate::entity::Action;
use crate::tile::{flip, Tile};
use crate::tileset::Tileset;

#[derive(Debug, Clone, PartialEq)]
pub struct Animation {
    frames: Vec<Tile>,
    timer: Instant,
    current: Tile,
}

impl Animation {
    pub fn new(frames: Vec<Tile>) -> Animation {
        Animation {
            current: frames[0].clone(),
            timer: Instant::now(),
            frames,
        }
    }

    pub fn give_frames(&mut self, frames: Vec<Tile>) {
        self.frames = frames;
    }

    pub fn update(&mut self) {
        if let Some(mut i) = self.frames.iter().position(|a| a == &self.current) {
            if let Some(mut delay) = self.current.properties.delay {
                if let Some(scramble_delay) = self.current.properties.scramble_delay {
                    if scramble_delay {
                        delay = rand::thread_rng().gen_range(delay as f32 * 0.6, delay as f32 * 1.4)
                            as usize;
                    }
                }
                if self.timer.elapsed().as_millis() > delay as u128 {
                    i = if i == self.frames.len() - 1 { 0 } else { i + 1 };
                    self.current = self.frames[i].clone();
                    self.timer = Instant::now();
                }
            }
        } else {
            self.current = self.frames[0].clone();
        }
    }

    pub fn draw(&self, spritebatch: &mut SpriteBatch, position: glam::Vec2) {
        self.current.draw(spritebatch, position);
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct Animations {
    available: HashMap<Action, Animation>,
    current: Animation,
}

impl Animations {
    pub fn new(tileset: &Tileset) -> Animations {
        let mut available = HashMap::new();

        let mut idle = tileset.get_tile_by_entity_keyframe("player-top", 0);
        idle.source.h *= 2.0;

        let animation = Animation::new(vec![idle.clone()]);
        available.insert(Action::IdleLeft, animation);

        let mut moving = tileset.get_tile_by_entity_keyframe("player-top", 1);
        moving.source.h *= 2.0;

        let animation = Animation::new(vec![idle.clone(), moving.clone()]);
        available.insert(Action::MovingLeft, animation.clone());
        available.insert(Action::MovingUpLeft, animation.clone());
        available.insert(Action::MovingDownLeft, animation);

        let idle = flip(idle);
        let moving = flip(moving);

        let animation = Animation::new(vec![idle.clone()]);
        available.insert(Action::IdleRight, animation);

        let animation = Animation::new(vec![idle, moving]);
        available.insert(Action::MovingRight, animation.clone());
        available.insert(Action::MovingUpRight, animation.clone());
        available.insert(Action::MovingDownRight, animation.clone());

        Animations {
            available,
            current: animation,
        }
    }

    pub fn update(&mut self, action: &Action) {
        if let Some(animation) = self.available.get(&action).cloned() {
            self.current.give_frames(animation.frames);
        }
        self.current.update();
    }

    pub fn draw(&self, spritebatch: &mut SpriteBatch, position: glam::Vec2) {
        self.current.draw(spritebatch, position)
    }
}