Skip to content

Instantly share code, notes, and snippets.

Created August 6, 2017 11:53
Show Gist options
  • Save anonymous/e126f2ea51b5728d5ec1e2130d59d8bd to your computer and use it in GitHub Desktop.
Save anonymous/e126f2ea51b5728d5ec1e2130d59d8bd to your computer and use it in GitHub Desktop.
Rust code shared from the playground
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, C, T>
where T: Tile + 'a,
C: ObjectCollection + 'a
{
object_lists: &'a [Cow<'a, C>],
neighbours_iter: NeighboursIter<'a, T>,
}
impl<'a, C, T> ObjectsAroundIter<'a, C, T>
where T: Tile,
C: ObjectCollection
{
pub fn new(tiles: &'a [T], object_lists: &'a [Cow<'a, C>], width: usize, height: usize, center_x: usize, center_y: usize, radius: u8) -> ObjectsAroundIter<'a, C, T> {
let neighbours_iter = NeighboursIter::from_tiles(tiles, width, height, center_x, center_y, radius);
ObjectsAroundIter { object_lists, neighbours_iter }
}
}
impl<'a, C, T> Iterator for ObjectsAroundIter<'a, C, T>
where T: Tile,
C: ObjectCollection
{
type Item = (TileRef<'a, T>, &'a Cow<'a, 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, C, T>
where T: Tile + 'a,
C: ObjectCollection + 'a
{
object_lists: &'a mut [Cow<'a, C>],
neighbours_iter: NeighboursIterMut<'a, T>,
last_index: usize,
}
impl<'a, C, T> ObjectsAroundIterMut<'a, C, T>
where T: Tile,
C: ObjectCollection
{
pub fn new(tiles: &'a mut [T], object_lists: &'a mut [Cow<'a, C>], width: usize, height: usize, center_x: usize, center_y: usize, radius: u8) -> ObjectsAroundIterMut<'a, 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, C, T> Iterator for ObjectsAroundIterMut<'a, C, T>
where T: Tile,
C: ObjectCollection
{
type Item = (TileRefMut<'a, T>, &'a 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) {
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment