~comcloudway/little_town

a772c1c2c38533a9ce4fd7840b60bd04f22674c3 — Jakob Meier 1 year, 6 months ago 3d081de v0.2.1
Added ability to rotate blocks using Shift+Mouse
4 files changed, 122 insertions(+), 65 deletions(-)

M README.md
M src/game/types.rs
M src/game/world.rs
M src/screens/build.rs
M README.md => README.md +3 -1
@@ 54,6 54,8 @@ launch the game and the world should appear in the world list
| South | `J` |
| West | `H` |
| East | `L` |
| rotate CCW | `<Shift>` and left mouse button |
| rotate CW | `<Shift>` and right mouse button |

#### Camera movement
| Action | Key(s) / MouseButton |


@@ 78,7 80,7 @@ launch the game and the world should appear in the world list
| Page up | `<ArrowUp>` |
| Close Screen | `Q` or `<Escape>` |

### Level Cration Screen
### Level Creation Screen
| Action | Key(s) / MouseButton |
|--------|----------------------|
| Close Screen | `<Escape>` |

M src/game/types.rs => src/game/types.rs +33 -0
@@ 39,3 39,36 @@ pub enum Direction {
    /// (bottom edge of screen)
    South
}
impl Direction {
    /// tries to extract the direction from an angle
    fn from_angle(deg: usize) -> Option<Self> {
        if deg % 360 == 0 {
            return Some(Self::North);
        } else if deg % 270 == 0 {
            return Some(Self::West);
        } else if deg%180 == 0 {
            return Some(Self::South);
        } else if deg%90 == 0 {
            return Some(Self::East);
        }

        None
    }
    /// converts the direction to an angle
    fn to_angle(&self) -> usize {
        match self {
            Self::North => 360,
            Self::West => 270,
            Self::South => 180,
            Self::East => 90
        }
    }
    /// rotate counter clock wise
    pub fn rotate_ccw(&self) -> Self {
        Self::from_angle(self.to_angle() + 90).unwrap()
    }
    /// rotate clock wise
    pub fn rotate_cw(&self) -> Self {
        Self::from_angle(self.to_angle() - 90).unwrap()
    }
}

