From 5a4451d6a7a3ea453baf1eca1e7471ff32b77e85 Mon Sep 17 00:00:00 2001 From: Glaeder Date: Sat, 6 Jul 2024 17:59:56 +0000 Subject: [PATCH] cabel-movement (#3) Cable Movemnt is finished. grid is hard coded Reviewed-on: https://msrd0.dev/spielemarmelade/turtlegame/pulls/3 Co-authored-by: Glaeder Co-committed-by: Glaeder --- .gitignore | 2 + Cargo.lock | 9 +- Cargo.toml | 5 + src/activities/house.rs | 7 - src/activities/house/grid.rs | 69 +++++++++ src/activities/house/mod.rs | 23 +++ src/activities/house/player.rs | 268 +++++++++++++++++++++++++++++++++ src/activities/mod.rs | 4 +- src/main.rs | 15 +- 9 files changed, 377 insertions(+), 25 deletions(-) delete mode 100644 src/activities/house.rs create mode 100644 src/activities/house/grid.rs create mode 100644 src/activities/house/mod.rs create mode 100644 src/activities/house/player.rs diff --git a/.gitignore b/.gitignore index ea8c4bf..0b4fc31 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +*.nix +.vscode/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 431f36e..51a9a0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -478,8 +478,7 @@ dependencies = [ [[package]] name = "comfy" version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e8ff7c66a696e9a9e5523d0c4a6306711acb7f6d490d9c412b044a8c95f17f4" +source = "git+https://github.com/Plonq/comfy/?branch=101-fix-keyboard-events#6293590aec51875e9832ef05a670149d371f849c" dependencies = [ "comfy-core", "comfy-wgpu", @@ -499,8 +498,7 @@ dependencies = [ [[package]] name = "comfy-core" version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "398260ce649e9d35adc3ae75565406aab9b360c1e892a48ae3606e3138df150b" +source = "git+https://github.com/Plonq/comfy/?branch=101-fix-keyboard-events#6293590aec51875e9832ef05a670149d371f849c" dependencies = [ "ahash", "anyhow", @@ -558,8 +556,7 @@ dependencies = [ [[package]] name = "comfy-wgpu" version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6118f09fd99577503ba6861dac53840bae6cf202d70f97042f5cdf43c222e39a" +source = "git+https://github.com/Plonq/comfy/?branch=101-fix-keyboard-events#6293590aec51875e9832ef05a670149d371f849c" dependencies = [ "bytemuck", "comfy-core", diff --git a/Cargo.toml b/Cargo.toml index 9585c1b..9ec0f12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,8 @@ opt-level = 3 [dependencies] comfy = { version = "0.4.0", features = ["wayland"] } log = "0.4.22" + +[patch.crates-io] +# https://github.com/darthdeus/comfy/issues/101 +# https://github.com/darthdeus/comfy/pull/102 +comfy = { git = "https://github.com/Plonq/comfy/", branch = "101-fix-keyboard-events" } diff --git a/src/activities/house.rs b/src/activities/house.rs deleted file mode 100644 index 8043a2d..0000000 --- a/src/activities/house.rs +++ /dev/null @@ -1,7 +0,0 @@ -use comfy::*; - -pub fn draw(_state: &crate::State, _engine: &comfy::EngineContext) { - draw_circle(vec2(0.0, 0.0), 0.5, RED, 0); -} - -pub fn update(_state: &mut crate::State, _engine: &mut comfy::EngineContext) {} diff --git a/src/activities/house/grid.rs b/src/activities/house/grid.rs new file mode 100644 index 0000000..114eace --- /dev/null +++ b/src/activities/house/grid.rs @@ -0,0 +1,69 @@ +use comfy::*; + +#[derive(Debug)] +pub struct Grid { + pub nodes: Vec, + pub connections: Vec<(usize, usize)> +} + +impl Default for Grid { + fn default() -> Self { + Grid::load() //Just for testing purposes + } +} + +impl Grid { + fn load() -> Self { + let mut grid = Self { + nodes: vec![ + vec2(10.0, 0.0), + vec2(0.0, 0.0), + vec2(0.0, 10.0), + vec2(-10.0, 0.0), + vec2(10.0, 10.0), + ], + connections: vec![(0, 1), (1, 2), (1, 3), (0, 4), (0, 5), (5, 1), (6, 7)] + }; + + grid.sanitize(); + + grid + } + + fn sanitize(&mut self) { + let mut len = self.nodes.len(); + let connections = self + .connections + .iter() + .filter(|(conn_i1, conn_i2)| { + if conn_i1 >= &mut len || conn_i2 >= &mut len { + error!("Connection in grid not possible {:?}", (conn_i1, conn_i2)); + false + } else { + true + } + }) + .map(|(conn_i1, conn_i2)| (*conn_i1, *conn_i2)) + .collect(); + + self.connections = connections; + } + + pub fn draw(&self) { + //Draw Grid + for node in &self.nodes { + draw_circle(*node, 0.25, BLUE, 0); + } + for (conn_i1, conn_i2) in &self.connections { + let node_1 = self.nodes.get(*conn_i1); + let node_2 = self.nodes.get(*conn_i2); + + if node_1.is_none() || node_2.is_none() { + error!("Connection in grid not available {:?}", (conn_i1, conn_i2)); + continue; + } + + draw_line(*node_1.unwrap(), *node_2.unwrap(), 0.1, BLUE, 0); + } + } +} diff --git a/src/activities/house/mod.rs b/src/activities/house/mod.rs new file mode 100644 index 0000000..643e666 --- /dev/null +++ b/src/activities/house/mod.rs @@ -0,0 +1,23 @@ +mod grid; +mod player; + +use grid::Grid; +use player::Player; + +#[derive(Debug, Default)] +pub struct HouseState { + grid: Grid, + player: Player +} + +pub fn draw(state: &crate::State, _engine: &comfy::EngineContext) { + //Draw Grid + state.house.grid.draw(); + + //Draw Player + state.house.player.draw(); +} + +pub fn update(state: &mut crate::State, _engine: &mut comfy::EngineContext) { + state.house.player.update(&state.house.grid); +} diff --git a/src/activities/house/player.rs b/src/activities/house/player.rs new file mode 100644 index 0000000..eb60107 --- /dev/null +++ b/src/activities/house/player.rs @@ -0,0 +1,268 @@ +use comfy::*; + +use super::Grid; + +#[derive(Debug)] +pub struct Player { + position: Vec2, + speed: f32, + connection: usize, + next_connections: Vec +} + +impl Default for Player { + fn default() -> Self { + Self { + position: Default::default(), + speed: 10.0, + connection: 0, + next_connections: vec![1, 2, 3] + } + } +} +impl Player { + pub fn draw(&self) { + draw_circle(self.position, 0.5, RED, 0); + } + pub fn update(&mut self, grid: &Grid) { + let allowed_movement = get_allowed_movement(self, grid); + + move_player(self, allowed_movement); + + if !on_current_connection(self, grid) && !update_connections(self, grid) { + snap_to_closest_node(self, grid); + } + } +} + +fn move_player(player: &mut Player, allowed_movement: (bool, bool, bool, bool)) { + let ( + allow_up_movement, + allow_down_movement, + allow_left_movement, + allow_right_movement + ) = allowed_movement; + + if allow_up_movement && is_key_down(KeyCode::Up) { + player.position += vec2(0.0, player.speed) * delta(); + } + + if allow_down_movement && is_key_down(KeyCode::Down) { + player.position += vec2(0.0, -player.speed) * delta(); + } + + if allow_right_movement && is_key_down(KeyCode::Right) { + player.position += vec2(player.speed, 0.0) * delta(); + } + + if allow_left_movement && is_key_down(KeyCode::Left) { + player.position += vec2(-player.speed, 0.0) * delta(); + } +} + +//(UP, DOWN, LEFT, RIGHT) +fn get_allowed_movement(player: &Player, grid: &Grid) -> (bool, bool, bool, bool) { + let (conn_i1, conn_i2) = grid.connections.get(player.connection).unwrap(); + let node_1 = grid.nodes.get(*conn_i1).unwrap(); + let node_2 = grid.nodes.get(*conn_i2).unwrap(); + + let range = 0.25; + + if in_node_range(&player.position, node_1, range) + || in_node_range(&player.position, node_2, range) + { + (true, true, true, true) + } else { + let ( + mut allow_up_movement, + mut allow_down_movement, + mut allow_left_movement, + mut allow_right_movement + ) = get_allowed_connection_movement(&player.position, node_1, node_2); + + for conn in &player.next_connections { + let (next_conn_i1, next_conn_i2) = grid.connections.get(*conn).unwrap(); + let next_node_1 = grid.nodes.get(*next_conn_i1).unwrap(); + let next_node_2 = grid.nodes.get(*next_conn_i2).unwrap(); + + let ( + next_allow_up_movement, + next_allow_down_movement, + next_allow_left_movement, + next_allow_right_movement + ) = get_allowed_connection_movement(&player.position, next_node_1, next_node_2); + + ( + allow_up_movement, + allow_down_movement, + allow_left_movement, + allow_right_movement + ) = ( + allow_up_movement || next_allow_up_movement, + allow_down_movement || next_allow_down_movement, + allow_left_movement || next_allow_left_movement, + allow_right_movement || next_allow_right_movement + ); + } + ( + allow_up_movement, + allow_down_movement, + allow_left_movement, + allow_right_movement + ) + } +} + +//(UP, DOWN, LEFT, RIGHT) +fn get_allowed_connection_movement( + player_position: &Vec2, + node_1: &Vec2, + node_2: &Vec2 +) -> (bool, bool, bool, bool) { + let allow_left_movement = { + if node_1.x <= node_2.x { + node_1.x < player_position.x + && player_position.x <= node_2.x + && player_position.y == node_1.y + } else { + node_2.x < player_position.x + && player_position.x <= node_1.x + && player_position.y == node_1.y + } + }; + + let allow_right_movement = { + if node_1.x <= node_2.x { + node_1.x <= player_position.x + && player_position.x < node_2.x + && player_position.y == node_1.y + } else { + node_2.x <= player_position.x + && player_position.x < node_1.x + && player_position.y == node_1.y + } + }; + + let allow_up_movement = { + if node_1.y <= node_2.y { + node_1.y <= player_position.y + && player_position.y < node_2.y + && player_position.x == node_1.x + } else { + node_2.y <= player_position.y + && player_position.y < node_1.y + && player_position.x == node_1.x + } + }; + + let allow_down_movement = { + if node_1.y <= node_2.y { + node_1.y < player_position.y + && player_position.y <= node_2.y + && player_position.x == node_1.x + } else { + node_2.y < player_position.y + && player_position.y <= node_1.y + && player_position.x == node_1.x + } + }; + + ( + allow_up_movement, + allow_down_movement, + allow_left_movement, + allow_right_movement + ) +} + +fn on_current_connection(player: &Player, grid: &Grid) -> bool { + let (conn_i1, conn_i2) = grid.connections.get(player.connection).unwrap(); + let node_1 = grid.nodes.get(*conn_i1).unwrap(); + let node_2 = grid.nodes.get(*conn_i2).unwrap(); + + on_connection(&player.position, node_1, node_2) +} + +fn on_connection(player_position: &Vec2, node_1: &Vec2, node_2: &Vec2) -> bool { + let on_x = if node_1.x <= node_2.x { + node_1.x <= player_position.x && player_position.x <= node_2.x + } else { + node_2.x <= player_position.x && player_position.x <= node_1.x + }; + + let on_y = if node_1.y <= node_2.y { + node_1.y <= player_position.y && player_position.y <= node_2.y + } else { + node_2.y <= player_position.y && player_position.y <= node_1.y + }; + + on_x && on_y +} + +fn update_connections(player: &mut Player, grid: &Grid) -> bool { + for conn in &player.next_connections { + let (next_conn_i1, next_conn_i2) = grid.connections.get(*conn).unwrap(); + let next_node_1 = grid.nodes.get(*next_conn_i1).unwrap(); + let next_node_2 = grid.nodes.get(*next_conn_i2).unwrap(); + + if on_connection(&player.position, next_node_1, next_node_2) { + player.connection = *conn; + //Update next connections + let mut next_connections = Vec::new(); + for (i, (poss_conn_i1, poss_conn_i2)) in grid.connections.iter().enumerate() { + if (next_conn_i1, next_conn_i2) != (poss_conn_i1, poss_conn_i2) + && next_conn_i1 == poss_conn_i1 + || next_conn_i1 == poss_conn_i2 + || next_conn_i2 == poss_conn_i1 + || next_conn_i2 == poss_conn_i2 + { + next_connections.push(i); + } + } + player.next_connections = next_connections; + + return true; + } + } + false +} + +fn in_node_range(player_position: &Vec2, node: &Vec2, range: f32) -> bool { + node.x - range <= player_position.x + && player_position.x <= node.x + range + && node.y - range <= player_position.y + && player_position.y <= node.y + range +} + +fn get_squared_node_range(player_position: &Vec2, node: &Vec2) -> f32 { + (player_position.x - node.x).abs() + (player_position.y - node.y).abs() +} + +fn snap_to_closest_node(player: &mut Player, grid: &Grid) { + let (current_connection_index_1, current_connection_index_2) = + grid.connections.get(player.connection).unwrap(); + + let mut nodes = HashSet::new(); + nodes.insert(current_connection_index_1); + nodes.insert(current_connection_index_2); + for conn in &player.next_connections { + let (next_connection_index_1, next_connection_index_2) = + grid.connections.get(*conn).unwrap(); + + nodes.insert(next_connection_index_1); + nodes.insert(next_connection_index_2); + } + + let mut closest_sqared_range = f32::MAX; + let mut closest_node = &vec2(0.0, 0.0); + for node_index in nodes { + let current_node = grid.nodes.get(*node_index).unwrap(); + let current_squard_range = get_squared_node_range(&player.position, current_node); + if closest_sqared_range > current_squard_range { + closest_sqared_range = current_squard_range; + closest_node = current_node; + } + } + + player.position = *closest_node; +} diff --git a/src/activities/mod.rs b/src/activities/mod.rs index 5d0b11f..dfa2b9e 100644 --- a/src/activities/mod.rs +++ b/src/activities/mod.rs @@ -1,8 +1,10 @@ pub mod house; pub mod overworld; -#[derive(Debug)] +#[derive(Debug, Default)] pub enum Activity { + #[default] House, + #[allow(dead_code)] Overworld } diff --git a/src/main.rs b/src/main.rs index 4992bdf..863ddb3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,15 @@ mod activities; mod game; -use activities::Activity; +use activities::{house::HouseState, Activity}; use comfy::*; const GAME_NAME: &str = "Powercreep"; -#[derive(Debug)] +#[derive(Debug, Default)] struct State { - activity: Activity -} - -impl Default for State { - fn default() -> Self { - Self { - activity: Activity::House - } - } + activity: Activity, + house: HouseState } impl GameLoop for State {