feat: Game configuration #38
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -3622,6 +3622,8 @@ dependencies = [
|
|||||||
"bevy",
|
"bevy",
|
||||||
"bevy_aseprite_ultra",
|
"bevy_aseprite_ultra",
|
||||||
"bevy_dev_tools",
|
"bevy_dev_tools",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -17,3 +17,5 @@ lto = "thin"
|
|||||||
bevy = "0.17.2"
|
bevy = "0.17.2"
|
||||||
bevy_aseprite_ultra = "0.7.0"
|
bevy_aseprite_ultra = "0.7.0"
|
||||||
bevy_dev_tools = "0.17.2"
|
bevy_dev_tools = "0.17.2"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
|
|||||||
5
assets/config.json
Normal file
5
assets/config.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"grid_width": 10,
|
||||||
|
"grid_height": 10,
|
||||||
|
"pom_speed": 2
|
||||||
|
}
|
||||||
@@ -24,10 +24,10 @@
|
|||||||
|
|
||||||
rust-toolchain = with fenix.packages.${system};
|
rust-toolchain = with fenix.packages.${system};
|
||||||
combine [
|
combine [
|
||||||
beta.rustc
|
stable.rustc
|
||||||
beta.cargo
|
stable.cargo
|
||||||
beta.rust-src
|
stable.rust-src
|
||||||
beta.rust-analyzer
|
stable.rust-analyzer
|
||||||
];
|
];
|
||||||
|
|
||||||
bevyDeps = with pkgs; [
|
bevyDeps = with pkgs; [
|
||||||
|
|||||||
17
src/config.rs
Normal file
17
src/config.rs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::BufReader;
|
||||||
|
|
||||||
|
#[derive(Resource, Deserialize, Debug)]
|
||||||
|
pub struct GameConfig {
|
||||||
|
pub grid_width: u32,
|
||||||
|
pub grid_height: u32,
|
||||||
|
pub pom_speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_config() -> Option<GameConfig> {
|
||||||
|
let file = File::open("assets/config.json").ok()?;
|
||||||
|
let reader = BufReader::new(file);
|
||||||
|
serde_json::from_reader(reader).ok()
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod components;
|
pub mod components;
|
||||||
|
pub mod config;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod messages;
|
pub mod messages;
|
||||||
pub mod plugins;
|
pub mod plugins;
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_aseprite_ultra::prelude::*;
|
use bevy_aseprite_ultra::prelude::*;
|
||||||
use bevy_dev_tools::fps_overlay::*;
|
use bevy_dev_tools::fps_overlay::*;
|
||||||
|
use pomomon_garden::config::read_config;
|
||||||
use pomomon_garden::plugins;
|
use pomomon_garden::plugins;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let config = read_config().expect("Error reading config");
|
||||||
|
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((
|
.add_plugins((
|
||||||
DefaultPlugins.set(ImagePlugin::default_nearest()),
|
DefaultPlugins.set(ImagePlugin::default_nearest()),
|
||||||
@@ -29,5 +32,6 @@ fn main() {
|
|||||||
plugins::PomPlugin,
|
plugins::PomPlugin,
|
||||||
plugins::InputPlugin,
|
plugins::InputPlugin,
|
||||||
))
|
))
|
||||||
|
.insert_resource(config)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
components::tile::{Grid, Tile, TileState},
|
components::tile::{Grid, Tile, TileState},
|
||||||
|
config::GameConfig,
|
||||||
states::AppState,
|
states::AppState,
|
||||||
};
|
};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_aseprite_ultra::prelude::AseSlice;
|
use bevy_aseprite_ultra::prelude::AseSlice;
|
||||||
|
|
||||||
pub const TILE_SIZE: f32 = 32.0;
|
pub const TILE_SIZE: f32 = 32.0;
|
||||||
pub const GRID_WIDTH: u32 = 10;
|
|
||||||
pub const GRID_HEIGHT: u32 = 10;
|
|
||||||
|
|
||||||
pub const GRID_START_X: f32 = -(GRID_WIDTH as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0;
|
pub fn grid_start_x(grid_width: u32) -> f32 {
|
||||||
pub const GRID_START_Y: f32 = -(GRID_HEIGHT as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0;
|
-(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 struct GridPlugin;
|
pub struct GridPlugin;
|
||||||
|
|
||||||
@@ -26,13 +29,15 @@ impl Plugin for GridPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>, config: Res<GameConfig>) {
|
||||||
let mut tiles = Vec::with_capacity(GRID_WIDTH as usize);
|
let grid_width = config.grid_width;
|
||||||
|
let grid_height = config.grid_height;
|
||||||
|
let mut tiles = Vec::with_capacity(grid_width as usize);
|
||||||
|
|
||||||
for x in 0..GRID_WIDTH {
|
for x in 0..grid_width {
|
||||||
let mut column = Vec::with_capacity(GRID_HEIGHT as usize);
|
let mut column = Vec::with_capacity(grid_height as usize);
|
||||||
|
|
||||||
for y in 0..GRID_HEIGHT {
|
for y in 0..grid_height {
|
||||||
let tile_entity = commands
|
let tile_entity = commands
|
||||||
.spawn((
|
.spawn((
|
||||||
Tile { x, y },
|
Tile { x, y },
|
||||||
@@ -42,7 +47,13 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
aseprite: asset_server.load("tiles/tile-unclaimed.aseprite"),
|
aseprite: asset_server.load("tiles/tile-unclaimed.aseprite"),
|
||||||
},
|
},
|
||||||
Sprite::default(),
|
Sprite::default(),
|
||||||
Transform::from_translation(grid_to_world_coords(x, y, None)),
|
Transform::from_translation(grid_to_world_coords(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
None,
|
||||||
|
grid_width,
|
||||||
|
grid_height,
|
||||||
|
)),
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
column.push(tile_entity);
|
column.push(tile_entity);
|
||||||
@@ -51,8 +62,8 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
commands.insert_resource(Grid {
|
commands.insert_resource(Grid {
|
||||||
width: GRID_WIDTH,
|
width: grid_width,
|
||||||
height: GRID_HEIGHT,
|
height: grid_height,
|
||||||
tiles,
|
tiles,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -84,27 +95,36 @@ fn update_tile_colors(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn world_to_grid_coords(world_pos: Vec3) -> (u32, u32) {
|
pub fn world_to_grid_coords(world_pos: Vec3, grid_width: u32, grid_height: u32) -> (u32, u32) {
|
||||||
let x = ((world_pos.x - GRID_START_X + TILE_SIZE / 2.0) / TILE_SIZE).floor();
|
let start_x = grid_start_x(grid_width);
|
||||||
let y = ((world_pos.y - GRID_START_Y + TILE_SIZE / 2.0) / TILE_SIZE).floor();
|
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 x_u32 = x as u32;
|
||||||
let mut y_u32 = y as u32;
|
let mut y_u32 = y as u32;
|
||||||
|
|
||||||
if x_u32 >= GRID_WIDTH {
|
if x_u32 >= grid_width {
|
||||||
x_u32 = GRID_WIDTH - 1;
|
x_u32 = grid_width - 1;
|
||||||
}
|
}
|
||||||
if y_u32 >= GRID_HEIGHT {
|
if y_u32 >= grid_height {
|
||||||
y_u32 = GRID_HEIGHT - 1;
|
y_u32 = grid_height - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
(x_u32, y_u32)
|
(x_u32, y_u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn grid_to_world_coords(grid_x: u32, grid_y: u32, z: Option<f32>) -> Vec3 {
|
pub fn grid_to_world_coords(
|
||||||
|
grid_x: u32,
|
||||||
|
grid_y: u32,
|
||||||
|
z: Option<f32>,
|
||||||
|
grid_width: u32,
|
||||||
|
grid_height: u32,
|
||||||
|
) -> Vec3 {
|
||||||
Vec3::new(
|
Vec3::new(
|
||||||
GRID_START_X + grid_x as f32 * TILE_SIZE,
|
grid_start_x(grid_width) + grid_x as f32 * TILE_SIZE,
|
||||||
GRID_START_Y + grid_y as f32 * TILE_SIZE,
|
grid_start_y(grid_height) + grid_y as f32 * TILE_SIZE,
|
||||||
z.unwrap_or(0.0),
|
z.unwrap_or(0.0),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use bevy::prelude::*;
|
|||||||
use bevy::window::PrimaryWindow;
|
use bevy::window::PrimaryWindow;
|
||||||
|
|
||||||
use crate::components::tile::{Grid, TileState};
|
use crate::components::tile::{Grid, TileState};
|
||||||
|
use crate::config::GameConfig;
|
||||||
use crate::messages::{InteractStartMessage, InvalidMoveMessage, MoveMessage};
|
use crate::messages::{InteractStartMessage, InvalidMoveMessage, MoveMessage};
|
||||||
use crate::plugins::grid::world_to_grid_coords;
|
use crate::plugins::grid::world_to_grid_coords;
|
||||||
use crate::states::AppState;
|
use crate::states::AppState;
|
||||||
@@ -28,6 +29,7 @@ fn move_click(
|
|||||||
mouse_btn: Res<ButtonInput<MouseButton>>,
|
mouse_btn: Res<ButtonInput<MouseButton>>,
|
||||||
window: Single<&Window, With<PrimaryWindow>>,
|
window: Single<&Window, With<PrimaryWindow>>,
|
||||||
camera: Single<(&Camera, &GlobalTransform), With<Camera2d>>,
|
camera: Single<(&Camera, &GlobalTransform), With<Camera2d>>,
|
||||||
|
config: Res<GameConfig>,
|
||||||
) {
|
) {
|
||||||
if mouse_btn.just_pressed(MouseButton::Right) {
|
if mouse_btn.just_pressed(MouseButton::Right) {
|
||||||
let (cam, cam_transform) = *camera;
|
let (cam, cam_transform) = *camera;
|
||||||
@@ -38,7 +40,7 @@ fn move_click(
|
|||||||
let Ok(world_pos) = cam.viewport_to_world(cam_transform, cursor_pos) else {
|
let Ok(world_pos) = cam.viewport_to_world(cam_transform, cursor_pos) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let (x, y) = world_to_grid_coords(world_pos.origin);
|
let (x, y) = world_to_grid_coords(world_pos.origin, config.grid_width, config.grid_height);
|
||||||
|
|
||||||
println!("Move Click: ({}, {})", x, y);
|
println!("Move Click: ({}, {})", x, y);
|
||||||
move_messages.write(MoveMessage { x, y });
|
move_messages.write(MoveMessage { x, y });
|
||||||
@@ -50,6 +52,7 @@ fn interact_click(
|
|||||||
mouse_btn: Res<ButtonInput<MouseButton>>,
|
mouse_btn: Res<ButtonInput<MouseButton>>,
|
||||||
window: Single<&Window, With<PrimaryWindow>>,
|
window: Single<&Window, With<PrimaryWindow>>,
|
||||||
camera: Single<(&Camera, &GlobalTransform), With<Camera2d>>,
|
camera: Single<(&Camera, &GlobalTransform), With<Camera2d>>,
|
||||||
|
config: Res<GameConfig>,
|
||||||
// for debug
|
// for debug
|
||||||
grid: ResMut<Grid>,
|
grid: ResMut<Grid>,
|
||||||
tile_query: Query<&mut TileState>,
|
tile_query: Query<&mut TileState>,
|
||||||
@@ -63,7 +66,7 @@ fn interact_click(
|
|||||||
let Ok(world_pos) = cam.viewport_to_world(cam_transform, cursor_pos) else {
|
let Ok(world_pos) = cam.viewport_to_world(cam_transform, cursor_pos) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let (x, y) = world_to_grid_coords(world_pos.origin);
|
let (x, y) = world_to_grid_coords(world_pos.origin, config.grid_width, config.grid_height);
|
||||||
|
|
||||||
println!("Interact Click: ({}, {})", x, y);
|
println!("Interact Click: ({}, {})", x, y);
|
||||||
interact_messages.write(InteractStartMessage { x, y });
|
interact_messages.write(InteractStartMessage { x, y });
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
use crate::components::pom::{GridPosition, MovingState, PathQueue, Pom};
|
use crate::components::pom::{GridPosition, MovingState, PathQueue, Pom};
|
||||||
use crate::components::tile::{Grid, TileState};
|
use crate::components::tile::{Grid, TileState};
|
||||||
|
use crate::config::GameConfig;
|
||||||
use crate::messages::{InvalidMoveMessage, MoveMessage};
|
use crate::messages::{InvalidMoveMessage, MoveMessage};
|
||||||
use crate::plugins::grid::{GRID_WIDTH, grid_to_world_coords};
|
use crate::plugins::grid::{TILE_SIZE, grid_to_world_coords};
|
||||||
use crate::states::*;
|
use crate::states::*;
|
||||||
use crate::utils::pathfinding::find_path;
|
use crate::utils::pathfinding::find_path;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_aseprite_ultra::prelude::*;
|
use bevy_aseprite_ultra::prelude::*;
|
||||||
|
|
||||||
const MOVE_SPEED: f32 = 2.0 * GRID_WIDTH as f32;
|
|
||||||
|
|
||||||
pub struct PomPlugin;
|
pub struct PomPlugin;
|
||||||
|
|
||||||
impl Plugin for PomPlugin {
|
impl Plugin for PomPlugin {
|
||||||
@@ -23,7 +22,7 @@ impl Plugin for PomPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>, config: Res<GameConfig>) {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
Pom,
|
Pom,
|
||||||
GridPosition { x: 0, y: 0 },
|
GridPosition { x: 0, y: 0 },
|
||||||
@@ -34,7 +33,13 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
animation: Animation::tag("sleep-sit-start").with_repeat(AnimationRepeat::Loop),
|
animation: Animation::tag("sleep-sit-start").with_repeat(AnimationRepeat::Loop),
|
||||||
},
|
},
|
||||||
Sprite::default(),
|
Sprite::default(),
|
||||||
Transform::from_translation(grid_to_world_coords(0, 0, Some(1.0))),
|
Transform::from_translation(grid_to_world_coords(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
Some(1.0),
|
||||||
|
config.grid_width,
|
||||||
|
config.grid_height,
|
||||||
|
)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,12 +87,20 @@ fn move_pom(
|
|||||||
&mut PathQueue,
|
&mut PathQueue,
|
||||||
&mut MovingState,
|
&mut MovingState,
|
||||||
)>,
|
)>,
|
||||||
|
config: Res<GameConfig>,
|
||||||
) {
|
) {
|
||||||
let dt = time.delta_secs();
|
let dt = time.delta_secs();
|
||||||
|
let move_speed = config.pom_speed * TILE_SIZE;
|
||||||
|
|
||||||
for (mut transform, mut grid_pos, mut path_queue, mut moving_state) in query.iter_mut() {
|
for (mut transform, mut grid_pos, mut path_queue, mut moving_state) in query.iter_mut() {
|
||||||
if let Some(&target) = path_queue.steps.front() {
|
if let Some(&target) = path_queue.steps.front() {
|
||||||
let target_pos = grid_to_world_coords(target.0, target.1, Some(1.0));
|
let target_pos = grid_to_world_coords(
|
||||||
|
target.0,
|
||||||
|
target.1,
|
||||||
|
Some(1.0),
|
||||||
|
config.grid_width,
|
||||||
|
config.grid_height,
|
||||||
|
);
|
||||||
let distance = transform.translation.distance(target_pos);
|
let distance = transform.translation.distance(target_pos);
|
||||||
|
|
||||||
let dx = target.0 as i32 - grid_pos.x as i32;
|
let dx = target.0 as i32 - grid_pos.x as i32;
|
||||||
@@ -100,14 +113,14 @@ fn move_pom(
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
if distance < MOVE_SPEED * dt {
|
if distance < move_speed * dt {
|
||||||
transform.translation = target_pos;
|
transform.translation = target_pos;
|
||||||
grid_pos.x = target.0;
|
grid_pos.x = target.0;
|
||||||
grid_pos.y = target.1;
|
grid_pos.y = target.1;
|
||||||
path_queue.steps.pop_front();
|
path_queue.steps.pop_front();
|
||||||
} else {
|
} else {
|
||||||
let direction = (target_pos - transform.translation).normalize();
|
let direction = (target_pos - transform.translation).normalize();
|
||||||
transform.translation += direction * MOVE_SPEED * dt;
|
transform.translation += direction * move_speed * dt;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*moving_state = MovingState::Idle;
|
*moving_state = MovingState::Idle;
|
||||||
|
|||||||
Reference in New Issue
Block a user