-
-
Save umurgdk/07ab1f10a88b96912a123e61e7aa2622 to your computer and use it in GitHub Desktop.
Rust code shared from the playground
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::borrow::Cow; | |
use std::fmt::Debug; | |
use specs::Entity; | |
use Tile; | |
use TileRef; | |
use TileRefMut; | |
use TileMap; | |
use NeighboursIter; | |
use NeighboursIterMut; | |
pub trait ObjectCollection: Debug + Clone {} | |
impl<'a, T: ToOwned + ?Sized + Clone + Debug + 'a> ObjectCollection for T {} | |
pub struct ObjectsAroundIter<'a, 'b: 'a, C, T> | |
where T: Tile + 'a, | |
C: ObjectCollection + 'b | |
{ | |
object_lists: &'a [Cow<'b, C>], | |
neighbours_iter: NeighboursIter<'a, T>, | |
} | |
impl<'a, 'b: 'a, C, T> ObjectsAroundIter<'a, 'b, C, T> | |
where T: Tile + 'a, | |
C: ObjectCollection + 'b | |
{ | |
pub fn new(tiles: &'a [T], object_lists: &'a [Cow<'b, C>], width: usize, height: usize, center_x: usize, center_y: usize, radius: u8) -> ObjectsAroundIter<'a, 'b, C, T> { | |
let neighbours_iter = NeighboursIter::from_tiles(tiles, width, height, center_x, center_y, radius); | |
ObjectsAroundIter { object_lists, neighbours_iter } | |
} | |
} | |
impl<'a, 'b: 'a, C, T> Iterator for ObjectsAroundIter<'a, 'b, C, T> | |
where T: Tile + 'a, | |
C: ObjectCollection + 'b | |
{ | |
type Item = (TileRef<'a, T>, &'a Cow<'b, C>); | |
fn next(&mut self) -> Option<Self::Item> { | |
self.neighbours_iter.next().map(|tile_ref| { | |
let object_list = self.object_lists.get(tile_ref.index).unwrap(); | |
(tile_ref, object_list) | |
}) | |
} | |
} | |
pub struct ObjectsAroundIterMut<'a, 'b: 'a, C, T> | |
where T: Tile + 'a, | |
C: ObjectCollection + 'b | |
{ | |
object_lists: &'a mut [Cow<'b, C>], | |
neighbours_iter: NeighboursIterMut<'a, T>, | |
last_index: usize, | |
} | |
impl<'a, 'b: 'a, C, T> ObjectsAroundIterMut<'a, 'b, C, T> | |
where T: Tile + 'a, | |
C: ObjectCollection + 'b | |
{ | |
pub fn new(tiles: &'a mut [T], object_lists: &'a mut [Cow<'b, C>], width: usize, height: usize, center_x: usize, center_y: usize, radius: u8) -> ObjectsAroundIterMut<'a, 'b, C, T> { | |
let neighbours_iter = NeighboursIterMut::from_tiles(tiles, width, height, center_x, center_y, radius); | |
ObjectsAroundIterMut { object_lists, neighbours_iter, last_index: 0 } | |
} | |
} | |
impl<'a, 'b: 'a, C, T> Iterator for ObjectsAroundIterMut<'a, 'b, C, T> | |
where T: Tile + 'a, | |
C: ObjectCollection + 'b | |
{ | |
type Item = (TileRefMut<'a, T>, &'b mut C); | |
fn next(&mut self) -> Option<Self::Item> { | |
use std::mem; | |
self.neighbours_iter.next().map(|tile_ref| { | |
let object_lists = mem::replace(&mut self.object_lists, &mut []); | |
let (head, rest) = object_lists.split_at_mut(tile_ref.index - self.last_index + 1); | |
self.object_lists = rest; | |
self.last_index = tile_ref.index + 1; | |
(tile_ref, head.last_mut().unwrap().to_mut()) | |
}) | |
} | |
} | |
#[cfg(test)] | |
mod test { | |
use std::cell::Cell; | |
use super::*; | |
use tilemap::TileMap; | |
use tilemap::Tile; | |
#[derive(Debug, PartialEq, Eq)] | |
struct MyObjectList { | |
statics: Vec<usize>, | |
max_clones: usize, | |
num_clones: Cell<usize>, | |
} | |
impl MyObjectList { | |
pub fn new(max_clones: usize) -> Self { | |
MyObjectList { statics: vec![], num_clones: Cell::new(0), max_clones } | |
} | |
pub fn add_object(&mut self, item: usize) { | |
println!("Adding object to list"); | |
self.statics.push(item); | |
} | |
} | |
impl Clone for MyObjectList { | |
fn clone(&self) -> Self { | |
println!("Tring to clone"); | |
let clones = self.num_clones.get(); | |
if clones >= self.max_clones { | |
panic!("Shouldn't be cloned!"); | |
} | |
self.num_clones.set(clones + 1); | |
println!("Cloning objects_list"); | |
Self { statics: self.statics.clone(), num_clones: self.num_clones.clone(), max_clones: self.max_clones } | |
} | |
} | |
impl<'a> From<&'a MyObjectList> for Cow<'a, MyObjectList> { | |
fn from(s: &'a MyObjectList) -> Self { | |
Cow::Borrowed(s) | |
} | |
} | |
#[derive(Clone)] | |
struct EmptyTile; | |
impl Tile for EmptyTile { | |
fn new() -> EmptyTile { | |
EmptyTile | |
} | |
} | |
#[test] | |
fn objects_around_mut() { | |
let object_list = MyObjectList::new(3); | |
let mut map = TileMap::<MyObjectList, EmptyTile>::new(5, 5, Cow::from(&object_list)); | |
for (tile_ref, obj_list) in map.objects_around_mut(0, 0, 1) { | |
obj_list.add_object(tile_ref.x); | |
obj_list.add_object(tile_ref.y); | |
} | |
for (tile_ref, obj_list) in map.objects_around(0, 0, 1) { | |
assert_eq!((*obj_list).statics, vec![tile_ref.x, tile_ref.y]); | |
} | |
} | |
#[test] | |
fn objects_around() { | |
let object_list = MyObjectList::new(0); | |
let mut map = TileMap::<MyObjectList, EmptyTile>::new(5, 5, Cow::from(&object_list)); | |
for (tile_ref, obj_list) in map.objects_around(2, 2, 2) { | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::ops::Deref; | |
use std::ops::DerefMut; | |
use std::borrow::Cow; | |
use std::marker::PhantomData; | |
use specs::Entity; | |
pub mod iterators; | |
pub use iterators::*; | |
pub mod objects; | |
use objects::*; | |
pub trait Tile: Sized + Clone { | |
fn new() -> Self; | |
} | |
#[derive(Debug, Clone)] | |
pub struct TileMap<'a, C, T> | |
where T: Tile, | |
C: ObjectCollection + 'a | |
{ | |
tiles: Vec<T>, | |
objects: Vec<Cow<'a, C>>, | |
pub width: usize, | |
pub height: usize, | |
} | |
impl<'a, C, T> TileMap<'a, C, T> | |
where T: Tile, | |
C: ObjectCollection + 'a | |
{ | |
pub fn new(width: usize, height: usize, empty_objects_list: Cow<'a, C>) -> TileMap<'a, C, T> { | |
let size = width * height; | |
let mut tiles = vec![T::new(); width * height]; | |
let mut objects = vec![empty_objects_list; width * height]; | |
TileMap { tiles, width, height, objects } | |
} | |
fn coords_to_index(&self, x: usize, y: usize) -> usize { | |
y * self.width + x | |
} | |
fn index_to_coords(&self, index: usize) -> (usize, usize) { | |
let x = index % self.width; | |
let y = (index as f32 / self.width as f32).floor() as usize; | |
(x, y) | |
} | |
pub fn at(&self, x: usize, y: usize) -> Option<&T> { | |
let index = self.coords_to_index(x, y); | |
self.tiles.get(index) | |
} | |
pub fn at_mut(&mut self, x: usize, y: usize) -> Option<&mut T> { | |
let index = y * self.width + x; | |
self.tiles.get_mut(index) | |
} | |
pub fn iter(&self) -> Iter<T> { | |
Iter::from_tiles(&self.tiles, self.width) | |
} | |
pub fn iter_mut(&mut self) -> IterMut<T> { | |
IterMut::from_tiles(&mut self.tiles, self.width) | |
} | |
pub fn tiles_around(&self, x: usize, y: usize, radius: u8) -> NeighboursIter<T> { | |
NeighboursIter::from_tiles(&self.tiles, self.width, self.height, x, y, radius) | |
} | |
pub fn tiles_around_mut(&mut self, x: usize, y: usize, radius: u8) -> NeighboursIterMut<T> { | |
let (width, height) = (self.width, self.height); | |
NeighboursIterMut::from_tiles(&mut self.tiles, width, height, x, y, radius) | |
} | |
pub fn objects_around(&self, x: usize, y: usize, radius: u8) -> ObjectsAroundIter<C, T> { | |
let (width, height) = (self.width, self.height); | |
ObjectsAroundIter::new(&self.tiles, &self.objects, width, height, x, y, radius) | |
} | |
pub fn objects_around_mut(&mut self, x: usize, y: usize, radius: u8) -> ObjectsAroundIterMut<'a, 'a, C, T> { | |
let (width, height) = (self.width, self.height); | |
ObjectsAroundIterMut::new(&mut self.tiles, &mut self.objects, width, height, x, y, radius) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment