summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/animation.rs144
-rw-r--r--src/npc.rs10
-rw-r--r--src/player.rs10
-rw-r--r--src/tileset.rs29
4 files changed, 118 insertions, 75 deletions
diff --git a/src/animation.rs b/src/animation.rs
index 24932b2..bc7e493 100644
--- a/src/animation.rs
+++ b/src/animation.rs
@@ -1,81 +1,117 @@
use ggez::graphics::Rect;
use std::collections::HashMap;
-use std::f32::consts::PI;
use std::time::Instant;
use crate::entity::Action;
use crate::tileset::Tileset;
-#[derive(Clone)]
+#[derive(Clone, PartialEq)]
+pub struct Frame {
+ pub source: Rect,
+ pub delay: Option<usize>,
+ pub rotation: f32,
+}
+
+impl Frame {
+ pub fn new(source: Rect, delay: Option<usize>, rotation: f32) -> Frame {
+ Frame {
+ source,
+ delay,
+ rotation,
+ }
+ }
+}
+
+#[derive(Clone, PartialEq)]
pub struct Animation {
- pub animation: Vec<(usize, Rect)>,
- pub animations: HashMap<Action, Vec<(usize, Rect)>>,
+ pub frames: Vec<Frame>,
pub timer: Instant,
- pub source: Rect,
+ pub current: Frame,
}
impl Animation {
- pub fn new(tileset: &Tileset) -> Animation {
- let mut animations = HashMap::new();
+ pub fn new() -> Animation {
+ Animation {
+ current: Frame::new(Rect::zero(), None, 0.0),
+ timer: Instant::now(),
+ frames: Vec::new(),
+ }
+ }
- let mut source = tileset.get_tile_by_entity_keyframe("player-top", 0);
- source.h += tileset.get_tile_by_entity_keyframe("player-bottom", 0).h;
- animations.insert(Action::IdleLeft, vec![(1, source)]);
+ pub fn give_frames(&mut self, frames: Vec<Frame>) {
+ self.frames = frames;
+ }
- let mut moving = tileset.get_tile_by_entity_keyframe("player-top", 1);
- moving.h += tileset.get_tile_by_entity_keyframe("player-bottom", 1).h;
+ pub fn update(&mut self) {
+ if let Some(mut i) = self.frames.iter().position(|a| a == &self.current) {
+ if let Some(delay) = self.current.delay {
+ 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 if !self.frames.is_empty() {
+ self.current = self.frames[0].clone();
+ }
+ }
+}
- animations.insert(Action::MovingLeft, vec![(100, source), (100, moving)]);
- animations.insert(Action::MovingUpLeft, vec![(100, source), (100, moving)]);
- animations.insert(Action::MovingDownLeft, vec![(100, source), (100, moving)]);
+#[derive(Clone)]
+pub struct Animations {
+ pub available: HashMap<Action, Animation>,
+ pub current: Animation,
+}
- source = flip(source);
- moving = flip(moving);
+impl Animations {
+ pub fn new(tileset: &Tileset) -> Animations {
+ let mut available = HashMap::new();
- animations.insert(Action::IdleRight, vec![(1, source)]);
+ let mut idle = tileset.get_frame_by_entity_keyframe("player-top", 0);
+ idle.source.h += tileset
+ .get_frame_by_entity_keyframe("player-bottom", 0)
+ .source
+ .h;
- animations.insert(Action::MovingRight, vec![(100, source), (100, moving)]);
- animations.insert(Action::MovingUpRight, vec![(100, source), (100, moving)]);
- animations.insert(Action::MovingDownRight, vec![(100, source), (100, moving)]);
+ let mut animation = Animation::new();
+ animation.give_frames(vec![idle.clone()]);
+ available.insert(Action::IdleLeft, animation.clone());
- Animation {
- animations,
- source,
- timer: Instant::now(),
- animation: Vec::new(),
- }
- }
+ let mut moving = tileset.get_frame_by_entity_keyframe("player-top", 1);
+ moving.source.h += tileset
+ .get_frame_by_entity_keyframe("player-bottom", 1)
+ .source
+ .h;
- pub fn update(&mut self, action: &Action) {
- self.animation = self.animations.get(&action).cloned().unwrap_or_default();
- let (source, timer) = next_source(self.source, &self.animation, self.timer);
- self.source = source;
- self.timer = timer;
- }
-}
+ animation.give_frames(vec![idle.clone(), moving.clone()]);
+ available.insert(Action::MovingLeft, animation.clone());
+ available.insert(Action::MovingUpLeft, animation.clone());
+ available.insert(Action::MovingDownLeft, animation.clone());
+
+ animation.give_frames(vec![flip(idle.clone())]);
+ available.insert(Action::IdleRight, animation.clone());
-pub fn next_source(source: Rect, animation: &[(usize, Rect)], timer: Instant) -> (Rect, Instant) {
- if let Some(mut i) = animation.iter().position(|a| a.1 == source) {
- if timer.elapsed().as_millis() > animation[i].0 as u128 {
- i = if i == animation.len() - 1 { 0 } else { i + 1 };
- (animation[i].1, Instant::now())
- } else {
- (source, timer)
+ animation.give_frames(vec![flip(idle.clone()), flip(moving.clone())]);
+ available.insert(Action::MovingRight, animation.clone());
+ available.insert(Action::MovingUpRight, animation.clone());
+ available.insert(Action::MovingDownRight, animation.clone());
+
+ Animations {
+ available,
+ current: Animation::new(),
}
- } else if !animation.is_empty() {
- (animation[0].1, timer)
- } else {
- (source, timer)
}
-}
-pub fn convert_angle_to_rad(angle: f32) -> f32 {
- angle * (PI / 180.0)
+ pub fn update(&mut self, action: &Action) {
+ let animation = self.available.get(&action).cloned().unwrap();
+ self.current.give_frames(animation.frames);
+ self.current.update();
+ }
}
-pub fn flip(rect: Rect) -> Rect {
- let mut r = rect;
- r.x *= -1.0;
- r.x -= rect.w;
- r
+pub fn flip(frame: Frame) -> Frame {
+ let mut f = frame.clone();
+ f.source.x *= -1.0;
+ f.source.x -= frame.source.w;
+ f
}
diff --git a/src/npc.rs b/src/npc.rs
index 96cb489..48e08b9 100644
--- a/src/npc.rs
+++ b/src/npc.rs
@@ -2,7 +2,7 @@ use ggez::graphics::{spritebatch::SpriteBatch, DrawParam};
use ggez::nalgebra::{/*distance,*/ Point2, Vector2};
//use std::time::Instant;
-use crate::animation::Animation;
+use crate::animation::Animations;
use crate::constants;
use crate::entity::{Entity, Operable};
use crate::map::Map;
@@ -12,14 +12,14 @@ use crate::tileset::Tileset;
pub struct NPC {
entity: Entity,
behavior: Behavior,
- animation: Animation,
+ animations: Animations,
}
impl Operable for NPC {
fn draw(&self, spritebatch: &mut SpriteBatch) {
spritebatch.add(
DrawParam::default()
- .src(self.animation.source)
+ .src(self.animations.current.current.source)
.dest(self.entity.position)
.scale(Vector2::new(constants::TILE_SCALE, constants::TILE_SCALE)),
);
@@ -32,7 +32,7 @@ impl Operable for NPC {
Behavior::Waiting(time) => (),
}
*/
- self.animation.update(&self.entity.action);
+ self.animations.update(&self.entity.action);
}
}
@@ -41,7 +41,7 @@ impl NPC {
NPC {
entity: Entity::new(spawn, map_dimensions),
behavior: Behavior::Wandering(None),
- animation: Animation::new(tileset),
+ animations: Animations::new(tileset),
}
}
diff --git a/src/player.rs b/src/player.rs
index ae43d80..2941934 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -2,21 +2,21 @@ use ggez::event::KeyCode;
use ggez::graphics::{spritebatch::SpriteBatch, DrawParam};
use ggez::nalgebra::{Point2, Vector2};
-use crate::animation::Animation;
+use crate::animation::Animations;
use crate::constants;
use crate::entity::{Action, Entity, Operable};
use crate::tileset::Tileset;
pub struct Player {
entity: Entity,
- animation: Animation,
+ animations: Animations,
}
impl Operable for Player {
fn draw(&self, spritebatch: &mut SpriteBatch) {
spritebatch.add(
DrawParam::default()
- .src(self.animation.source)
+ .src(self.animations.current.current.source)
.dest(self.entity.position)
.scale(Vector2::new(constants::TILE_SCALE, constants::TILE_SCALE)),
);
@@ -24,7 +24,7 @@ impl Operable for Player {
fn update(&mut self) {
self.move_position();
- self.animation.update(&self.entity.action);
+ self.animations.update(&self.entity.action);
}
}
@@ -32,7 +32,7 @@ impl Player {
pub fn new(tileset: &Tileset, dimensions: (f32, f32)) -> Player {
Player {
entity: Entity::new(Point2::new(0.0, 0.0), dimensions),
- animation: Animation::new(tileset),
+ animations: Animations::new(tileset),
}
}
diff --git a/src/tileset.rs b/src/tileset.rs
index 0595186..975398d 100644
--- a/src/tileset.rs
+++ b/src/tileset.rs
@@ -2,6 +2,7 @@ use ggez::filesystem::File;
use ggez::graphics::Rect;
use std::collections::HashMap;
+use crate::animation::Frame;
use crate::constants;
use crate::property::Property;
use crate::xmlelements::XMLElements;
@@ -96,17 +97,23 @@ impl Tileset {
}
}
- pub fn get_tile_by_entity_keyframe(&self, entity: &str, keyframe: usize) -> Rect {
- *self
- .tiles
- .get(
- &self
- .properties
- .iter()
- .find(|p| p.entity == Some(entity.to_string()) && Some(keyframe) == p.keyframe)
- .unwrap()
- .tile_id,
- )
+ pub fn get_frame_by_entity_keyframe(&self, entity: &str, keyframe: usize) -> Frame {
+ let tile_id = &self
+ .properties
+ .iter()
+ .find(|p| p.entity == Some(entity.to_string()) && Some(keyframe) == p.keyframe)
+ .unwrap()
+ .tile_id;
+
+ let delay = self
+ .properties
+ .iter()
+ .find(|p| p.tile_id == *tile_id && p.delay.is_some())
.unwrap()
+ .delay;
+
+ let source = self.tiles.get(tile_id).unwrap();
+
+ Frame::new(*source, delay, 0.0)
}
}