diff --git a/src/activities/house.rs b/src/activities/house.rs index 849cafd..785d94e 100644 --- a/src/activities/house.rs +++ b/src/activities/house.rs @@ -3,7 +3,7 @@ use comfy::*; #[derive(Debug, Default)] pub struct HouseState { grid: Grid, - player: Player + player: Player, } #[derive(Debug)] @@ -12,9 +12,12 @@ struct Grid { connections: Vec<(usize, usize)>, } -#[derive(Debug, Default)] +#[derive(Debug)] struct Player { - position: Vec2 + position: Vec2, + speed: f32, + connection: usize, + next_connections: Vec, } impl Default for Grid { @@ -43,34 +46,50 @@ impl 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(); + 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; } } +impl Default for Player { + fn default() -> Self { + Self { + position: Default::default(), + speed: 10.0, + connection: 0, + next_connections: vec![1, 2, 3], + } + } +} + pub fn draw(state: &crate::State, _engine: &comfy::EngineContext) { //Draw Grid - for pos in &state.house.grid.nodes { - draw_circle(*pos, 0.25, BLUE, 0); + for node in &state.house.grid.nodes { + draw_circle(*node, 0.25, BLUE, 0); } for (conn_i1, conn_i2) in &state.house.grid.connections { - let p1 = state.house.grid.nodes.get(*conn_i1); - let p2 = state.house.grid.nodes.get(*conn_i2); + let node_1 = state.house.grid.nodes.get(*conn_i1); + let node_2 = state.house.grid.nodes.get(*conn_i2); - if p1.is_none() || p2.is_none() { + if node_1.is_none() || node_2.is_none() { error!("Connection in grid not available {:?}", (conn_i1, conn_i2)); continue; } - - draw_line(*p1.unwrap(), *p2.unwrap(), 0.1, BLUE, 0); + + draw_line(*node_1.unwrap(), *node_2.unwrap(), 0.1, BLUE, 0); } //Draw Player @@ -78,20 +97,225 @@ pub fn draw(state: &crate::State, _engine: &comfy::EngineContext) { } pub fn update(state: &mut crate::State, _engine: &mut comfy::EngineContext) { - if is_key_down(KeyCode::Up) { - error!("KEY UPPPPPPPPP"); - state.house.player.position += vec2(0.0, 1.0) * delta(); + let player = &mut state.house.player; + let grid = &state.house.grid; + + 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; + let ( + allow_up_movement, + allow_down_movement, + allow_left_movement, + allow_right_movement, + ) = 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_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_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, + ) + }; + + if allow_up_movement && is_key_down(KeyCode::Up) { + player.position += vec2(0.0, player.speed) * delta(); } - if is_key_down(KeyCode::Down) { - state.house.player.position += vec2(0.0, -1.0) * delta(); + if allow_down_movement && is_key_down(KeyCode::Down) { + player.position += vec2(0.0, -player.speed) * delta(); } - if is_key_down(KeyCode::Right) { - state.house.player.position += vec2(1.0, 0.0) * delta(); + if allow_right_movement && is_key_down(KeyCode::Right) { + player.position += vec2(player.speed, 0.0) * delta(); } - if is_key_down(KeyCode::Left) { - state.house.player.position += vec2(-1.0, 0.0) * delta(); + if allow_left_movement && is_key_down(KeyCode::Left) { + player.position += vec2(-player.speed, 0.0) * delta(); + } + + if !on_connection(&player.position, node_1, node_2) { + + let mut changed = false; + 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) { + changed = true; + + 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) { + if 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; + + break; + } + } + + if !changed { + //Get closest node to snap to + let mut nodes = HashSet::new(); + nodes.insert(conn_i1); + nodes.insert(conn_i2); + for conn in &player.next_connections { + let (next_conn_i1, next_conn_i2) = grid.connections.get(*conn).unwrap(); + + nodes.insert(next_conn_i1); + nodes.insert(next_conn_i2); + } + + let mut closest_sqared_range = f32::MAX; + let mut closest_node = node_1; + 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; + } } } + +//(UP, DOWN, LEFT, RIGHT) +fn get_allowed_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_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 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() +} \ No newline at end of file