Merge branch '53-refactor-project-structure' into 'dev'
Refactor project structure See merge request softwaregrundprojekt/2025-2026/einzelprojekt/tutorium-moritz/bernroider-dominik/bernroider-dominik!11
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
pub mod phase;
|
||||
pub mod pom;
|
||||
pub mod savegame;
|
||||
pub mod tile;
|
||||
pub mod ui;
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
1
src/features/config/mod.rs
Normal file
1
src/features/config/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod components;
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::states::*;
|
||||
use bevy::prelude::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub mod states;
|
||||
|
||||
pub struct CorePlugin;
|
||||
|
||||
8
src/features/core/states.rs
Normal file
8
src/features/core/states.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(States, Clone, PartialEq, Eq, Debug, Hash, Default)]
|
||||
pub enum AppState {
|
||||
#[default]
|
||||
StartScreen,
|
||||
GameScreen,
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::states::*;
|
||||
use bevy::prelude::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub struct GameScreenPlugin;
|
||||
|
||||
@@ -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 {
|
||||
1
src/features/grid/consts.rs
Normal file
1
src/features/grid/consts.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub const TILE_SIZE: f32 = 32.0;
|
||||
@@ -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),
|
||||
)
|
||||
}
|
||||
43
src/features/grid/utils.rs
Normal file
43
src/features/grid/utils.rs
Normal 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),
|
||||
)
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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 {
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::components::phase::Phase;
|
||||
use bevy::prelude::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Message)]
|
||||
pub struct PhaseTimerFinishedMessage {
|
||||
@@ -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;
|
||||
|
||||
14
src/features/phase/utils.rs
Normal file
14
src/features/phase/utils.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
use crate::prelude::*;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Pom;
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use bevy::prelude::*;
|
||||
use crate::prelude::*;
|
||||
use directories::ProjectDirs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use bevy::prelude::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Message)]
|
||||
pub struct SavegameDumpMessage;
|
||||
@@ -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 {
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::{components::savegame::SavegamePath, states::*};
|
||||
use bevy::prelude::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub struct StartScreenPlugin;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -38,13 +34,13 @@ fn setup(mut commands: Commands) {
|
||||
BackgroundColor(Color::srgba(0.0, 0.0, 0.0, 0.8)),
|
||||
children![
|
||||
(
|
||||
UiPhaseText,
|
||||
UiStatusText::Phase,
|
||||
Text::new("..."),
|
||||
TextFont::from_font_size(16.0),
|
||||
TextColor(Color::WHITE)
|
||||
),
|
||||
(
|
||||
UiTimerText,
|
||||
UiStatusText::Timer,
|
||||
Text::new("--:--"),
|
||||
TextFont::from_font_size(16.0),
|
||||
TextColor(Color::WHITE)
|
||||
@@ -63,22 +59,17 @@ fn setup(mut commands: Commands) {
|
||||
));
|
||||
}
|
||||
|
||||
fn update_status(
|
||||
phase_res: Res<CurrentPhase>,
|
||||
mut phase_query: Query<&mut Text, (With<UiPhaseText>, Without<UiTimerText>)>,
|
||||
mut timer_query: Query<&mut Text, (With<UiTimerText>, Without<UiPhaseText>)>,
|
||||
) {
|
||||
fn update_status(phase_res: Res<CurrentPhase>, mut text_query: Query<(&mut Text, &UiStatusText)>) {
|
||||
if !phase_res.is_changed() {
|
||||
return;
|
||||
}
|
||||
let current_phase = &phase_res.0;
|
||||
|
||||
if let Ok(mut phase_text) = phase_query.single_mut() {
|
||||
phase_text.0 = current_phase.display_name().to_string();
|
||||
}
|
||||
|
||||
if let Ok(mut timer_text) = timer_query.single_mut() {
|
||||
timer_text.0 = current_phase.format_duration();
|
||||
for (mut text, status_type) in text_query.iter_mut() {
|
||||
text.0 = match status_type {
|
||||
UiStatusText::Phase => current_phase.display_name().into(),
|
||||
UiStatusText::Timer => current_phase.format_duration(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use bevy::prelude::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct UiStatusRootContainer;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct UiPhaseText;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct UiTimerText;
|
||||
pub enum UiStatusText {
|
||||
Phase,
|
||||
Timer,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub enum UiStatusButton {
|
||||
1
src/features/ui/mod.rs
Normal file
1
src/features/ui/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod components;
|
||||
@@ -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;
|
||||
|
||||
25
src/main.rs
25
src/main.rs
@@ -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();
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
#[derive(Message)]
|
||||
pub struct InteractStartMessage {
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
pub mod interact;
|
||||
pub mod r#move;
|
||||
pub mod phase;
|
||||
pub mod savegame;
|
||||
20
src/prelude.rs
Normal file
20
src/prelude.rs
Normal 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};
|
||||
@@ -1,8 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
#[derive(States, Clone, PartialEq, Eq, Debug, Hash, Default, Reflect)]
|
||||
pub enum AppState {
|
||||
#[default]
|
||||
StartScreen,
|
||||
GameScreen,
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
pub mod pathfinding;
|
||||
Reference in New Issue
Block a user