use crate::{ activities::{house, overworld, Activity}, State }; use comfy::{EngineContext, Vec2}; use std::{ops::Sub, time::Instant}; #[derive(Debug)] pub struct Ghost { /// Current electric charge of the Ghost. pub charge: f32, /// Max electric charge of the Ghost. pub max_charge: f32, /// 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.signum() * 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 { fn default() -> Self { Self { charge: 1000.0, max_charge: 1000.0, overworld_pos: Vec2::ZERO, overworld_movement_pending: Vec2::ZERO, overworld_movement_speed: 0.0, overworld_pos_last_update: Instant::now() } } } #[repr(i32)] pub enum ZLayer { MapMax = -1, Human = 0, Ghost = 1 } impl From for i32 { fn from(value: ZLayer) -> Self { // safe because #[repr(i32)] value as i32 } } impl Sub for ZLayer { type Output = i32; fn sub(self, other: i32) -> Self::Output { i32::from(self) - other } } pub fn update(state: &mut State, engine: &mut EngineContext<'_>) { state.score += engine.delta * 10.0; match state.activity { Activity::House => house::update(state, engine), Activity::Overworld => overworld::update(state, engine) } } pub fn draw(state: &State, engine: &EngineContext<'_>) { match state.activity { Activity::House => house::draw(state, engine), Activity::Overworld => overworld::draw(state, engine) } crate::ui::draw(state, engine); }