From 83ff2ad49e6d3bf83fd85fcfee68a454372bf22a Mon Sep 17 00:00:00 2001 From: tom barrett Date: Thu, 4 Jul 2019 07:39:51 -0500 Subject: moved animation file, moved player function to enitity, tile now uses animation, move drawing from npc tile player to animation --- src/animation.rs | 117 ------------------------------------------- src/animations.rs | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/entity.rs | 49 +++++++++++++++++- src/layer.rs | 1 + src/lib.rs | 2 +- src/npc.rs | 15 ++---- src/player.rs | 57 ++------------------- src/tile.rs | 66 ++++++++++++------------- src/tileset.rs | 6 +-- 9 files changed, 240 insertions(+), 218 deletions(-) delete mode 100644 src/animation.rs create mode 100644 src/animations.rs diff --git a/src/animation.rs b/src/animation.rs deleted file mode 100644 index bc7e493..0000000 --- a/src/animation.rs +++ /dev/null @@ -1,117 +0,0 @@ -use ggez::graphics::Rect; -use std::collections::HashMap; -use std::time::Instant; - -use crate::entity::Action; -use crate::tileset::Tileset; - -#[derive(Clone, PartialEq)] -pub struct Frame { - pub source: Rect, - pub delay: Option, - pub rotation: f32, -} - -impl Frame { - pub fn new(source: Rect, delay: Option, rotation: f32) -> Frame { - Frame { - source, - delay, - rotation, - } - } -} - -#[derive(Clone, PartialEq)] -pub struct Animation { - pub frames: Vec, - pub timer: Instant, - pub current: Frame, -} - -impl Animation { - pub fn new() -> Animation { - Animation { - current: Frame::new(Rect::zero(), None, 0.0), - timer: Instant::now(), - frames: Vec::new(), - } - } - - pub fn give_frames(&mut self, frames: Vec) { - self.frames = frames; - } - - 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(); - } - } -} - -#[derive(Clone)] -pub struct Animations { - pub available: HashMap, - pub current: Animation, -} - -impl Animations { - pub fn new(tileset: &Tileset) -> Animations { - let mut available = HashMap::new(); - - 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; - - let mut animation = Animation::new(); - animation.give_frames(vec![idle.clone()]); - available.insert(Action::IdleLeft, animation.clone()); - - 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; - - 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()); - - 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(), - } - } - - 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(frame: Frame) -> Frame { - let mut f = frame.clone(); - f.source.x *= -1.0; - f.source.x -= frame.source.w; - f -} diff --git a/src/animations.rs b/src/animations.rs new file mode 100644 index 0000000..f1ec902 --- /dev/null +++ b/src/animations.rs @@ -0,0 +1,145 @@ +use ggez::graphics::{spritebatch::SpriteBatch, DrawParam, Rect}; +use ggez::nalgebra::{Point2, Vector2}; +use std::collections::HashMap; +use std::time::Instant; + +use crate::constants; +use crate::entity::Action; +use crate::tileset::Tileset; + +#[derive(Debug, Clone, PartialEq)] +pub struct Frame { + pub source: Rect, + pub delay: Option, + pub rotation: f32, +} + +impl Frame { + pub fn new(source: Rect, delay: Option, rotation: f32) -> Frame { + Frame { + source, + delay, + rotation, + } + } +} + +impl Default for Frame { + fn default() -> Frame { + Frame::new(Rect::zero(), None, 0.0) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct Animation { + pub frames: Vec, + pub timer: Instant, + pub current: Frame, +} + +impl Default for Animation { + fn default() -> Animation { + Animation::new(Frame::default()) + } +} + +impl Animation { + pub fn new(current: Frame) -> Animation { + Animation { + current, + timer: Instant::now(), + frames: Vec::new(), + } + } + + pub fn give_frames(&mut self, frames: Vec) { + self.frames = frames; + } + + 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(); + } + } + + pub fn draw(&self, spritebatch: &mut SpriteBatch, position: Point2) { + spritebatch.add( + DrawParam::default() + .src(self.current.source) + .dest(position) + .scale(Vector2::new(constants::TILE_SCALE, constants::TILE_SCALE)), + ); + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct Animations { + pub available: HashMap, + pub current: Animation, +} + +impl Animations { + pub fn new(tileset: &Tileset) -> Animations { + let mut available = HashMap::new(); + + 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; + + let mut animation = Animation::new(idle.clone()); + animation.give_frames(vec![idle.clone()]); + available.insert(Action::IdleLeft, animation.clone()); + + 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; + + 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()); + + 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::default(), + } + } + + 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: Point2) { + self.current.draw(spritebatch, position) + } +} + +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/entity.rs b/src/entity.rs index 8086b77..ae3a236 100644 --- a/src/entity.rs +++ b/src/entity.rs @@ -1,6 +1,8 @@ use ggez::graphics::spritebatch::SpriteBatch; use ggez::nalgebra::Point2; +use crate::constants; + pub trait Operable { fn update(&mut self); fn draw(&self, spritebatch: &mut SpriteBatch); @@ -23,9 +25,54 @@ impl Entity { map_dimensions, } } + + pub fn update(&mut self) { + self.move_position(); + } + + fn move_position(&mut self) { + match self.action { + Action::MovingUp => self.position.y -= constants::PLAYER_SPEED, + Action::MovingUpLeft => { + self.position.x -= constants::PLAYER_SPEED / 2.0_f32.sqrt(); + self.position.y -= constants::PLAYER_SPEED / 2.0_f32.sqrt(); + } + Action::MovingUpRight => { + self.position.x += constants::PLAYER_SPEED / 2.0_f32.sqrt(); + self.position.y -= constants::PLAYER_SPEED / 2.0_f32.sqrt(); + } + Action::MovingLeft => self.position.x -= constants::PLAYER_SPEED, + Action::MovingDown => self.position.y += constants::PLAYER_SPEED, + Action::MovingDownLeft => { + self.position.x -= constants::PLAYER_SPEED / 2.0_f32.sqrt(); + self.position.y += constants::PLAYER_SPEED / 2.0_f32.sqrt(); + } + Action::MovingDownRight => { + self.position.x += constants::PLAYER_SPEED / 2.0_f32.sqrt(); + self.position.y += constants::PLAYER_SPEED / 2.0_f32.sqrt(); + } + Action::MovingRight => self.position.x += constants::PLAYER_SPEED, + Action::IdleLeft | Action::IdleRight => (), + } + + let pixel_width = constants::TILE_WIDTH * constants::TILE_SCALE; + let pixel_height = constants::TILE_HEIGHT * constants::TILE_SCALE; + + if self.position.x < 0.0 { + self.position.x = 0.0; + } else if self.position.x + pixel_height > self.map_dimensions.0 { + self.position.x = self.map_dimensions.0 - pixel_width; + } + + if self.position.y < 0.0 { + self.position.y = 0.0; + } else if self.position.y + pixel_height > self.map_dimensions.1 { + self.position.y = self.map_dimensions.1 - pixel_height; + } + } } -#[derive(Clone, Hash, Eq, PartialEq)] +#[derive(Clone, Hash, Eq, PartialEq, Debug)] pub enum Action { IdleLeft, IdleRight, diff --git a/src/layer.rs b/src/layer.rs index ae645fb..0247d81 100644 --- a/src/layer.rs +++ b/src/layer.rs @@ -1,5 +1,6 @@ use ggez::graphics::spritebatch::SpriteBatch; +use crate::entity::Operable; use crate::tile::Tile; use crate::tileset::Tileset; diff --git a/src/lib.rs b/src/lib.rs index 14c74d1..ed8948f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -pub mod animation; +pub mod animations; pub mod camera; pub mod constants; pub mod entity; diff --git a/src/npc.rs b/src/npc.rs index 48e08b9..9316e69 100644 --- a/src/npc.rs +++ b/src/npc.rs @@ -1,9 +1,7 @@ -use ggez::graphics::{spritebatch::SpriteBatch, DrawParam}; -use ggez::nalgebra::{/*distance,*/ Point2, Vector2}; -//use std::time::Instant; +use ggez::graphics::spritebatch::SpriteBatch; +use ggez::nalgebra::Point2; -use crate::animation::Animations; -use crate::constants; +use crate::animations::Animations; use crate::entity::{Entity, Operable}; use crate::map::Map; use crate::tileset::Tileset; @@ -17,12 +15,7 @@ pub struct NPC { impl Operable for NPC { fn draw(&self, spritebatch: &mut SpriteBatch) { - spritebatch.add( - DrawParam::default() - .src(self.animations.current.current.source) - .dest(self.entity.position) - .scale(Vector2::new(constants::TILE_SCALE, constants::TILE_SCALE)), - ); + self.animations.draw(spritebatch, self.entity.position); } fn update(&mut self) { diff --git a/src/player.rs b/src/player.rs index 2941934..5993d21 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,9 +1,8 @@ use ggez::event::KeyCode; -use ggez::graphics::{spritebatch::SpriteBatch, DrawParam}; -use ggez::nalgebra::{Point2, Vector2}; +use ggez::graphics::spritebatch::SpriteBatch; +use ggez::nalgebra::Point2; -use crate::animation::Animations; -use crate::constants; +use crate::animations::Animations; use crate::entity::{Action, Entity, Operable}; use crate::tileset::Tileset; @@ -14,16 +13,11 @@ pub struct Player { impl Operable for Player { fn draw(&self, spritebatch: &mut SpriteBatch) { - spritebatch.add( - DrawParam::default() - .src(self.animations.current.current.source) - .dest(self.entity.position) - .scale(Vector2::new(constants::TILE_SCALE, constants::TILE_SCALE)), - ); + self.animations.draw(spritebatch, self.get_position()); } fn update(&mut self) { - self.move_position(); + self.entity.update(); self.animations.update(&self.entity.action); } } @@ -40,47 +34,6 @@ impl Player { self.entity.position } - fn move_position(&mut self) { - match self.entity.action { - Action::MovingUp => self.entity.position.y -= constants::PLAYER_SPEED, - Action::MovingUpLeft => { - self.entity.position.x -= constants::PLAYER_SPEED / 2.0_f32.sqrt(); - self.entity.position.y -= constants::PLAYER_SPEED / 2.0_f32.sqrt(); - } - Action::MovingUpRight => { - self.entity.position.x += constants::PLAYER_SPEED / 2.0_f32.sqrt(); - self.entity.position.y -= constants::PLAYER_SPEED / 2.0_f32.sqrt(); - } - Action::MovingLeft => self.entity.position.x -= constants::PLAYER_SPEED, - Action::MovingDown => self.entity.position.y += constants::PLAYER_SPEED, - Action::MovingDownLeft => { - self.entity.position.x -= constants::PLAYER_SPEED / 2.0_f32.sqrt(); - self.entity.position.y += constants::PLAYER_SPEED / 2.0_f32.sqrt(); - } - Action::MovingDownRight => { - self.entity.position.x += constants::PLAYER_SPEED / 2.0_f32.sqrt(); - self.entity.position.y += constants::PLAYER_SPEED / 2.0_f32.sqrt(); - } - Action::MovingRight => self.entity.position.x += constants::PLAYER_SPEED, - Action::IdleLeft | Action::IdleRight => (), - } - - let pixel_width = constants::TILE_WIDTH * constants::TILE_SCALE; - let pixel_height = constants::TILE_HEIGHT * constants::TILE_SCALE; - - if self.entity.position.x < 0.0 { - self.entity.position.x = 0.0; - } else if self.entity.position.x + pixel_height > self.entity.map_dimensions.0 { - self.entity.position.x = self.entity.map_dimensions.0 - pixel_width; - } - - if self.entity.position.y < 0.0 { - self.entity.position.y = 0.0; - } else if self.entity.position.y + pixel_height > self.entity.map_dimensions.1 { - self.entity.position.y = self.entity.map_dimensions.1 - pixel_height; - } - } - pub fn give_key_down(&mut self, keycode: KeyCode) { let original_state = self.entity.action.clone(); diff --git a/src/tile.rs b/src/tile.rs index 1f3c2f7..144e764 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -1,19 +1,36 @@ -use ggez::graphics::{spritebatch::SpriteBatch, DrawParam, Rect}; -use ggez::nalgebra::{Point2, Vector2}; -use std::time::Instant; +use ggez::graphics::spritebatch::SpriteBatch; +use ggez::nalgebra::Point2; +use crate::animations::{Animation, Frame}; use crate::constants; -use crate::math::{convert_angle_to_rad, flip, next_source}; +use crate::entity::Operable; +use crate::math::{convert_angle_to_rad, flip}; use crate::tileset::Tileset; -#[derive(Clone, Debug)] +#[derive(Debug, Clone)] pub struct Tile { pub id: usize, - source: Rect, - animation: Vec<(usize, Rect)>, - timer: Instant, + pub animation: Animation, pub destination: Point2, - rotation: f32, +} + +impl Operable for Tile { + fn update(&mut self) { + self.animation.update(); + } + + fn draw(&self, spritebatch: &mut SpriteBatch) { + self.animation.draw(spritebatch, self.destination); + /* + DrawParam::default() + .src(self.animation.current.source) + .dest(self.destination) + .offset(Point2::new(0.5, 0.5)) + //.rotation(self.rotation) + .scale(Vector2::new(constants::TILE_SCALE, constants::TILE_SCALE)), + ); + */ + } } impl Tile { @@ -44,37 +61,20 @@ impl Tile { let x = i as f32 % width as f32; let y = (i as f32 / height as f32).floor(); - let offset = (constants::TILE_WIDTH / 2.0) * constants::TILE_SCALE; + //let offset = (constants::TILE_WIDTH / 2.0) * constants::TILE_SCALE; let destination = Point2::new( - (constants::TILE_WIDTH * constants::TILE_SCALE * x) + offset, - (constants::TILE_HEIGHT * constants::TILE_SCALE * y) + offset, + constants::TILE_WIDTH * constants::TILE_SCALE * x, //+ offset, + constants::TILE_HEIGHT * constants::TILE_SCALE * y, //+ offset, ); + let mut animation = Animation::new(Frame::new(source, None, rotation)); + animation.give_frames(tileset.get_frames(id)); + Tile { id, - source, - animation: tileset.get_animation(id), - timer: Instant::now(), + animation, destination, - rotation, } } - - pub fn update(&mut self) { - let (source, timer) = next_source(self.source, &self.animation, self.timer); - self.source = source; - self.timer = timer; - } - - pub fn draw(&self, spritebatch: &mut SpriteBatch) { - let draw_param = DrawParam::default() - .src(self.source) - .dest(self.destination) - .offset(Point2::new(0.5, 0.5)) - .rotation(self.rotation) - .scale(Vector2::new(constants::TILE_SCALE, constants::TILE_SCALE)); - - spritebatch.add(draw_param); - } } diff --git a/src/tileset.rs b/src/tileset.rs index 975398d..ee7128f 100644 --- a/src/tileset.rs +++ b/src/tileset.rs @@ -2,7 +2,7 @@ use ggez::filesystem::File; use ggez::graphics::Rect; use std::collections::HashMap; -use crate::animation::Frame; +use crate::animations::Frame; use crate::constants; use crate::property::Property; use crate::xmlelements::XMLElements; @@ -84,13 +84,13 @@ impl Tileset { .collect() } - pub fn get_animation(&self, tile_id: usize) -> Vec<(usize, Rect)> { + pub fn get_frames(&self, tile_id: usize) -> Vec { if let Some(property) = self.properties.iter().find(|p| p.tile_id == tile_id) { self.properties .clone() .into_iter() .filter(|p| p.entity == property.entity && p.entity.is_some()) - .map(|p| (p.delay.unwrap(), self.get(p.tile_id))) + .map(|p| Frame::new(self.get(p.tile_id), p.delay, 0.0)) .collect() } else { Vec::new() -- cgit v1.2.3