feat(player): add ascension/descension

This commit is contained in:
Kristofers Solo 2024-12-18 17:01:21 +02:00
parent 4640862402
commit 269686323f
10 changed files with 138 additions and 11 deletions

View File

@ -1,10 +1,10 @@
use bevy::prelude::*; use bevy::prelude::*;
#[derive(Debug, Reflect, Component)] #[derive(Debug, Reflect, Component, Deref, DerefMut)]
#[reflect(Component)] #[reflect(Component)]
pub struct Floor(pub u8); pub struct Floor(pub u8);
#[derive(Debug, Reflect, Component)] #[derive(Debug, Reflect, Component, Deref, DerefMut)]
#[reflect(Component)] #[reflect(Component)]
pub struct TargetFloor(pub u8); pub struct TargetFloor(pub u8);
@ -17,3 +17,13 @@ impl Default for Floor {
Self(1) Self(1)
} }
} }
impl Floor {
pub fn increase(&self) -> Self {
Self(self.0.saturating_add(1))
}
pub fn decrease(&self) -> Self {
Self(self.0.saturating_sub(1).max(1))
}
}

View File

@ -4,4 +4,6 @@ mod systems;
use bevy::prelude::*; use bevy::prelude::*;
pub(super) fn plugin(_app: &mut App) {} pub(super) fn plugin(app: &mut App) {
app.add_plugins(systems::plugin);
}

View File

@ -1 +1,3 @@
use bevy::prelude::*;
pub(super) fn plugin(_app: &mut App) {}

View File

