~comcloudway/little_town

6be25370c4dfd735558e3989bc24143ae7eb5d6c — Jakob Meier 1 year, 8 months ago 0064f11
Added ability to destroy blocks using mouse RightClick
2 files changed, 112 insertions(+), 75 deletions(-)

M src/screens/build.rs
M src/screens/inventory.rs
M src/screens/build.rs => src/screens/build.rs +103 -75
@@ 43,7 43,8 @@ const TEXTURE_DEPTH: f32 = 100.0;
pub struct BuildScreen {
    grid: HashMap<Pos3, (Block, Direction)>,
    cam: Camera,
    mouse_down: bool,
    mouse_left_down: bool,
    mouse_right_down: bool,
    show_inv: bool,
    inv: Inventory
}


@@ 52,7 53,8 @@ impl BuildScreen {
        let mut this = Self {
            grid: HashMap::new(),
            cam: Camera::new(),
            mouse_down: false,
            mouse_left_down: false,
            mouse_right_down: false,
            show_inv: false,
            inv: Inventory::new()
        };


@@ 65,22 67,22 @@ impl BuildScreen {

fn get_screen_coords(pos: &Pos3, scale: f32, center: Vec2) -> (f32, f32) {
    let w_i = TEXTURE_INNER_WIDTH * scale;
            let width = TEXTURE_WIDTH * scale;
            let height = TEXTURE_HEIGHT * scale;
            let h_i = TEXTURE_INNER_HEIGHT * scale;

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

            let x = screen_width() / 2.0
                + dx as f32 * w_i / 2.0
                + center.x
                - width / 2.0;
            let y = screen_height() / 2.0
                + dy as f32 * h_i / 2.0
                - pos.z as f32 * h_i
                + center.y
                - height / 2.0;
    let width = TEXTURE_WIDTH * scale;
    let height = TEXTURE_HEIGHT * scale;
    let h_i = TEXTURE_INNER_HEIGHT * scale;

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

    let x = screen_width() / 2.0
        + dx as f32 * w_i / 2.0
        + center.x
        - width / 2.0;
    let y = screen_height() / 2.0
        + dy as f32 * h_i / 2.0
        - pos.z as f32 * h_i
        + center.y
        - height / 2.0;

    return (x,y);
}


@@ 207,68 209,94 @@ impl GameComponent for BuildScreen {

        // 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;
            // determine which block / side was clicked
            let (mx, my) = mouse_position();

            // virtual render cycle
            let render_order: Vec<(&Pos3, &(Block, Direction))> = self.grid.iter().collect();

            // list of positions in render que for given pixel
            // (mx, my)
            let mut in_path:Vec<&Pos3> = Vec::new();

            for (pos, _) in render_order.iter() {
                let (x,y) = get_screen_coords(pos, self.cam.scale, self.cam.center);

                if mx >= x
                    && mx <= x + TEXTURE_WIDTH * self.cam.scale
                    && my >= y + TEXTURE_Y_WHITESPACE * self.cam.scale
                    && my <= y + TEXTURE_HEIGHT * self.cam.scale {

                        // check if mouse is above transparent area
                        // and skip block if necessary
                        if Face::from_xy(mx-x, my-y, self.cam.scale).is_none() {
                            println!("skipping");
                            continue;
                        }
            self.mouse_left_down = true;
        }
        if is_mouse_button_down(MouseButton::Right) {
            self.mouse_right_down = true;
        }

                        // block in mouse path
                        in_path.push(pos);
                    }
            }
            // weight axis
            in_path.sort_by_key(|pos| pos.x + pos.y*2 + pos.z*3 );
            if let Some(pos) = in_path.last() {
                // position of clicked block
                // because it is the last block in de render queue
                // for a given pixel
                let mut pos = Pos3::new(pos.x, pos.y, pos.z);
                let (x,y) = get_screen_coords(&pos, self.cam.scale, self.cam.center);
                let face = Face::from_xy(mx-x, my-y, self.cam.scale);

                match face.unwrap() {
                    Face::Top => {
                        pos.z+=1;
                    },
                    Face::Left => {
                        pos.x+=1;
                    },
                    Face::Right => {
                        pos.y+=1;
                    }
                }
        if (self.mouse_left_down && !is_mouse_button_down(MouseButton::Left))
            || (self.mouse_right_down && !is_mouse_button_down(MouseButton::Right)) {

                // determine which block / side was clicked
                let (mx, my) = mouse_position();

                // virtual render cycle
                let render_order: Vec<(&Pos3, &(Block, Direction))> = self.grid.iter().collect();

                // list of positions in render que for given pixel
                // (mx, my)
                let mut in_path:Vec<&Pos3> = Vec::new();

                for (pos, _) in render_order.iter() {
                    let (x,y) = get_screen_coords(pos, self.cam.scale, self.cam.center);

                if let Some(block) = self.inv.place() {
                    self.grid.insert(pos, (block, self.inv.direction.clone()));
                    if mx >= x
                        && mx <= x + TEXTURE_WIDTH * self.cam.scale
                        && my >= y + TEXTURE_Y_WHITESPACE * self.cam.scale
                        && my <= y + TEXTURE_HEIGHT * self.cam.scale {

                            // check if mouse is above transparent area
                            // and skip block if necessary
                            if Face::from_xy(mx-x, my-y, self.cam.scale).is_none() {
                                continue;
                            }

                            // block in mouse path
                            in_path.push(pos);
                        }
                }
                // weight axis
                in_path.sort_by_key(|pos| pos.x + pos.y*2 + pos.z*3 );
                if let Some(pos) = in_path.last() {
                    // position of clicked block
                    // because it is the last block in de render queue
                    // for a given pixel
                    let mut pos = Pos3::new(pos.x, pos.y, pos.z);

                    if self.mouse_right_down && !is_mouse_button_down(MouseButton::Right) {
                        // released right click
                        self.mouse_right_down = false;

                        // if grid has only one block
                        // the block can not be removed
                        // because the palyer would not be able to place
                        // new blocks if no block exists
                        if self.grid.len() > 1 {

                            // destroy block
                            if let Some((block, _)) = self.grid.remove(&pos) {
                                self.inv.add(block);
                            }
                        }
                    }

                    if self.mouse_left_down && !is_mouse_button_down(MouseButton::Left) {
                        // released left click
                        self.mouse_left_down = false;

                        // place block
                        let (x,y) = get_screen_coords(&pos, self.cam.scale, self.cam.center);
                        let face = Face::from_xy(mx-x, my-y, self.cam.scale);

                        match face.unwrap() {
                            Face::Top => {
                                pos.z+=1;
                            },
                            Face::Left => {
                                pos.x+=1;
                            },
                            Face::Right => {
                                pos.y+=1;
                            }
                        }

                        if let Some(block) = self.inv.place() {
                            self.grid.insert(pos, (block, self.inv.direction.clone()));
                        }
                    }
                }
            }
        }

        // zoom with Ctrl-MouseWheel
        if is_key_down(KeyCode::LeftControl) {

M src/screens/inventory.rs => src/screens/inventory.rs +9 -0
@@ 55,6 55,15 @@ impl Inventory {
            is_mouse_down: false
        }
    }
    /// adds a block to the players inventory
    pub fn add(&mut self, block: Block) {
        if !self.infinite_items {
            *self.contents.get_mut(&block).unwrap_or(&mut 0)+=1;
        }
    }
    /// removes the selected block (one) from the inventory
    /// can be used to remove items
    /// or place items
    pub fn place(&mut self) -> Option<Block> {
        if let Some(block) = &self.selected {