freenukum 0.3.5

A clone of the 1991 DOS game Duke Nukem 1
Documentation
use crate::Result;
use crate::TileProvider;
use anyhow::anyhow;
use sdl2::{
    pixels::Color,
    rect::{Point, Rect},
    render::{Canvas, RenderTarget, TextureCreator},
    surface::Surface,
};

pub type TileIndex = usize;

pub trait Renderer {
    fn place_surface(
        &mut self,
        surface: &Surface,
        rect: Rect,
    ) -> Result<()>;

    fn place_tile(
        &mut self,
        tile: TileIndex,
        destination: Point,
    ) -> Result<()>;
    fn fill_rect(&mut self, rect: Rect, color: Color) -> Result<()>;
    fn fill(&mut self, color: Color) -> Result<()>;
    fn draw_rect(&mut self, rect: Rect, color: Color) -> Result<()>;
}

pub struct MovePositionRenderer<'a> {
    pub offset_x: i32,
    pub offset_y: i32,
    pub upstream: &'a mut dyn Renderer,
}

impl<'a> Renderer for MovePositionRenderer<'a> {
    fn place_surface(
        &mut self,
        surface: &Surface,
        mut rect: Rect,
    ) -> Result<()> {
        rect.offset(self.offset_x, self.offset_y);
        self.upstream.place_surface(surface, rect)
    }

    fn place_tile(
        &mut self,
        tile: TileIndex,
        destination: Point,
    ) -> Result<()> {
        self.upstream.place_tile(
            tile,
            destination.offset(self.offset_x, self.offset_y),
        )
    }

    fn fill_rect(&mut self, mut rect: Rect, color: Color) -> Result<()> {
        rect.offset(self.offset_x, self.offset_y);
        self.upstream.fill_rect(rect, color)
    }

    fn fill(&mut self, color: Color) -> Result<()> {
        self.upstream.fill(color)
    }

    fn draw_rect(&mut self, mut rect: Rect, color: Color) -> Result<()> {
        rect.offset(self.offset_x, self.offset_y);
        self.upstream.draw_rect(rect, color)
    }
}

pub struct CanvasRenderer<'a, RT: RenderTarget, T> {
    pub canvas: &'a mut Canvas<RT>,
    pub texture_creator: &'a TextureCreator<T>,
    pub tileprovider: &'a dyn TileProvider,
}

impl<'a, RT: RenderTarget, T> Renderer for CanvasRenderer<'a, RT, T> {
    fn place_surface(
        &mut self,
        surface: &Surface,
        rect: Rect,
    ) -> Result<()> {
        self.canvas
            .copy(&surface.as_texture(&self.texture_creator)?, None, rect)
            .map_err(|s| anyhow!(s))?;
        Ok(())
    }

    fn place_tile(
        &mut self,
        tile: TileIndex,
        destination: Point,
    ) -> Result<()> {
        let tile = self.tileprovider.get_tile(tile).unwrap();
        let rect = Rect::new(
            destination.x,
            destination.y,
            tile.width(),
            tile.height(),
        );
        self.canvas
            .copy(&tile.as_texture(&self.texture_creator)?, None, rect)
            .map_err(|s| anyhow!(s))?;
        Ok(())
    }

    fn fill_rect(&mut self, rect: Rect, color: Color) -> Result<()> {
        self.canvas.set_draw_color(color);
        self.canvas.fill_rect(rect).map_err(|s| anyhow!(s))?;
        Ok(())
    }

    fn fill(&mut self, color: Color) -> Result<()> {
        self.canvas.set_draw_color(color);
        self.canvas.clear();
        Ok(())
    }

    fn draw_rect(&mut self, rect: Rect, color: Color) -> Result<()> {
        self.canvas.set_draw_color(color);
        self.canvas.draw_rect(rect).map_err(|s| anyhow!(s))?;
        Ok(())
    }
}