~comcloudway/little_town

d27cbceb9933be29aa46a442b08b79a54caaecbc — Jakob Meier 1 year, 8 months ago 93d0409
Updated render engine to use a 3D grid
2 files changed, 105 insertions(+), 47 deletions(-)

M src/screens/build.rs
M src/types.rs
M src/screens/build.rs => src/screens/build.rs +91 -42
@@ 4,7 4,7 @@ use crate::textures::AssetStore;
use crate::types::{
    GameComponent,
    GameEvent,
    Pos2
    Pos3
};
use crate::blocks::Block;



@@ 21,72 21,121 @@ impl Camera {
    }
}

const TARGET_RENDER_SIZE:f32 = 128.0;

/// image width
const TEXTURE_WIDTH: f32 = 256.0;
/// actual width inside ob cube
const TEXTURE_INNER_WIDTH: f32 = 223.0; // 216
/// height of image
const TEXTURE_HEIGHT: f32 = 352.0;
/// actual height of cube
const TEXTURE_INNER_HEIGHT: f32 = 108.0; // 110

pub struct BuildScreen {
    grid: HashMap<Pos2, Block>,
    cam: Camera
    grid: HashMap<Pos3, Block>,
    cam: Camera,
    mouse_down: bool
}
impl BuildScreen {
    pub fn new() -> Self {
        let mut this = Self {
            grid: HashMap::new(),
            cam: Camera::new()
            cam: Camera::new(),
            mouse_down: false
        };

        this.grid.insert(Pos2::new(0, 0), Block::Dirt(crate::types::Direction::North));
        this.grid.insert(Pos2::new(0, 1), Block::Dirt(crate::types::Direction::North));
        this.grid.insert(Pos3::new(0, 0, 0), Block::Dirt(crate::types::Direction::North));

        this
    }
}

impl GameComponent for BuildScreen {
    fn draw(&self, assets: &AssetStore) {
        for (pos, block) in self.grid.iter() {
        // order: x (inc) -> y (inc) -> z (inc)
        let mut render_order: Vec<(&Pos3, &Block)> = self.grid.iter().collect();
        render_order.sort_by_key(|(pos, _)| pos.x + pos.y*2 + pos.z*3 );

        for (pos, block) in render_order.iter() {
            let texture = block.get_texture(&assets);

            let size = 128.0 * self.cam.scale;
            let w_i = TEXTURE_INNER_WIDTH * self.cam.scale;
            let width = TEXTURE_WIDTH * self.cam.scale;
            let height = TEXTURE_HEIGHT * self.cam.scale;
            let h_i = TEXTURE_INNER_HEIGHT * self.cam.scale;

            let dx = pos.y - pos.x;
            let dy = pos.y + pos.x;

            let x = screen_width() / 2.0
                + pos.x as f32 * size
                + self.cam.center.x * size;
                + dx as f32 * w_i / 2.0
                + self.cam.center.x
                - width / 2.0;
            let y = screen_height() / 2.0
                + pos.y as f32 * (size / 3.0)
                + self.cam.center.y * size;

            if x >= -size && x <= screen_width()
                && y >= -size && y <= screen_height() {
                // render block
                // TODO: render blocks in order:
                // - from front to back
                // - from bottom to top
            draw_texture_ex(
                texture,
                x,
                y,
                WHITE,
                DrawTextureParams {
                    dest_size: Some(Vec2::new(size, size)),
                    source: None,
                    rotation: 0.0,
                    flip_x: false,
                    flip_y: false,
                    pivot: None
                });
                + dy as f32 * h_i / 2.0
                - pos.z as f32 * h_i
                + self.cam.center.y
                - height / 2.0;

            }
       }
            if x >= -width && x <= screen_width()
                && y >= -width && y <= screen_height() {
                    // render block
                    draw_texture_ex(
                        texture,
                        x,
                        y,
                        WHITE,
                        DrawTextureParams {
                            dest_size: Some(Vec2::new(width, height)),
                            source: None,
                            rotation: 0.0,
                            flip_x: false,
                            flip_y: false,
                            pivot: None
                        });

                }
        }
    }
    fn ev_loop(&mut self) -> GameEvent {
        // mouse input
        if is_mouse_button_down(MouseButton::Left) {
            // currently holding button down
            self.mouse_down = true;
        } else if self.mouse_down {
            // button was released
            self.mouse_down = false;
            // TODO: determine which block / side was clicked
            let (mx, my) = mouse_position();

        if is_key_down(KeyCode::Up) {
            self.cam.center.y -= 0.1;
            let size = TARGET_RENDER_SIZE * self.cam.scale;
        }
if is_key_down(KeyCode::Down) {
            self.cam.center.y += 0.1;

        // zoom with Ctrl-MouseWheel
        if is_key_down(KeyCode::LeftControl) {
            let mut scale = self.cam.scale;
            let (_, wy) = mouse_wheel();

            scale += wy as f32 * 1.0/10.0;

            if scale > 0.05 && scale < 6.0 {
                self.cam.scale = scale;
            }
        }

        // keyboard control
        if is_key_down(KeyCode::Down) {
            self.cam.center.y += 1.0 * (1.0/self.cam.scale);
        }
        if is_key_down(KeyCode::Up) {
            self.cam.center.y -= 1.0 * (1.0/self.cam.scale);
        }
if is_key_down(KeyCode::Left) {
            self.cam.center.x -= 0.1;
        if is_key_down(KeyCode::Left) {
            self.cam.center.x -= 1.0 * (1.0/self.cam.scale);
        }
if is_key_down(KeyCode::Right) {
            self.cam.center.x += 0.1;
        if is_key_down(KeyCode::Right) {
            self.cam.center.x += 1.0 * (1.0/self.cam.scale);
        }

        GameEvent::None

M src/types.rs => src/types.rs +14 -5
@@ 1,16 1,25 @@
use crate::textures::AssetStore;
use crate::Screen;

/// three dimensional coordinate
///    z
///    |
///    |__ y
///   /
///  /
/// x
#[derive(Debug,Eq,Hash,PartialEq)]
pub struct Pos2 {
pub struct Pos3 {
    pub x: isize,
    pub y: isize
    pub y: isize,
    pub z: isize
}
impl Pos2 {
    pub fn new(x: isize, y: isize) -> Self {
impl Pos3 {
    pub fn new(x: isize, y: isize, z: isize) -> Self {
        Self {
            x,
            y
            y,
            z
        }
    }
}