@ -1,5 +1,7 @@
use crate::theme::palette::rose_pine::{LOVE, PINE};
use super::resources::GlobalMazeConfig; use super::resources::GlobalMazeConfig;
use bevy::prelude::*; use bevy::{prelude::*, utils::HashMap};
use std::f32::consts::FRAC_PI_2; use std::f32::consts::FRAC_PI_2;
const WALL_OVERLAP_MODIFIER: f32 = 1.25; const WALL_OVERLAP_MODIFIER: f32 = 1.25;
@ -11,6 +13,7 @@ pub(crate) struct MazeAssets {
pub(crate) wall_mesh: Handle<Mesh>, pub(crate) wall_mesh: Handle<Mesh>,
pub(crate) hex_material: Handle<StandardMaterial>, pub(crate) hex_material: Handle<StandardMaterial>,
pub(crate) wall_material: Handle<StandardMaterial>, pub(crate) wall_material: Handle<StandardMaterial>,
pub(crate) custom_materials: HashMap<String, Handle<StandardMaterial>>,
} }
impl MazeAssets { impl MazeAssets {
@ -19,6 +22,11 @@ impl MazeAssets {
materials: &mut ResMut<Assets<StandardMaterial>>, materials: &mut ResMut<Assets<StandardMaterial>>,
global_config: &GlobalMazeConfig, global_config: &GlobalMazeConfig,
) -> MazeAssets { ) -> MazeAssets {
let mut custom_materials = HashMap::new();
custom_materials.extend(vec![
("LOVE".to_string(), materials.add(red_material())),
("PINE".to_string(), materials.add(blue_material())),
]);
MazeAssets { MazeAssets {
hex_mesh: meshes.add(generate_hex_mesh( hex_mesh: meshes.add(generate_hex_mesh(
global_config.hex_size, global_config.hex_size,
@ -30,6 +38,7 @@ impl MazeAssets {
)), )),
hex_material: materials.add(white_material()), hex_material: materials.add(white_material()),
wall_material: materials.add(Color::BLACK), wall_material: materials.add(Color::BLACK),
custom_materials,
} }
} }
} }
@ -53,9 +62,8 @@ fn generate_square_mesh(depth: f32, wall_size: f32) -> Mesh {
Mesh::from(rectangular_prism).rotated_by(rotation) Mesh::from(rectangular_prism).rotated_by(rotation)
} }
fn white_material() -> StandardMaterial { pub(crate) fn white_material() -> StandardMaterial {
StandardMaterial { StandardMaterial {
base_color: Color::WHITE,
emissive: LinearRgba::new( emissive: LinearRgba::new(
WHITE_EMISSION_INTENSITY, WHITE_EMISSION_INTENSITY,
WHITE_EMISSION_INTENSITY, WHITE_EMISSION_INTENSITY,
@ -65,3 +73,17 @@ fn white_material() -> StandardMaterial {
..default() ..default()
} }
} }
pub(crate) fn red_material() -> StandardMaterial {
StandardMaterial {
emissive: LOVE.to_linear(),
..default()
}
}
pub(crate) fn blue_material() -> StandardMaterial {
StandardMaterial {
emissive: PINE.to_linear(),
..default()
}
}

View File

@ -81,12 +81,28 @@ pub(super) fn spawn_single_hex_tile(
HexOrientation::Flat => Quat::from_rotation_y(FRAC_PI_6), // 30 degrees rotation HexOrientation::Flat => Quat::from_rotation_y(FRAC_PI_6), // 30 degrees rotation
}; };
let material = match tile.pos() {
pos if pos == maze_config.start_pos => assets
.custom_materials
.get("PINE")
.cloned()
.to_owned()
.unwrap(),
pos if pos == maze_config.end_pos => assets
.custom_materials
.get("LOVE")
.cloned()
.to_owned()
.unwrap(),
_ => assets.hex_material.clone(),
};
parent parent
.spawn(( .spawn((
Name::new(format!("Hex {}", tile)), Name::new(format!("Hex {}", tile)),
Tile, Tile,
Mesh3d(assets.hex_mesh.clone()), Mesh3d(assets.hex_mesh.clone()),
MeshMaterial3d(assets.hex_material.clone()), MeshMaterial3d(material),
Transform::from_translation(world_pos).with_rotation(rotation), Transform::from_translation(world_pos).with_rotation(rotation),
)) ))
.with_children(|parent| spawn_walls(parent, assets, tile.walls(), global_config)); .with_children(|parent| spawn_walls(parent, assets, tile.walls(), global_config));

View File

@ -8,3 +8,13 @@ pub struct RespawnPlayer;
#[derive(Debug, Event)] #[derive(Debug, Event)]
pub struct DespawnPlayer; pub struct DespawnPlayer;
#[derive(Debug, Event)]
pub struct AscendPlayer {
pub floor: u8,
}
#[derive(Debug, Event)]
pub struct DescendPlayer {
pub floor: u8,
}

View File

@ -6,13 +6,15 @@ mod triggers;
use bevy::{ecs::system::RunSystemOnce, prelude::*}; use bevy::{ecs::system::RunSystemOnce, prelude::*};
use components::Player; use components::Player;
use events::{DespawnPlayer, RespawnPlayer, SpawnPlayer}; use events::{AscendPlayer, DescendPlayer, DespawnPlayer, RespawnPlayer, SpawnPlayer};
pub(super) fn plugin(app: &mut App) { pub(super) fn plugin(app: &mut App) {
app.register_type::<Player>() app.register_type::<Player>()
.add_event::<SpawnPlayer>() .add_event::<SpawnPlayer>()
.add_event::<RespawnPlayer>() .add_event::<RespawnPlayer>()
.add_event::<DespawnPlayer>() .add_event::<DespawnPlayer>()
.add_event::<AscendPlayer>()
.add_event::<DescendPlayer>()
.add_plugins((triggers::plugin, systems::plugin)); .add_plugins((triggers::plugin, systems::plugin));
} }

View File

@ -0,0 +1,30 @@
use bevy::prelude::*;
use crate::{
floor::components::{CurrentFloor, Floor},
maze::components::MazeConfig,
player::{
components::{CurrentPosition, Player},
events::AscendPlayer,
},
};
pub(super) fn ascend_player(
query: Query<&CurrentPosition, With<Player>>,
maze_config_query: Query<(&MazeConfig, &Floor), With<CurrentFloor>>,
mut event_writer: EventWriter<AscendPlayer>,
) {
let Ok((config, floor)) = maze_config_query.get_single() else {
warn!("No current floor configuration found");
return;
};
for current_hex in query.iter() {
if current_hex.0 == config.end_pos {
event_writer.send(AscendPlayer {
floor: *floor.increase(),
});
return;
}
}
}

View File

@ -0,0 +1,30 @@
use bevy::prelude::*;
use crate::{
floor::components::{CurrentFloor, Floor},
maze::components::MazeConfig,
player::{
components::{CurrentPosition, Player},
events::DescendPlayer,
},
};
pub(super) fn descend_player(
query: Query<&CurrentPosition, With<Player>>,
maze_config_query: Query<(&MazeConfig, &Floor), With<CurrentFloor>>,
mut event_writer: EventWriter<DescendPlayer>,
) {
let Ok((config, floor)) = maze_config_query.get_single() else {
warn!("No current floor configuration found");
return;
};
for current_hex in query.iter() {
if current_hex.0 == config.start_pos {
event_writer.send(DescendPlayer {
floor: *floor.decrease(),
});
return;
}
}
}

View File

@ -1,17 +1,20 @@
mod ascend;
mod descend;
mod input; mod input;
mod movement; mod movement;
pub mod setup; pub mod setup;
use crate::maze::MazePluginLoaded;
use ascend::ascend_player;
use bevy::prelude::*; use bevy::prelude::*;
use descend::descend_player;
use input::player_input; use input::player_input;
use movement::player_movement; use movement::player_movement;
use crate::maze::MazePluginLoaded;
pub(super) fn plugin(app: &mut App) { pub(super) fn plugin(app: &mut App) {
app.add_systems( app.add_systems(
Update, Update,
(player_input, player_movement) (player_input, player_movement, ascend_player, descend_player)
.chain() .chain()
.run_if(resource_exists::<MazePluginLoaded>), .run_if(resource_exists::<MazePluginLoaded>),
); );