From d90b0ad9926d8667b99f17afbdec549dfc452ff6 Mon Sep 17 00:00:00 2001 From: luckyturtledev Date: Sun, 7 Jul 2024 00:52:19 +0200 Subject: [PATCH 1/9] start move ment --- src/activities/overworld/mod.rs | 51 +++++++++++++++++++++++++--- src/activities/overworld/worldgen.rs | 2 +- src/game.rs | 8 +++-- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/activities/overworld/mod.rs b/src/activities/overworld/mod.rs index f8bee45..803a452 100644 --- a/src/activities/overworld/mod.rs +++ b/src/activities/overworld/mod.rs @@ -1,8 +1,13 @@ use comfy::{ - draw_rect_outline, draw_sprite, main_camera_mut, EngineContext, IVec2, Vec2, RED, - WHITE + draw_circle, draw_rect_outline, draw_sprite, main_camera_mut, EngineContext, IVec2, + Vec2, RED, WHITE, }; +use log::info; +use comfy::is_key_pressed; +use comfy::is_key_down; +use comfy::KeyCode; +use crate::game::Ghost; use crate::game::ZLayer; pub mod worldgen; @@ -16,16 +21,54 @@ pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) { coords.as_vec2(), WHITE, ZLayer::MapMax - i, - Vec2::ONE + Vec2::ONE, ); draw_rect_outline(coords.as_vec2(), Vec2::ONE, 0.1, RED, 10); } } + draw_circle( + state.ghost.overworld_pos.as_vec2(), + 0.5, + RED, + ZLayer::Ghost.into(), + ); } pub fn update(state: &mut crate::State, _engine: &mut EngineContext<'_>) { let mut camera = main_camera_mut(); camera.center = Vec2::ZERO; camera.zoom = 30.0; - state.overworld.get_or_generate_tile(IVec2::ZERO); + + let mut ghost_pos = &mut state.ghost.overworld_pos; + + // move player + if is_key_down(KeyCode::Up) { + ghost_pos.y +=1; + } + if is_key_down(KeyCode::Down) { + ghost_pos.y -=1; + } + if is_key_down(KeyCode::Left) { + ghost_pos.x -=1; + } + if is_key_down(KeyCode::Right) { + ghost_pos.x +=1; + } + + // generate more chunks if needed + { + let half_viewport = (camera.world_viewport() * 0.5 + 3.0).as_ivec2(); + state + .overworld + .get_or_generate_tile(*ghost_pos + IVec2::new(half_viewport.x, half_viewport.y)); + state + .overworld + .get_or_generate_tile(*ghost_pos + IVec2::new(half_viewport.x, -half_viewport.y)); + state + .overworld + .get_or_generate_tile(*ghost_pos + IVec2::new(-half_viewport.x, half_viewport.y)); + state + .overworld + .get_or_generate_tile(*ghost_pos + IVec2::new(-half_viewport.x, -half_viewport.y)); + } } diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index 5af1dcd..bf75f9a 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -138,7 +138,7 @@ impl Tile { /// The size of a chunk (both width and height). This value squared gives the amount of /// tiles in the chunk. -const CHUNK_SIZE: u32 = 100; +const CHUNK_SIZE: u32 = 50; /// Chunks #[derive(Debug)] diff --git a/src/game.rs b/src/game.rs index 2a2abf2..f21698c 100644 --- a/src/game.rs +++ b/src/game.rs @@ -2,7 +2,7 @@ use crate::{ activities::{house, overworld, Activity}, State }; -use comfy::EngineContext; +use comfy::{EngineContext, IVec2}; use std::ops::Sub; #[derive(Debug)] @@ -10,14 +10,16 @@ pub struct Ghost { /// current electric charge of the Ghost pub charge: f32, /// max electric charge of the Ghost - pub max_charge: f32 + pub max_charge: f32, + pub overworld_pos: IVec2, } impl Default for Ghost { fn default() -> Self { Self { charge: 1000.0, - max_charge: 1000.0 + max_charge: 1000.0, + overworld_pos: IVec2::ZERO, } } } -- 2.45.2 From 2a27eaec6a8c1b8fb62bf38b2cbaa9d2fd4ef7c6 Mon Sep 17 00:00:00 2001 From: Dominic Date: Sun, 7 Jul 2024 09:39:28 +0200 Subject: [PATCH 2/9] cargofmt --- src/activities/overworld/mod.rs | 46 +++++++++++++++------------------ src/game.rs | 4 +-- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/activities/overworld/mod.rs b/src/activities/overworld/mod.rs index 803a452..2d39c97 100644 --- a/src/activities/overworld/mod.rs +++ b/src/activities/overworld/mod.rs @@ -1,14 +1,10 @@ use comfy::{ - draw_circle, draw_rect_outline, draw_sprite, main_camera_mut, EngineContext, IVec2, - Vec2, RED, WHITE, + draw_circle, draw_rect_outline, draw_sprite, is_key_down, is_key_pressed, + main_camera_mut, EngineContext, IVec2, KeyCode, Vec2, RED, WHITE }; use log::info; -use comfy::is_key_pressed; -use comfy::is_key_down; -use comfy::KeyCode; -use crate::game::Ghost; -use crate::game::ZLayer; +use crate::game::{Ghost, ZLayer}; pub mod worldgen; @@ -21,7 +17,7 @@ pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) { coords.as_vec2(), WHITE, ZLayer::MapMax - i, - Vec2::ONE, + Vec2::ONE ); draw_rect_outline(coords.as_vec2(), Vec2::ONE, 0.1, RED, 10); } @@ -30,7 +26,7 @@ pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) { state.ghost.overworld_pos.as_vec2(), 0.5, RED, - ZLayer::Ghost.into(), + ZLayer::Ghost.into() ); } @@ -43,32 +39,32 @@ pub fn update(state: &mut crate::State, _engine: &mut EngineContext<'_>) { // move player if is_key_down(KeyCode::Up) { - ghost_pos.y +=1; + ghost_pos.y += 1; } if is_key_down(KeyCode::Down) { - ghost_pos.y -=1; + ghost_pos.y -= 1; } if is_key_down(KeyCode::Left) { - ghost_pos.x -=1; + ghost_pos.x -= 1; } if is_key_down(KeyCode::Right) { - ghost_pos.x +=1; + ghost_pos.x += 1; } // generate more chunks if needed { let half_viewport = (camera.world_viewport() * 0.5 + 3.0).as_ivec2(); - state - .overworld - .get_or_generate_tile(*ghost_pos + IVec2::new(half_viewport.x, half_viewport.y)); - state - .overworld - .get_or_generate_tile(*ghost_pos + IVec2::new(half_viewport.x, -half_viewport.y)); - state - .overworld - .get_or_generate_tile(*ghost_pos + IVec2::new(-half_viewport.x, half_viewport.y)); - state - .overworld - .get_or_generate_tile(*ghost_pos + IVec2::new(-half_viewport.x, -half_viewport.y)); + state.overworld.get_or_generate_tile( + *ghost_pos + IVec2::new(half_viewport.x, half_viewport.y) + ); + state.overworld.get_or_generate_tile( + *ghost_pos + IVec2::new(half_viewport.x, -half_viewport.y) + ); + state.overworld.get_or_generate_tile( + *ghost_pos + IVec2::new(-half_viewport.x, half_viewport.y) + ); + state.overworld.get_or_generate_tile( + *ghost_pos + IVec2::new(-half_viewport.x, -half_viewport.y) + ); } } diff --git a/src/game.rs b/src/game.rs index f21698c..aa9ac70 100644 --- a/src/game.rs +++ b/src/game.rs @@ -11,7 +11,7 @@ pub struct Ghost { pub charge: f32, /// max electric charge of the Ghost pub max_charge: f32, - pub overworld_pos: IVec2, + pub overworld_pos: IVec2 } impl Default for Ghost { @@ -19,7 +19,7 @@ impl Default for Ghost { Self { charge: 1000.0, max_charge: 1000.0, - overworld_pos: IVec2::ZERO, + overworld_pos: IVec2::ZERO } } } -- 2.45.2 From 1eeaf80a932e687254dd9336132c3f7b2f9c0eab Mon Sep 17 00:00:00 2001 From: Dominic Date: Sun, 7 Jul 2024 09:45:02 +0200 Subject: [PATCH 3/9] fix typos and incorrect documentation --- src/activities/overworld/worldgen.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index bf75f9a..3cfe2aa 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -430,21 +430,21 @@ impl Overworld { chunk.get_tile(local_chunk_coords).unwrap() } - /// Iterate over all generated tiles and its engine/world cordinates. using a [`Tile`] at the given world coordinates, or `None` if that tile has not - /// been generated yet. + /// Iterate over all generated tiles in all generated chunks and their engine/world + /// cordinates. pub fn iter_tiles(&self) -> impl Iterator { - self.iter_tilese_private().map(|(coords, tile)| { + self.iter_tiles_private().map(|(coords, tile)| { let mut w_coords = coords; w_coords.y *= -1; (w_coords, tile) }) } - /// iterate over all tiles and its global coords - fn iter_tilese_private(&self) -> impl Iterator { + /// Iterate over all generated tiles in all generated chunks. + fn iter_tiles_private(&self) -> impl Iterator { self.chunks.iter().flat_map(|(chunk_coords, chunk)| { chunk.iter_tiles().map(|(local_coords, tile)| { - // never fail because chunksize fits alswas into i32 + // never fail because chunksize fits always into i32 let local_coords: IVec2 = local_coords.try_into().unwrap(); (local_coords + (*chunk_coords * CHUNK_SIZE as i32), tile) }) -- 2.45.2 From 39631fb4ac2515da78e6f02972a61ad804d5612e Mon Sep 17 00:00:00 2001 From: Dominic Date: Sun, 7 Jul 2024 10:30:35 +0200 Subject: [PATCH 4/9] new movement code --- Cargo.lock | 1 - Cargo.toml | 1 - src/activities/overworld/mod.rs | 155 ++++++++++++++++++++++----- src/activities/overworld/worldgen.rs | 21 ++-- src/game.rs | 51 +++++++-- 5 files changed, 185 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e71edcb..b45ae10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2129,7 +2129,6 @@ version = "0.1.0" dependencies = [ "comfy", "heck", - "log", "resvg", ] diff --git a/Cargo.toml b/Cargo.toml index 3dfe2bc..38a2d18 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,6 @@ opt-level = 3 [dependencies] comfy = { version = "0.4.0", features = ["wayland"] } -log = "0.4.22" [build-dependencies] heck = "0.5" diff --git a/src/activities/overworld/mod.rs b/src/activities/overworld/mod.rs index 2d39c97..12dc2e7 100644 --- a/src/activities/overworld/mod.rs +++ b/src/activities/overworld/mod.rs @@ -1,10 +1,13 @@ +use crate::{ + game::{Ghost, ZLayer}, + State +}; use comfy::{ - draw_circle, draw_rect_outline, draw_sprite, is_key_down, is_key_pressed, + draw_circle, draw_rect_outline, draw_sprite, error, is_key_down, is_key_pressed, main_camera_mut, EngineContext, IVec2, KeyCode, Vec2, RED, WHITE }; -use log::info; - -use crate::game::{Ghost, ZLayer}; +use std::time::Instant; +use worldgen::MovementCost; pub mod worldgen; @@ -22,49 +25,143 @@ pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) { draw_rect_outline(coords.as_vec2(), Vec2::ONE, 0.1, RED, 10); } } - draw_circle( - state.ghost.overworld_pos.as_vec2(), - 0.5, - RED, - ZLayer::Ghost.into() - ); + draw_circle(state.ghost.overworld_pos, 0.5, RED, ZLayer::Ghost.into()); } -pub fn update(state: &mut crate::State, _engine: &mut EngineContext<'_>) { +fn update_move_player(state: &mut State) { + let now = Instant::now(); + + // Are there any pending position updates? If so, we ignore all user input and execute + // the pending updates. + if state.ghost.overworld_movement_pending != Vec2::ZERO { + state.ghost.update_overworld_pos(now); + return; + } + + // Otherwise, we check for user inputs, and update the pending movement accordingly. + let tile_pos = IVec2 { + x: state.ghost.overworld_pos.x.round() as _, + y: state.ghost.overworld_pos.y.round() as _ + }; + let Some(tile) = state.overworld.get_tile(tile_pos).copied() else { + error!("How can we be standing inside a non-generated tile?"); + return; + }; + + let mut requested_pos = None; + let mut requested_pos_diff = None; + let mut requested_cost_curr = None; + let mut requested_cost_new = None; + + if is_key_down(KeyCode::Up) { + let diff = IVec2 { x: 0, y: 1 }; + let new_pos = tile_pos + diff; + let new_tile = state.overworld.get_or_generate_tile(new_pos); + if new_tile.can_stand_inside() { + requested_pos = Some(new_pos); + requested_pos_diff = Some(diff); + requested_cost_curr = Some(tile.movement_cost_up()); + requested_cost_new = Some(new_tile.movement_cost_down()); + } + } + + if is_key_down(KeyCode::Down) { + let diff = IVec2 { x: 0, y: -1 }; + let new_pos = tile_pos + diff; + let new_tile = state.overworld.get_or_generate_tile(new_pos); + if new_tile.can_stand_inside() { + requested_pos = Some(new_pos); + requested_pos_diff = Some(diff); + requested_cost_curr = Some(tile.movement_cost_down()); + requested_cost_new = Some(new_tile.movement_cost_up()); + } + } + + if is_key_down(KeyCode::Left) { + let diff = IVec2 { x: -1, y: 0 }; + let new_pos = tile_pos + diff; + let new_tile = state.overworld.get_or_generate_tile(new_pos); + if new_tile.can_stand_inside() { + requested_pos = Some(new_pos); + requested_pos_diff = Some(diff); + requested_cost_curr = Some(tile.movement_cost_left()); + requested_cost_new = Some(new_tile.movement_cost_right()); + } + } + + if is_key_down(KeyCode::Right) { + let diff = IVec2 { x: 1, y: 0 }; + let new_pos = tile_pos + diff; + let new_tile = state.overworld.get_or_generate_tile(new_pos); + if new_tile.can_stand_inside() { + requested_pos = Some(new_pos); + requested_pos_diff = Some(diff); + requested_cost_curr = Some(tile.movement_cost_right()); + requested_cost_new = Some(new_tile.movement_cost_left()); + } + } + + // only continue if some movement was requested + let Some(_requested_pos) = requested_pos else { + return; + }; + let Some(requested_pos_diff) = requested_pos_diff else { + return; + }; + let Some(requested_cost_curr) = requested_cost_curr else { + return; + }; + let Some(requested_cost_new) = requested_cost_new else { + return; + }; + + state.ghost.overworld_movement_speed = match (requested_cost_curr, requested_cost_new) + { + // movement in this direction not possible + (MovementCost::Infinite, _) | (_, MovementCost::Infinite) => return, + + // we are walking on a path + (MovementCost::Path, MovementCost::Path) => 10.0, + + // we are walking across an obstacle + (MovementCost::Obstacle, _) | (_, MovementCost::Obstacle) => 1.0, + + // we are walking on grass + _ => 5.0 + }; + state.ghost.overworld_movement_pending = Vec2 { + x: requested_pos_diff.x as _, + y: requested_pos_diff.y as _ + }; + state.ghost.overworld_pos_last_update = now; +} + +pub fn update(state: &mut State, _ctx: &mut EngineContext<'_>) { let mut camera = main_camera_mut(); camera.center = Vec2::ZERO; camera.zoom = 30.0; - let mut ghost_pos = &mut state.ghost.overworld_pos; - // move player - if is_key_down(KeyCode::Up) { - ghost_pos.y += 1; - } - if is_key_down(KeyCode::Down) { - ghost_pos.y -= 1; - } - if is_key_down(KeyCode::Left) { - ghost_pos.x -= 1; - } - if is_key_down(KeyCode::Right) { - ghost_pos.x += 1; - } + update_move_player(state); // generate more chunks if needed { let half_viewport = (camera.world_viewport() * 0.5 + 3.0).as_ivec2(); + let rounded_ghost_pos = IVec2 { + x: state.ghost.overworld_pos.x.round() as _, + y: state.ghost.overworld_pos.y.round() as _ + }; state.overworld.get_or_generate_tile( - *ghost_pos + IVec2::new(half_viewport.x, half_viewport.y) + rounded_ghost_pos + IVec2::new(half_viewport.x, half_viewport.y) ); state.overworld.get_or_generate_tile( - *ghost_pos + IVec2::new(half_viewport.x, -half_viewport.y) + rounded_ghost_pos + IVec2::new(half_viewport.x, -half_viewport.y) ); state.overworld.get_or_generate_tile( - *ghost_pos + IVec2::new(-half_viewport.x, half_viewport.y) + rounded_ghost_pos + IVec2::new(-half_viewport.x, half_viewport.y) ); state.overworld.get_or_generate_tile( - *ghost_pos + IVec2::new(-half_viewport.x, -half_viewport.y) + rounded_ghost_pos + IVec2::new(-half_viewport.x, -half_viewport.y) ); } } diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index 3cfe2aa..809c7b6 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -2,8 +2,7 @@ #![allow(dead_code)] use crate::assets::ASSETS; -use comfy::{IVec2, TextureHandle, UVec2}; -use log::info; +use comfy::{info, IVec2, TextureHandle, UVec2}; use std::collections::HashMap; pub enum MovementCost { @@ -403,7 +402,15 @@ fn world_to_chunk_and_local_coords(world_coords: IVec2) -> (IVec2, UVec2) { } impl Overworld { - fn get_tile(&self, world_coords: IVec2) -> Option<&Tile> { + /// Return a [`Tile`] at the given world coordinates, or `None` if that tile has not + /// been generated yet. Uses engine/world cordinates. + pub fn get_tile(&self, world_coords: IVec2) -> Option<&Tile> { + let mut coords = world_coords; + coords.y *= -1; + self.get_tile_private(coords) + } + + fn get_tile_private(&self, world_coords: IVec2) -> Option<&Tile> { let (chunk_coords, local_chunk_coords) = world_to_chunk_and_local_coords(world_coords); @@ -411,15 +418,15 @@ impl Overworld { chunk.get_tile(local_chunk_coords) } - /// Return a [`Tile`] at the given world coordinates, or `None` if that tile has not - /// been generated yet. use engine/world cordinates. + /// Return a [`Tile`] at the given world coordinates. Generates tiles if necessary. + /// Uses engine/world cordinates. pub fn get_or_generate_tile(&mut self, world_coords: IVec2) -> &Tile { let mut coords = world_coords; coords.y *= -1; - self.get_or_generate_tiles_private(coords) + self.get_or_generate_tile_private(coords) } - fn get_or_generate_tiles_private(&mut self, world_coords: IVec2) -> &Tile { + fn get_or_generate_tile_private(&mut self, world_coords: IVec2) -> &Tile { let (chunk_coords, local_chunk_coords) = world_to_chunk_and_local_coords(world_coords); diff --git a/src/game.rs b/src/game.rs index aa9ac70..4215d64 100644 --- a/src/game.rs +++ b/src/game.rs @@ -2,16 +2,51 @@ use crate::{ activities::{house, overworld, Activity}, State }; -use comfy::{EngineContext, IVec2}; -use std::ops::Sub; +use comfy::{EngineContext, Vec2}; +use std::{ops::Sub, time::Instant}; #[derive(Debug)] pub struct Ghost { - /// current electric charge of the Ghost + /// Current electric charge of the Ghost. pub charge: f32, - /// max electric charge of the Ghost + /// Max electric charge of the Ghost. pub max_charge: f32, - pub overworld_pos: IVec2 + + /// The position of the ghost in the overworld. Expressed in tile coordinates, but + /// as a float as a ghost takes more than one tick to move. + pub overworld_pos: Vec2, + /// Pending movement of the ghost in the overworld. + pub overworld_movement_pending: Vec2, + /// The current movement speed of the ghost in tiles/sec. + pub overworld_movement_speed: f32, + /// The timestamp of the last overworld position update. + pub overworld_pos_last_update: Instant +} + +impl Ghost { + pub fn update_overworld_pos(&mut self, now: Instant) { + // This calculation is extremely simplistic. It will not work properly if both + // x and y of movement_pending are non-zero. But we only move left,right,up,down + // so that should never happen! + let secs = now + .duration_since(self.overworld_pos_last_update) + .as_secs_f32(); + let mut movement = + self.overworld_movement_pending * self.overworld_movement_speed * secs; + + // limit the movement to the remaining movement + if self.overworld_movement_pending.x.abs() < movement.x.abs() { + movement.x = self.overworld_movement_pending.x; + } + if self.overworld_movement_pending.y.abs() < movement.y.abs() { + movement.y = self.overworld_movement_pending.y; + } + + // execute the movement + self.overworld_pos += movement; + self.overworld_movement_pending -= movement; + self.overworld_pos_last_update = now; + } } impl Default for Ghost { @@ -19,7 +54,11 @@ impl Default for Ghost { Self { charge: 1000.0, max_charge: 1000.0, - overworld_pos: IVec2::ZERO + + overworld_pos: Vec2::ZERO, + overworld_movement_pending: Vec2::ZERO, + overworld_movement_speed: 0.0, + overworld_pos_last_update: Instant::now() } } } -- 2.45.2 From 642aed602372b2ffb956c7667a4c652a23a18771 Mon Sep 17 00:00:00 2001 From: Dominic Date: Sun, 7 Jul 2024 08:30:57 +0000 Subject: [PATCH 5/9] Implement Movement Cost (#7) Reviewed-on: https://msrd0.dev/spielemarmelade/turtlegame/pulls/7 Co-authored-by: Dominic Co-committed-by: Dominic --- src/activities/overworld/worldgen.rs | 40 +++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index 809c7b6..49c1bdc 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -116,22 +116,50 @@ impl Tile { } pub fn can_stand_inside(&self) -> bool { - unimplemented!() + #[allow(clippy::match_like_matches_macro)] // I believe this is better readable + match self { + Self::House { door: false, .. } => false, + _ => true + } } pub fn movement_cost_left(&self) -> MovementCost { - unimplemented!() + match self { + Self::Grass => MovementCost::Default, + Self::Path { left: true, .. } => MovementCost::Path, + Self::Fence { left: false, .. } => MovementCost::Obstacle, + _ => MovementCost::Infinite + } } pub fn movement_cost_right(&self) -> MovementCost { - unimplemented!() + match self { + Self::Grass => MovementCost::Default, + Self::Path { right: true, .. } => MovementCost::Path, + Self::Fence { right: false, .. } => MovementCost::Obstacle, + _ => MovementCost::Infinite + } } pub fn movement_cost_up(&self) -> MovementCost { - unimplemented!() + match self { + Self::Grass => MovementCost::Default, + Self::Path { top: true, .. } => MovementCost::Path, + Self::Fence { top: false, .. } => MovementCost::Obstacle, + _ => MovementCost::Infinite + } } pub fn movement_cost_down(&self) -> MovementCost { - unimplemented!() + match self { + Self::Grass => MovementCost::Default, + Self::Path { bottom: true, .. } => MovementCost::Path, + Self::Fence { bottom: false, .. } => MovementCost::Obstacle, + _ => MovementCost::Infinite + } } pub fn can_enter_house(&self) -> bool { - unimplemented!() + #[allow(clippy::match_like_matches_macro)] // I believe this is better readable + match self { + Self::House { door: true, .. } => true, + _ => false + } } } -- 2.45.2 From d273e87b55667dd6e2a9242b7bab398d43409432 Mon Sep 17 00:00:00 2001 From: Dominic Date: Sun, 7 Jul 2024 10:35:07 +0200 Subject: [PATCH 6/9] don't move with infinetly much missing --- src/activities/overworld/mod.rs | 8 ++++++-- src/game.rs | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/activities/overworld/mod.rs b/src/activities/overworld/mod.rs index 12dc2e7..68c0764 100644 --- a/src/activities/overworld/mod.rs +++ b/src/activities/overworld/mod.rs @@ -3,8 +3,8 @@ use crate::{ State }; use comfy::{ - draw_circle, draw_rect_outline, draw_sprite, error, is_key_down, is_key_pressed, - main_camera_mut, EngineContext, IVec2, KeyCode, Vec2, RED, WHITE + draw_circle, draw_rect_outline, draw_sprite, error, info, is_key_down, + is_key_pressed, main_camera_mut, EngineContext, IVec2, KeyCode, Vec2, RED, WHITE }; use std::time::Instant; use worldgen::MovementCost; @@ -34,6 +34,10 @@ fn update_move_player(state: &mut State) { // Are there any pending position updates? If so, we ignore all user input and execute // the pending updates. if state.ghost.overworld_movement_pending != Vec2::ZERO { + info!( + "Pending Movement: {:?}", + state.ghost.overworld_movement_pending + ); state.ghost.update_overworld_pos(now); return; } diff --git a/src/game.rs b/src/game.rs index 4215d64..7613efd 100644 --- a/src/game.rs +++ b/src/game.rs @@ -35,10 +35,10 @@ impl Ghost { self.overworld_movement_pending * self.overworld_movement_speed * secs; // limit the movement to the remaining movement - if self.overworld_movement_pending.x.abs() < movement.x.abs() { + if self.overworld_movement_pending.x.abs() < movement.x.abs() + 1e-2 { movement.x = self.overworld_movement_pending.x; } - if self.overworld_movement_pending.y.abs() < movement.y.abs() { + if self.overworld_movement_pending.y.abs() < movement.y.abs() + 1e-2 { movement.y = self.overworld_movement_pending.y; } -- 2.45.2 From 89bc156f524d2ea904c3589eac180dde2f6bdb2e Mon Sep 17 00:00:00 2001 From: Dominic Date: Sun, 7 Jul 2024 10:38:09 +0200 Subject: [PATCH 7/9] way better attempt at movement --- src/game.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/game.rs b/src/game.rs index 7613efd..936373e 100644 --- a/src/game.rs +++ b/src/game.rs @@ -31,14 +31,15 @@ impl Ghost { let secs = now .duration_since(self.overworld_pos_last_update) .as_secs_f32(); - let mut movement = - self.overworld_movement_pending * self.overworld_movement_speed * secs; + let mut movement = self.overworld_movement_pending.signum() + * self.overworld_movement_speed + * secs; // limit the movement to the remaining movement - if self.overworld_movement_pending.x.abs() < movement.x.abs() + 1e-2 { + if self.overworld_movement_pending.x.abs() < movement.x.abs() { movement.x = self.overworld_movement_pending.x; } - if self.overworld_movement_pending.y.abs() < movement.y.abs() + 1e-2 { + if self.overworld_movement_pending.y.abs() < movement.y.abs() { movement.y = self.overworld_movement_pending.y; } -- 2.45.2 From 06ee1a411ab4eab27184077a4364485eea97d7fd Mon Sep 17 00:00:00 2001 From: Dominic Date: Sun, 7 Jul 2024 10:44:10 +0200 Subject: [PATCH 8/9] overworld movement works :) --- src/activities/overworld/mod.rs | 13 ++++++++++++- src/activities/overworld/worldgen.rs | 10 +++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/activities/overworld/mod.rs b/src/activities/overworld/mod.rs index 68c0764..dc1bdf4 100644 --- a/src/activities/overworld/mod.rs +++ b/src/activities/overworld/mod.rs @@ -66,6 +66,8 @@ fn update_move_player(state: &mut State) { requested_pos_diff = Some(diff); requested_cost_curr = Some(tile.movement_cost_up()); requested_cost_new = Some(new_tile.movement_cost_down()); + } else { + info!("Rejecting movement - cannot stand in the requested tile."); } } @@ -78,6 +80,8 @@ fn update_move_player(state: &mut State) { requested_pos_diff = Some(diff); requested_cost_curr = Some(tile.movement_cost_down()); requested_cost_new = Some(new_tile.movement_cost_up()); + } else { + info!("Rejecting movement - cannot stand in the requested tile."); } } @@ -90,6 +94,8 @@ fn update_move_player(state: &mut State) { requested_pos_diff = Some(diff); requested_cost_curr = Some(tile.movement_cost_left()); requested_cost_new = Some(new_tile.movement_cost_right()); + } else { + info!("Rejecting movement - cannot stand in the requested tile."); } } @@ -102,6 +108,8 @@ fn update_move_player(state: &mut State) { requested_pos_diff = Some(diff); requested_cost_curr = Some(tile.movement_cost_right()); requested_cost_new = Some(new_tile.movement_cost_left()); + } else { + info!("Rejecting movement - cannot stand in the requested tile."); } } @@ -122,7 +130,10 @@ fn update_move_player(state: &mut State) { state.ghost.overworld_movement_speed = match (requested_cost_curr, requested_cost_new) { // movement in this direction not possible - (MovementCost::Infinite, _) | (_, MovementCost::Infinite) => return, + (MovementCost::Infinite, _) | (_, MovementCost::Infinite) => { + info!("Rejecting movement - movement cost is infinite"); + return; + }, // we are walking on a path (MovementCost::Path, MovementCost::Path) => 10.0, diff --git a/src/activities/overworld/worldgen.rs b/src/activities/overworld/worldgen.rs index 49c1bdc..83e9067 100644 --- a/src/activities/overworld/worldgen.rs +++ b/src/activities/overworld/worldgen.rs @@ -126,6 +126,7 @@ impl Tile { match self { Self::Grass => MovementCost::Default, Self::Path { left: true, .. } => MovementCost::Path, + Self::Path { left: false, .. } => MovementCost::Default, Self::Fence { left: false, .. } => MovementCost::Obstacle, _ => MovementCost::Infinite } @@ -134,6 +135,7 @@ impl Tile { match self { Self::Grass => MovementCost::Default, Self::Path { right: true, .. } => MovementCost::Path, + Self::Path { right: false, .. } => MovementCost::Default, Self::Fence { right: false, .. } => MovementCost::Obstacle, _ => MovementCost::Infinite } @@ -142,6 +144,7 @@ impl Tile { match self { Self::Grass => MovementCost::Default, Self::Path { top: true, .. } => MovementCost::Path, + Self::Path { top: false, .. } => MovementCost::Default, Self::Fence { top: false, .. } => MovementCost::Obstacle, _ => MovementCost::Infinite } @@ -150,7 +153,9 @@ impl Tile { match self { Self::Grass => MovementCost::Default, Self::Path { bottom: true, .. } => MovementCost::Path, + Self::Path { bottom: false, .. } => MovementCost::Default, Self::Fence { bottom: false, .. } => MovementCost::Obstacle, + Self::House { door: true, .. } => MovementCost::Path, _ => MovementCost::Infinite } } @@ -313,7 +318,10 @@ impl Chunk { fence_vert, grass, house(ASSETS.overworld.house_bottom_left), - house(ASSETS.overworld.house_bottom_door), + Tile::House { + door: true, + texture: ASSETS.overworld.house_bottom_door + }, house(ASSETS.overworld.house_bottom_window), house(ASSETS.overworld.house_bottom_window), house(ASSETS.overworld.house_bottom_right), -- 2.45.2 From 15887cb97e50dbbe064164a61e2d4b8435304467 Mon Sep 17 00:00:00 2001 From: Dominic Date: Sun, 7 Jul 2024 10:47:48 +0200 Subject: [PATCH 9/9] remove unused imports --- src/activities/overworld/mod.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/activities/overworld/mod.rs b/src/activities/overworld/mod.rs index dc1bdf4..f22d84b 100644 --- a/src/activities/overworld/mod.rs +++ b/src/activities/overworld/mod.rs @@ -1,10 +1,7 @@ -use crate::{ - game::{Ghost, ZLayer}, - State -}; +use crate::{game::ZLayer, State}; use comfy::{ draw_circle, draw_rect_outline, draw_sprite, error, info, is_key_down, - is_key_pressed, main_camera_mut, EngineContext, IVec2, KeyCode, Vec2, RED, WHITE + main_camera_mut, EngineContext, IVec2, KeyCode, Vec2, RED, WHITE }; use std::time::Instant; use worldgen::MovementCost; -- 2.45.2