use crate::*;
pub use crossterm::style::Color;
use std::collections::HashSet;
#[derive(Default, Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct Point {
pub x: i32,
pub y: i32,
}
impl Point {
pub fn new(x: i32, y: i32) -> Self {
Self { x, y }
}
}
pub struct Sprite {
pub glyph: char,
pub fg: Color,
pub bg: Color,
}
#[derive(new)]
pub struct MultiSprite {
pub ascii: String,
pub width: u32,
pub height: u32,
pub fg: Vec<Color>,
pub bg: Vec<Color>,
}
#[derive(new, Default)]
pub struct AiPath {
pub path: Path,
}
pub struct RenderTarget(pub usize);
#[derive(new)]
pub struct AiDestination {
pub target: Point,
}
#[derive(new)]
pub struct GotoStraight {
pub target: Point,
pub speed: f32,
}
#[derive(new)]
pub struct GotoEntity {
pub entity: Entity,
pub speed: f32,
}
pub struct Collision;
#[derive(Debug, Clone)]
pub struct CollisionMap {
bitset: HBitSet,
width: u32,
height: u32,
}
impl CollisionMap {
pub fn new(width: u32, height: u32) -> Self {
Self {
bitset: HBitSet::with_capacity(width * height),
width,
height,
}
}
pub fn set(&mut self, x: u32, y: u32) {
self.bitset.add(self.index_of(x, y));
}
pub fn unset(&mut self, x: u32, y: u32) {
self.bitset.remove(self.index_of(x, y));
}
pub fn is_set(&self, x: u32, y: u32) -> bool {
self.bitset.contains(self.index_of(x, y))
}
pub fn size(&self) -> (u32, u32) {
(self.width, self.height)
}
pub fn clear(&mut self) {
self.bitset.clear();
}
pub fn index_of(&self, x: u32, y: u32) -> u32 {
let idx = y * self.width + x;
assert!(idx <= self.width * self.height - 1);
idx
}
pub fn position_of(&self, idx: u32) -> (u32, u32) {
assert!(self.width > 0);
assert!(self.height > 0);
(idx % self.width, idx / self.width)
}
pub fn is_inbound(&self, x: u32, y: u32) -> bool {
x < self.width && y < self.height
}
}
#[derive(new, Clone, Debug)]
pub struct Camera {
pub position: Point,
pub screen_position: Point,
pub size: Point,
}
impl Default for Camera {
fn default() -> Self {
Self {
position: Point::new(0, 0),
screen_position: Point::new(0, 0),
size: Point::new(80, 50),
}
}
}
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Direction {
North,
East,
South,
West,
Up,
Down,
}
#[derive(new)]
pub struct Viewshed {
pub visible_tiles: HashSet<Point>,
}
impl Default for Viewshed {
fn default() -> Self {
Self {
visible_tiles: HashSet::new(),
}
}
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn collision_map_set_unset_clear() {
let mut map = CollisionMap::new(5, 5);
assert!(!map.is_set(3, 3));
map.set(3, 3);
assert!(map.is_set(3, 3));
map.unset(3, 3);
assert!(!map.is_set(3, 3));
map.set(3, 3);
map.clear();
assert!(!map.is_set(3, 3));
}
#[test]
fn small_map() {
let _ = CollisionMap::new(0, 0);
let mut map = CollisionMap::new(1, 1);
map.set(0, 0);
assert!(map.is_set(0, 0));
}
#[test]
fn huge_map() {
let mut map = CollisionMap::new(1000, 1000);
map.set(999, 999);
}
#[test]
#[should_panic]
fn small_map_out_of_bounds() {
let mut map = CollisionMap::new(0, 0);
map.set(0, 0);
assert!(map.is_set(0, 0));
}
#[test]
#[should_panic]
fn big_map_out_of_bounds() {
let mut map = CollisionMap::new(1000, 1000);
map.set(1000, 1000);
assert!(map.is_set(1000, 1000));
map.set(9999, 1000);
assert!(map.is_set(9999, 1000));
}
}