turtlegame/src/activities/overworld/mod.rs
luckyturtledev bb37f613ad
Some checks failed
Rust / rustfmt (push) Successful in 29s
Rust / clippy (push) Failing after 2m25s
Rust / build (push) Successful in 2m54s
enter house (#10)
Reviewed-on: #10
Co-authored-by: luckyturtledev <git@lukas1818.de>
Co-committed-by: luckyturtledev <git@lukas1818.de>
2024-07-07 11:21:08 +00:00

196 lines
5.6 KiB
Rust

use crate::{
activities::{
house::{self, HouseState},
Activity
},
game::ZLayer,
State
};
use comfy::{
draw_circle, draw_rect_outline, draw_sprite, error, info, is_key_down,
main_camera_mut, EngineContext, IVec2, KeyCode, Vec2, RED, WHITE
};
use std::time::Instant;
use worldgen::MovementCost;
pub mod worldgen;
pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) {
for (coords, tile) in state.overworld.iter_tiles() {
for (i, texture) in tile.textures().iter().rev().enumerate() {
let i = i as i32;
draw_sprite(
*texture,
coords.as_vec2(),
WHITE,
ZLayer::MapMax - i,
Vec2::ONE
);
draw_rect_outline(coords.as_vec2(), Vec2::ONE, 0.1, RED, 10);
}
}
draw_circle(state.ghost.overworld_pos, 0.5, RED, ZLayer::Ghost.into());
}
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 {
info!(
"Pending Movement: {:?}",
state.ghost.overworld_movement_pending
);
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());
} else {
info!("Rejecting movement - cannot stand in the requested tile.");
}
}
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());
} else {
info!("Rejecting movement - cannot stand in the requested tile.");
}
}
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());
} else {
info!("Rejecting movement - cannot stand in the requested tile.");
}
}
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());
} else {
info!("Rejecting movement - cannot stand in the requested tile.");
}
}
// 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) => {
info!("Rejecting movement - movement cost is 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;
//move into house if player stepp at door
{
let current_tile = state.overworld.get_or_generate_tile(tile_pos);
if current_tile.can_enter_house() {
info!("enter house at {tile_pos}");
state.activity = Activity::House(tile_pos);
state.house_mut(); // gen new house
}
}
}
pub fn update(state: &mut State, _ctx: &mut EngineContext<'_>) {
let mut camera = main_camera_mut();
camera.center = Vec2::ZERO;
camera.zoom = 30.0;
// move player
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(
rounded_ghost_pos + IVec2::new(half_viewport.x, half_viewport.y)
);
state.overworld.get_or_generate_tile(
rounded_ghost_pos + IVec2::new(half_viewport.x, -half_viewport.y)
);
state.overworld.get_or_generate_tile(
rounded_ghost_pos + IVec2::new(-half_viewport.x, half_viewport.y)
);
state.overworld.get_or_generate_tile(
rounded_ghost_pos + IVec2::new(-half_viewport.x, -half_viewport.y)
);
}
}