rust-sokoban/src/components.rs

118 lines
2.4 KiB
Rust

use specs::{Component, NullStorage, VecStorage, World, WorldExt};
use std::fmt;
use std::fmt::Display;
#[derive(PartialEq)]
pub enum BoxColor {
Red,
Blue,
Green,
Brown,
}
impl Display for BoxColor {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str(match self {
BoxColor::Red => "red",
BoxColor::Blue => "blue",
BoxColor::Green => "green",
BoxColor::Brown => "brown",
})?;
Ok(())
}
}
pub enum RenderableKind {
Static,
Animated,
}
#[derive(Debug, Component, Clone, Copy)]
#[storage(VecStorage)]
pub struct Position {
pub x: u8,
pub y: u8,
pub z: u8,
}
impl Position {
pub fn new(x: u8, y: u8) -> Self {
Position { x, y, z: 0 }
}
pub fn with_z(self, z: u8) -> Self {
Position { z, ..self }
}
}
#[derive(Component)]
#[storage(VecStorage)]
pub struct Renderable {
paths: Vec<String>,
}
impl Renderable {
pub fn new_static(path: String) -> Self {
Self { paths: vec![path] }
}
pub fn new_animated(paths: Vec<String>) -> Self {
Self { paths }
}
pub fn kind(&self) -> RenderableKind {
match self.paths.len() {
0 => panic!("invalid renderable"),
1 => RenderableKind::Static,
_ => RenderableKind::Animated,
}
}
pub fn path(&self, path_index: usize) -> String {
// If we get asked for a path that is larger than the
// number of paths we actually have, we simply mod the index
// with the length to get an index that is in range
self.paths[path_index % self.paths.len()].clone()
}
}
#[derive(Component)]
#[storage(VecStorage)]
pub struct Wall {}
#[derive(Component)]
#[storage(VecStorage)]
pub struct Player {}
#[derive(Component)]
#[storage(VecStorage)]
pub struct Box {
pub color: BoxColor,
}
#[derive(Component)]
#[storage(VecStorage)]
pub struct BoxSpot {
pub color: BoxColor,
}
#[derive(Component, Default)]
#[storage(NullStorage)]
pub struct Movable;
#[derive(Component, Default)]
#[storage(NullStorage)]
pub struct Immovable;
pub fn register_components(world: &mut World) {
world.register::<Position>();
world.register::<Renderable>();
world.register::<Player>();
world.register::<Wall>();
world.register::<Box>();
world.register::<BoxSpot>();
world.register::<Movable>();
world.register::<Immovable>();
}