123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- use ggez::{Context,GameError};
- use ggez::graphics::{Drawable,DrawParam,Image};
- use ggez::graphics::spritebatch::{SpriteBatch,SpriteIdx};
- use std::path::Path;
- /// we only care about 16x16 tilesets
- const TILE_SIZE: f32 = 1.0 / 16.0;
- pub struct Board {
- size: Size,
- contents: Vec<(u8, SpriteIdx)>,
- tileset: Tileset,
- }
- pub struct Tileset {
- tile_size: Size,
- batch: SpriteBatch,
- }
- impl Tileset {
- pub fn from_file(ctx: &mut Context, tile_size: impl Into<Size>, file: impl AsRef<Path>) -> Result<Tileset, GameError> {
- let tile_size = tile_size.into();
- let image = Image::new(ctx, file)?;
- let mut batch = SpriteBatch::new(image);
- batch.set_filter(ggez::graphics::FilterMode::Nearest);
- Ok(Tileset { tile_size, batch })
- }
- fn to_screen(&self, coord: impl Into<Coord>) -> [f32;2] {
- let Coord { x, y } = coord.into();
- [(x * self.tile_size.width) as f32,
- (y * self.tile_size.height) as f32,
- ]
- }
- }
- #[derive(Debug, PartialEq, Eq, Hash)]
- pub struct Size {
- width: usize,
- height: usize,
- }
- impl From<[usize;2]> for Size {
- fn from([width, height]: [usize;2]) -> Size {
- Size { width, height }
- }
- }
- #[derive(Debug, PartialEq, Eq, Hash)]
- pub struct Coord {
- x: usize,
- y: usize,
- }
- impl From<[usize;2]> for Coord {
- fn from([x, y]: [usize;2]) -> Coord {
- Coord { x, y }
- }
- }
- impl Board {
- pub fn new(size: impl Into<Size>, mut tileset: Tileset) -> Board {
- let size = size.into();
- let mut contents = Vec::new();
- for y in 0..size.height {
- for x in 0..size.width {
- let param = DrawParam::new()
- .src(Board::sprite_location(0u8).into())
- .dest(tileset.to_screen([x, y]));
- let idx = tileset.batch.add(param);
- contents.push((0u8, idx));
- }
- }
- Board { size, contents, tileset }
- }
- fn sprite_location(ch: u8) -> [f32;4] {
- let u = f32::from(ch % 16) * TILE_SIZE;
- let v = f32::from(ch / 16) * TILE_SIZE;
- [u, v, TILE_SIZE, TILE_SIZE]
- }
- pub fn draw(&self, ctx: &mut Context) -> Result<(), ggez::GameError> {
- self.tileset.batch.draw(ctx, DrawParam::new())
- }
- pub fn set(&mut self, at: impl Into<Coord>, ch: u8) {
- let at = at.into();
- let idx = at.x + at.y * self.size.width;
- let param = DrawParam::new()
- .src(Board::sprite_location(ch).into())
- .dest(self.tileset.to_screen(at));
- self.tileset.batch.set(self.contents[idx].1, param).unwrap();
- }
- pub fn get(&mut self, at: impl Into<Coord>) -> u8 {
- let at = at.into();
- let idx = at.x + at.y * self.size.width;
- self.contents[idx].0
- }
- pub fn print(&mut self, at: impl Into<Coord>, msg: &str) {
- let Coord { x, y } = at.into();
- for (idx, ch) in msg.chars().enumerate() {
- self.set([idx + x, y], ch as u8);
- }
- }
- pub fn clear(&mut self) {
- for (n, contents) in self.contents.iter_mut().enumerate() {
- let x = n % self.size.width;
- let y = n / self.size.width;
- let param = DrawParam::new()
- .src(Board::sprite_location(0).into())
- .dest(self.tileset.to_screen([x, y]));
- contents.0 = 0;
- self.tileset.batch.set(contents.1, param).unwrap();
- }
- }
- }
|