refactor: Refactor to features (#53)

This commit is contained in:
demenik
2025-11-26 19:59:53 +01:00
parent 4c3aeb08ed
commit 3b7bfb17e1
35 changed files with 167 additions and 185 deletions

View File

@@ -1,5 +0,0 @@
pub mod phase;
pub mod pom;
pub mod savegame;
pub mod tile;
pub mod ui;

View File

@@ -1,5 +1,4 @@
use bevy::prelude::*;
use serde::Deserialize;
use crate::prelude::*;
use std::fs::File;
use std::io::BufReader;
@@ -20,8 +19,10 @@ impl Default for GameConfig {
}
}
pub fn read_config() -> Option<GameConfig> {
impl GameConfig {
pub fn read_config() -> Option<Self> {
let file = File::open("assets/config.json").ok()?;
let reader = BufReader::new(file);
serde_json::from_reader(reader).ok()
}
}

View File

@@ -0,0 +1 @@
pub mod components;

View File

@@ -1,5 +1,6 @@
use crate::states::*;
use bevy::prelude::*;
use crate::prelude::*;
pub mod states;
pub struct CorePlugin;

View File

@@ -0,0 +1,8 @@
use crate::prelude::*;
#[derive(States, Clone, PartialEq, Eq, Debug, Hash, Default)]
pub enum AppState {
#[default]
StartScreen,
GameScreen,
}

View File

@@ -1,5 +1,4 @@
use crate::states::*;
use bevy::prelude::*;
use crate::prelude::*;
pub struct GameScreenPlugin;

View File

@@ -1,7 +1,5 @@
use bevy::prelude::*;
use serde::{Deserialize, Serialize};
use crate::errors::GridError;
use super::errors::GridError;
use crate::prelude::*;
#[derive(Component)]
pub struct Tile {

View File

@@ -0,0 +1 @@
pub const TILE_SIZE: f32 = 32.0;

View File

@@ -1,19 +1,9 @@
use crate::{
components::tile::{Grid, Tile, TileState},
config::GameConfig,
states::AppState,
};
use bevy::prelude::*;
use bevy_aseprite_ultra::prelude::AseSlice;
use crate::prelude::*;
pub const TILE_SIZE: f32 = 32.0;
pub fn grid_start_x(grid_width: u32) -> f32 {
-(grid_width as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0
}
pub fn grid_start_y(grid_height: u32) -> f32 {
-(grid_height as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0
}
pub mod components;
pub mod consts;
pub mod errors;
pub mod utils;
pub struct GridPlugin;
@@ -94,37 +84,3 @@ fn update_tile_colors(
};
}
}
pub fn world_to_grid_coords(world_pos: Vec3, grid_width: u32, grid_height: u32) -> (u32, u32) {
let start_x = grid_start_x(grid_width);
let start_y = grid_start_y(grid_height);
let x = ((world_pos.x - start_x + TILE_SIZE / 2.0) / TILE_SIZE).floor();
let y = ((world_pos.y - start_y + TILE_SIZE / 2.0) / TILE_SIZE).floor();
let mut x_u32 = x as u32;
let mut y_u32 = y as u32;
if x_u32 >= grid_width {
x_u32 = grid_width - 1;
}
if y_u32 >= grid_height {
y_u32 = grid_height - 1;
}
(x_u32, y_u32)
}
pub fn grid_to_world_coords(
grid_x: u32,
grid_y: u32,
z: Option<f32>,
grid_width: u32,
grid_height: u32,
) -> Vec3 {
Vec3::new(
grid_start_x(grid_width) + grid_x as f32 * TILE_SIZE,
grid_start_y(grid_height) + grid_y as f32 * TILE_SIZE,
z.unwrap_or(0.0),
)
}

View File

@@ -0,0 +1,43 @@
use crate::prelude::*;
pub fn grid_start_x(grid_width: u32) -> f32 {
-(grid_width as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0
}
pub fn grid_start_y(grid_height: u32) -> f32 {
-(grid_height as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0
}
pub fn world_to_grid_coords(world_pos: Vec3, grid_width: u32, grid_height: u32) -> (u32, u32) {
let start_x = grid_start_x(grid_width);
let start_y = grid_start_y(grid_height);
let x = ((world_pos.x - start_x + TILE_SIZE / 2.0) / TILE_SIZE).floor();
let y = ((world_pos.y - start_y + TILE_SIZE / 2.0) / TILE_SIZE).floor();
let mut x_u32 = x as u32;
let mut y_u32 = y as u32;
if x_u32 >= grid_width {
x_u32 = grid_width - 1;
}
if y_u32 >= grid_height {
y_u32 = grid_height - 1;
}
(x_u32, y_u32)
}
pub fn grid_to_world_coords(
grid_x: u32,
grid_y: u32,
z: Option<f32>,
grid_width: u32,
grid_height: u32,
) -> Vec3 {
Vec3::new(
grid_start_x(grid_width) + grid_x as f32 * TILE_SIZE,
grid_start_y(grid_height) + grid_y as f32 * TILE_SIZE,
z.unwrap_or(0.0),
)
}

View File

@@ -1,17 +1,10 @@
use bevy::input::mouse::MouseButton;
use bevy::prelude::*;
use bevy::window::PrimaryWindow;
use crate::components::phase::{CurrentPhase, Phase};
use crate::components::tile::{Grid, TileState};
use crate::config::GameConfig;
use crate::messages::phase::{NextPhaseMessage, PhaseTimerPauseMessage};
use crate::messages::{
interact::InteractStartMessage,
r#move::{InvalidMoveMessage, MoveMessage},
use crate::features::{
phase::messages::{NextPhaseMessage, PhaseTimerPauseMessage},
pom::messages::InvalidMoveMessage,
};
use crate::plugins::grid::world_to_grid_coords;
use crate::states::AppState;
use crate::prelude::*;
use bevy::input::mouse::MouseButton;
use bevy::window::PrimaryWindow;
pub struct InputPlugin;

View File

@@ -1,3 +1,4 @@
pub mod config;
pub mod core;
pub mod game_screen;
pub mod grid;
@@ -7,6 +8,7 @@ pub mod pom;
pub mod savegame;
pub mod start_screen;
pub mod status;
pub mod ui;
pub use core::CorePlugin;
pub use game_screen::GameScreenPlugin;

View File

@@ -1,5 +1,5 @@
use bevy::prelude::*;
use serde::{Deserialize, Serialize};
use super::utils::format_time;
use crate::prelude::*;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Phase {
@@ -9,21 +9,6 @@ pub enum Phase {
Finished { completed_phase: Box<Phase> },
}
fn format_time(seconds: f32) -> String {
let seconds = seconds.max(0.0) as u32;
if seconds >= 3600 {
let hours = seconds / 3600;
let minutes = (seconds % 3600) / 60;
let secs = seconds % 60;
format!("{:02}:{:02}:{:02}", hours, minutes, secs)
} else {
let minutes = seconds / 60;
let secs = seconds % 60;
format!("{:02}:{:02}", minutes, secs)
}
}
impl Phase {
pub fn ui_color(&self) -> Color {
match self {

View File

@@ -1,5 +1,4 @@
use crate::components::phase::Phase;
use bevy::prelude::*;
use crate::prelude::*;
#[derive(Message)]
pub struct PhaseTimerFinishedMessage {

View File

@@ -1,9 +1,11 @@
use crate::{
components::phase::*,
messages::{phase::*, savegame::SavegameDumpMessage},
states::AppState,
};
use bevy::prelude::*;
use crate::features::savegame::messages::SavegameDumpMessage;
use crate::prelude::*;
use components::{SessionTracker, TimerSettings};
use messages::*;
pub mod components;
pub mod messages;
pub mod utils;
pub struct PhasePlugin;

View File

@@ -0,0 +1,14 @@
pub fn format_time(seconds: f32) -> String {
let seconds = seconds.max(0.0) as u32;
if seconds >= 3600 {
let hours = seconds / 3600;
let minutes = (seconds % 3600) / 60;
let secs = seconds % 60;
format!("{:02}:{:02}:{:02}", hours, minutes, secs)
} else {
let minutes = seconds / 60;
let secs = seconds % 60;
format!("{:02}:{:02}", minutes, secs)
}
}

View File

@@ -1,8 +1,6 @@
use crate::prelude::*;
use std::collections::VecDeque;
use bevy::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Component)]
pub struct Pom;

View File

@@ -1,4 +1,4 @@
use bevy::prelude::*;
use crate::prelude::*;
#[derive(Message)]
pub struct MoveMessage {
@@ -10,3 +10,9 @@ pub struct MoveMessage {
pub struct InvalidMoveMessage {
pub message: String,
}
#[derive(Message)]
pub struct InteractStartMessage {
pub x: u32,
pub y: u32,
}

View File

@@ -1,12 +1,11 @@
use crate::components::pom::{GridPosition, MovingState, PathQueue, Pom};
use crate::components::tile::{Grid, TileState};
use crate::config::GameConfig;
use crate::messages::r#move::{InvalidMoveMessage, MoveMessage};
use crate::plugins::grid::{TILE_SIZE, grid_to_world_coords};
use crate::states::*;
use crate::utils::pathfinding::find_path;
use bevy::prelude::*;
use bevy_aseprite_ultra::prelude::*;
use crate::prelude::*;
use components::*;
use messages::InvalidMoveMessage;
use utils::find_path;
pub mod components;
pub mod messages;
pub mod utils;
pub struct PomPlugin;

View File

@@ -1,5 +1,4 @@
use crate::components::tile::{Grid, TileState};
use bevy::prelude::*;
use crate::prelude::*;
use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap, VecDeque};

View File

@@ -1,4 +1,4 @@
use bevy::prelude::*;
use crate::prelude::*;
use directories::ProjectDirs;
use std::path::PathBuf;

View File

@@ -1,4 +1,4 @@
use bevy::prelude::*;
use crate::prelude::*;
#[derive(Message)]
pub struct SavegameDumpMessage;

View File

@@ -1,18 +1,12 @@
use crate::{
components::{
phase::{CurrentPhase, SessionTracker, TimerSettings},
pom::{GridPosition, Pom},
savegame::SavegamePath,
tile::{Grid, TileState},
},
messages::savegame::*,
states::AppState,
};
use bevy::prelude::*;
use serde::{Deserialize, Serialize};
use crate::features::phase::components::{SessionTracker, TimerSettings};
use crate::prelude::*;
use messages::*;
use std::fs::File;
use std::io::Write;
pub mod components;
pub mod messages;
pub struct SavegamePlugin;
impl Plugin for SavegamePlugin {

View File

@@ -1,5 +1,4 @@
use crate::{components::savegame::SavegamePath, states::*};
use bevy::prelude::*;
use crate::prelude::*;
pub struct StartScreenPlugin;

View File

@@ -1,9 +1,5 @@
use crate::{
components::{phase::CurrentPhase, ui::*},
messages::savegame::SavegameDumpMessage,
states::AppState,
};
use bevy::prelude::*;
use crate::features::savegame::messages::SavegameDumpMessage;
use crate::prelude::*;
pub struct StatusPlugin;

View File

@@ -1,4 +1,4 @@
use bevy::prelude::*;
use crate::prelude::*;
#[derive(Component)]
pub struct UiStatusRootContainer;

1
src/features/ui/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod components;

View File

@@ -1,7 +1,2 @@
pub mod components;
pub mod config;
pub mod errors;
pub mod messages;
pub mod plugins;
pub mod states;
pub mod utils;
pub mod features;
pub mod prelude;

View File

@@ -1,11 +1,8 @@
use bevy::prelude::*;
use bevy_aseprite_ultra::prelude::*;
use bevy_dev_tools::fps_overlay::*;
use pomomon_garden::config::{GameConfig, read_config};
use pomomon_garden::plugins;
use pomomon_garden::prelude::*;
fn main() {
let config = read_config().unwrap_or(GameConfig::default());
let config = GameConfig::read_config().unwrap_or(GameConfig::default());
App::new()
.add_plugins((
@@ -25,15 +22,15 @@ fn main() {
},
},))
.add_plugins((
plugins::CorePlugin,
plugins::StartScreenPlugin,
plugins::GameScreenPlugin,
plugins::GridPlugin,
plugins::PomPlugin,
plugins::InputPlugin,
plugins::PhasePlugin,
plugins::StatusPlugin,
plugins::SavegamePlugin,
features::CorePlugin,
features::StartScreenPlugin,
features::GameScreenPlugin,
features::GridPlugin,
features::PomPlugin,
features::InputPlugin,
features::PhasePlugin,
features::StatusPlugin,
features::SavegamePlugin,
))
.insert_resource(config)
.run();

View File

@@ -1,7 +0,0 @@
use bevy::prelude::*;
#[derive(Message)]
pub struct InteractStartMessage {
pub x: u32,
pub y: u32,
}

View File

@@ -1,4 +0,0 @@
pub mod interact;
pub mod r#move;
pub mod phase;
pub mod savegame;

20
src/prelude.rs Normal file
View File

@@ -0,0 +1,20 @@
pub use crate::features;
pub use crate::features::{
config::components::GameConfig,
core::states::AppState,
grid::{
components::{Grid, Tile, TileState},
consts::TILE_SIZE,
utils::{grid_to_world_coords, world_to_grid_coords},
},
phase::components::{CurrentPhase, Phase},
pom::{
components::{GridPosition, MovingState, Pom},
messages::{InteractStartMessage, MoveMessage},
},
savegame::components::SavegamePath,
ui::components::*,
};
pub use bevy::prelude::*;
pub use bevy_aseprite_ultra::prelude::*;
pub use serde::{Deserialize, Serialize};

View File

@@ -1,8 +0,0 @@
use bevy::prelude::*;
#[derive(States, Clone, PartialEq, Eq, Debug, Hash, Default, Reflect)]
pub enum AppState {
#[default]
StartScreen,
GameScreen,
}

View File

@@ -1 +0,0 @@
pub mod pathfinding;