M src/game/world.rs => src/game/world.rs +2 -4
@@ 155,17 155,15 @@ impl World {
        if let Some(dir) = get_data_dir() {
            let json = World::serialize_json(self);

            let path = Path::new(&dir).join(name);

            DirBuilder::new()
                .recursive(true)
                .create(&path);
                .create(Path::new(&dir)).unwrap();

            let mut file =  OpenOptions::new()
                .write(true)
                .create(true)
                .truncate(true)
                .open(path);
                .open(Path::new(&dir).join(name));

            if let Ok(file) = &mut file {
                if file.write_all(json.as_bytes()).is_err() {

M src/screens/build.rs => src/screens/build.rs +84 -60
@@ 414,48 414,60 @@ impl GameComponent for BuildScreen {
                            // for a given pixel
                            let mut pos = Pos3::new(pos.x, pos.y, pos.z);

                            if is_mouse_button_pressed(MouseButton::Right) {
                                // 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 world.grid.len() > 1 {

                                    // destroy block
                                    if let Some((block, _)) = world.destroy_block(&pos) {
                                        // transmit block destruction
                                        // if multiplayer mode enabled
                                        if let Some(mp) = &mut self.multiplayer {
                                            mp.perform_action(GameAction::RemoveBlock(pos.clone(), block));
                            if is_key_down(KeyCode::LeftShift) {
                                if let Some(block) = world.grid.get_mut(&pos) {
                                    if is_mouse_button_pressed(MouseButton::Left) {
                                        // rotate block CCW
                                        block.1 = block.1.rotate_ccw();
                                    } else if is_mouse_button_pressed(MouseButton::Right) {
                                        // rotate block CW
                                        block.1 = block.1.rotate_cw();
                                    }
                                }
                            } else {
                                if is_mouse_button_pressed(MouseButton::Right) {
                                    // 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 world.grid.len() > 1 {

                                        // destroy block
                                        if let Some((block, _)) = world.destroy_block(&pos) {
                                            // transmit block destruction
                                            // if multiplayer mode enabled
                                            if let Some(mp) = &mut self.multiplayer {
                                                mp.perform_action(GameAction::RemoveBlock(pos.clone(), block));
                                            }
                                        }
                                    }
                                }
                            }

                            if is_mouse_button_pressed(MouseButton::Left) {
                                // place block
                                let (x,y) = get_screen_coords(&pos, world.cam.scale, world.cam.center);
                                let face = Face::from_xy(mx-x, my-y, world.cam.scale);

                                match face.unwrap() {
                                    Face::Top => {
                                        pos.z+=1;
                                    },
                                    Face::Left => {
                                        pos.x+=1;
                                    },
                                    Face::Right => {
                                        pos.y+=1;
                                if is_mouse_button_pressed(MouseButton::Left) {
                                    // place block
                                    let (x,y) = get_screen_coords(&pos, world.cam.scale, world.cam.center);
                                    let face = Face::from_xy(mx-x, my-y, world.cam.scale);

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

                                if let Some(block) = &world.inventory.selected.clone() {
                                    if world.place_block(&pos, block.clone(), world.inventory.direction.clone()) {
                                    if let Some(block) = &world.inventory.selected.clone() {
                                        if world.place_block(&pos, block.clone(), world.inventory.direction.clone()) {

                                        // transmit block placement
                                        // if multiplayer mode enabled
                                        if let Some(mp) = &mut self.multiplayer {
                                            mp.perform_action(GameAction::PlaceBlock(pos, block.clone(), world.inventory.direction.clone()));
                                            // transmit block placement
                                            // if multiplayer mode enabled
                                            if let Some(mp) = &mut self.multiplayer {
                                                mp.perform_action(GameAction::PlaceBlock(pos, block.clone(), world.inventory.direction.clone()));
                                            }
                                        }
                                    }
                                }


@@ 548,35 560,47 @@ impl GameComponent for BuildScreen {
                    }

            }
        } else {
            // game has no world
            if is_key_pressed(KeyCode::Q) || is_key_pressed(KeyCode::Escape) || is_key_pressed(KeyCode::I) {
                return GameEvent::Quit;
            }
        }
        if let Some(mp) = &mut self.multiplayer {
            if let Some(task) = mp.get_next_task() {
                // match action
                // and perform neccesarry action
                match task {
                    GameAction::RequestWorld => {
                        if let Some(world) = &mut self.world {
                            mp.perform_action(
                                GameAction::TransmitWorld(world.clone()));
                        }
                    },
                    GameAction::PlaceBlock(pos, block, dir) => {
                        if let Some(world) = &mut self.world {
                            // remove block from inventory
                            world.place_block(&pos, block, dir);
                        }
                    },
                    GameAction::RemoveBlock(pos, _block) => {
                        if let Some(world) = &mut self.world {
                            world.destroy_block(&pos);
                        }
                    },
                    GameAction::TransmitWorld(world) => {
                        self.upgrade(world);
                    },

        #[cfg(feature="multiplayer")]
        {
            // maybe user is waiting in lobby
            // still check for p2p connections
            if let Some(mp) = &mut self.multiplayer {
                if let Some(task) = mp.get_next_task() {
                    // match action
                    // and perform neccesarry action
                    match task {
                        GameAction::RequestWorld => {
                            if let Some(world) = &mut self.world {
                                mp.perform_action(
                                    GameAction::TransmitWorld(world.clone()));
                            }
                        },
                        GameAction::PlaceBlock(pos, block, dir) => {
                            if let Some(world) = &mut self.world {
                                // remove block from inventory
                                world.place_block(&pos, block, dir);
                            }
                        },
                        GameAction::RemoveBlock(pos, _block) => {
                            if let Some(world) = &mut self.world {
                                world.destroy_block(&pos);
                            }
                        },
                        GameAction::TransmitWorld(world) => {
                            self.upgrade(world);
                        },
                    }
                }
            }
        }

        GameEvent::None
    }
}