From a772c1c2c38533a9ce4fd7840b60bd04f22674c3 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Tue, 28 Feb 2023 20:03:19 +0100 Subject: [PATCH] Added ability to rotate blocks using Shift+Mouse --- README.md | 4 +- src/game/types.rs | 33 ++++++++++ src/game/world.rs | 6 +- src/screens/build.rs | 144 +++++++++++++++++++++++++------------------ 4 files changed, 122 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index eac7b4c..2d20334 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,8 @@ launch the game and the world should appear in the world list | South | `J` | | West | `H` | | East | `L` | +| rotate CCW | `` and left mouse button | +| rotate CW | `` 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 | `` | | Close Screen | `Q` or `` | -### Level Cration Screen +### Level Creation Screen | Action | Key(s) / MouseButton | |--------|----------------------| | Close Screen | `` | diff --git a/src/game/types.rs b/src/game/types.rs index 6d50002..eec49af 100644 --- a/src/game/types.rs +++ b/src/game/types.rs @@ -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 { + 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() + } +} diff --git a/src/game/world.rs b/src/game/world.rs index 15f432d..3f17ac7 100644 --- a/src/game/world.rs +++ b/src/game/world.rs @@ -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() { diff --git a/src/screens/build.rs b/src/screens/build.rs index 5b11123..527321d 100644 --- a/src/screens/build.rs +++ b/src/screens/build.rs @@ -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 } } -- 2.38.5