kvark / claymore

Just another tactical RPG in dark fantasy setting
Apache License 2.0
54 stars 3 forks source link

Sample grid code #2

Closed kvark closed 9 years ago

kvark commented 9 years ago
pub type Coordinate = (int,int,int);
static MaxSize : uint = 20;

struct Point(float,float,float);
impl core::ops::Add<Point,Point> for Point  {
    fn add( &self, rhs: &Point )-> Point    {
        let Point(x1,y1,z1) = *self;
        let Point(x2,y2,z2) = *rhs;
        Point( x1+x2, y1+y2, z1+z2 )
    }
}
impl core::ops::Mul<float,Point> for Point  {
    fn mul( &self, rhs: &float )-> Point    {
        let Point(x,y,z) = *self;
        Point( x**rhs, y**rhs, z**rhs )
    }
}

pub enum Cell<Unit> {
    CellEmpty,
    CellObstacle,
    CellUnit(Unit),
}
impl<Unit:Copy> Copy for Cell<Unit>;

//TODO: use new iterators
trait PureGrid  {
    fn get_neighbours( c : Coordinate )-> ~[Coordinate];
    fn get_center( &self, c : Coordinate )-> Point;
    fn get_coordinate( &self, p : Point )-> Coordinate;
    fn is_out_bounds( &self, c : Coordinate )-> bool;
}

trait Grid<Unit> : PureGrid {
    fn mut_cell( &mut self, c : Coordinate, fun : &fn(&mut Cell<Unit>) )-> bool;
}

struct Grid2D<Unit> {
    corner  : Point,
    side    : float,
    dim     : (uint,uint),
    cells   : [[Cell<Unit>, ..MaxSize], ..MaxSize],
}

//  Quad    //

pub struct GridQuad<Unit>( Grid2D<Unit> );

impl<Unit> PureGrid for GridQuad<Unit>  {
    fn get_neighbours( c : Coordinate )-> ~[Coordinate] {
        let (i,j,k) = c;
        ~[ (i+1,j,k), (i,j+1,k), (i-1,j,k), (i,j-1,k) ]
    }
    fn get_center( &self, c : Coordinate )-> Point  {
        let (i,j,_) = c;
        self.corner + Point(i as float,j as float,0f) * self.side
    }
    fn get_coordinate( &self, p : Point )-> Coordinate  {
        let Point(x,y,_) = (p + self.corner*-1f) * (1f/self.side);
        (x as int, y as int, 0)
    }
    fn is_out_bounds( &self, c : Coordinate )-> bool    {
        let (i,j,_) = c, (dx,dy) = self.dim;
        i<0 || j<0 || i>=dx as int || j>=dy as int
    }
}

impl<Unit> Grid<Unit> for GridQuad<Unit>    {
    fn mut_cell( &mut self, c : Coordinate, fun : &fn(&mut Cell<Unit>) )-> bool {
        if self.is_out_bounds( c )  {
            false
        }else   {
            let (i,j,_) = c;
            fun( &mut self.cells[i][j] );
            true
        }
    }
}

//  Triangle    //
pub struct GridTriangle<Unit>( Grid2D<Unit> );

impl<Unit> PureGrid for GridTriangle<Unit>  {
    fn get_neighbours( c : Coordinate )-> ~[Coordinate] {
        let (i,j,k) = c;
        match j&3   {
            0   => ~[ (i,j+1,k), (i-1,j+1,k), (i,j-1,k) ],
            1   => ~[ (i+1,j-1,k), (i,j+1,k), (i,j-1,k) ],
            2   => ~[ (i+1,j+1,k), (i,j+1,k), (i,j-1,k) ],
            3   => ~[ (i,j-1,k), (i,j+1,k), (i-1,j-1,k) ],
            _   => fail!(~"")
        }
    }
    fn get_center( &self, c : Coordinate )-> Point  {
        let (i,j,_) = c;
        let ho3 = self.side * float::sqrt(3f) / 6f;
        let x = (i as float)*self.side +
            if (j+1)&2==0   {0f} else {0.5f*self.side};
        let y = (((j+1)/2) as float)*ho3*3f +
            if j&1==0   {ho3} else {-ho3};
        self.corner + Point(x,y,0f)
    }
    fn get_coordinate( &self, p : Point )-> Coordinate  {
        let Point(x,y,_) = p;
        let h = self.side * float::sqrt(3f) / 2f;
        let jt = (y/h) as int;
        let y0 = (jt as float) * h;
        let xt = x - (y-y0) * self.side / h;
        let i = (xt/self.side) as int;
        let x0 = (i as float) * self.side;
        let j = 2*jt + (if x-x0+y-y0 > self.side {1} else {0});
        (i,j,0)
    }
    fn is_out_bounds( &self, c : Coordinate )-> bool    {
        let (i,j,_) = c, (dx,dy) = self.dim;
        i<0 || j<0 || i>=dx as int || j>=dy as int
    }
}

impl<Unit> Grid<Unit> for GridTriangle<Unit>    {
    fn mut_cell( &mut self, c : Coordinate, fun : &fn(&mut Cell<Unit>) )-> bool {
        if self.is_out_bounds( c )  {
            false
        }else   {
            let (i,j,_) = c;
            fun( &mut self.cells[i][j] );
            true
        }
    }
}

// ----- //

pub fn create_grid<Unit:Copy+Owned>( topology : uint, dim : (uint,uint), side : float )-> ~Grid<Unit>   {
    let base : Grid2D<Unit> = Grid2D{
        corner  : Point(0f,0f,0f),
        side    : side,
        dim     : dim,
        cells   : [[CellEmpty, ..MaxSize], ..MaxSize],
    };
    match topology  {
        3   => ~GridTriangle( base ) as ~Grid<Unit>,
        4   => ~GridQuad    ( base ) as ~Grid<Unit>,
        _   => fail!(fmt!( "Unsupported topology %u", topology ))
    }
}

fn main()   {
    //empty
}
kvark commented 9 years ago

Alternatively, use https://github.com/dpc/hex2d-rs

kvark commented 9 years ago

Or https://github.com/kvark/grid-rs Related to #17

kvark commented 9 years ago

Grid is abstracted away now, and the relevant issues will be created for grid-rs.