Skip to content

Instantly share code, notes, and snippets.

@umurgdk
Forked from anonymous/playground.rs
Last active August 6, 2017 12:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save umurgdk/07ab1f10a88b96912a123e61e7aa2622 to your computer and use it in GitHub Desktop.
Save umurgdk/07ab1f10a88b96912a123e61e7aa2622 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, '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) {
}
}
}
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