Refactor visibility system to use component-based approach
- Introduce VisibleGameEntity component for entities needing visibility logic - Move Z-index based visibility calculations to dedicated system - Update both citizens and logs to use new visibility system - Remove duplicated visibility logic from citizen movement system - Add compute_visibility_of_game_entities system to Update phase This improves modularity by separating visibility concerns from movement systems.
This commit is contained in:
+4
-21
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
constants::*,
|
||||
game,
|
||||
tilemap::{ChunkMap, CHUNK_SIZE},
|
||||
tilemap::{ChunkMap, VisibleGameEntity, CHUNK_SIZE},
|
||||
};
|
||||
use bevy::{math::ivec3, prelude::*};
|
||||
|
||||
@@ -17,7 +17,7 @@ impl Citizen {
|
||||
pub fn new(asset_server: &Res<AssetServer>, position: Vec3) -> Self {
|
||||
Citizen {
|
||||
ambulatory: Ambulatory {
|
||||
walk_speed: 0.,
|
||||
walk_speed: 8.,
|
||||
run_speed: 6.,
|
||||
target: None,
|
||||
current_path: None,
|
||||
@@ -189,24 +189,6 @@ pub fn citizen_movement(
|
||||
} else if direction.x < 0.0 {
|
||||
transform.scale.x = -PIXEL_RATIO;
|
||||
}
|
||||
if (z_index.0 - transform.translation.z / TILE_SIZE) / 8.0 > 1.0 {
|
||||
*visibility = Visibility::Hidden;
|
||||
} else {
|
||||
if transform.translation.z / TILE_SIZE <= z_index.0 + 1.0 {
|
||||
*visibility = Visibility::Visible;
|
||||
let saturation =
|
||||
((z_index.0 - (transform.translation.z / TILE_SIZE) + 1.)
|
||||
/ 8.0)
|
||||
.clamp(0.0, 1.0);
|
||||
|
||||
sprite.color =
|
||||
Color::hsv(194.7, saturation, 1.0 - (saturation / 2.0));
|
||||
|
||||
sprite.color.set_alpha(1.0 - saturation);
|
||||
} else {
|
||||
*visibility = Visibility::Hidden;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we've reached the next point
|
||||
if transform.translation.distance(next_point) < TILE_SIZE {
|
||||
@@ -409,6 +391,7 @@ pub fn spawn_citizens(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
let mut position = Vec3::new(x.round(), y.round(), 35.0) * TILE_SIZE;
|
||||
position.z += 0.1;
|
||||
|
||||
commands.spawn(Citizen::new(&asset_server, position));
|
||||
let cit = commands.spawn(Citizen::new(&asset_server, position)).id();
|
||||
commands.entity(cit).insert(VisibleGameEntity);
|
||||
}
|
||||
}
|
||||
|
||||
+46
-5
@@ -2,6 +2,7 @@ use std::sync::Mutex;
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::constants::{ITILE_SIZE, TILE_SIZE};
|
||||
use crate::game;
|
||||
use crate::tile::{FixtureTile, FloorTile, NeedsOccluded, TileMap};
|
||||
use crate::tiles::{
|
||||
CurrentWorldSpriteState, FixtureTilePrefab, FloorTilePrefab, TerrainSpriteState, TextureIDs,
|
||||
@@ -365,7 +366,7 @@ fn generate_chunk_weathering_and_precipitation(// mut commands: Commands,
|
||||
}
|
||||
|
||||
fn generate_chunk_forrestry(
|
||||
commands: ParallelCommands<'_, '_>, // Use ParallelCommands for parallel spawning
|
||||
commands: ParallelCommands<'_, '_>,
|
||||
mut events: EventReader<ChunkForrestryEvent>,
|
||||
mut tilemap: ResMut<TileMap>,
|
||||
texture_ids: Res<TextureIDs>,
|
||||
@@ -402,10 +403,17 @@ fn generate_chunk_forrestry(
|
||||
image: texture.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
commands.spawn((
|
||||
let log = commands
|
||||
.spawn((
|
||||
sprite,
|
||||
Transform::from_xyz(above_pos.x, above_pos.y, above_pos.z),
|
||||
));
|
||||
Transform::from_xyz(
|
||||
above_pos.x,
|
||||
above_pos.y,
|
||||
above_pos.z,
|
||||
),
|
||||
))
|
||||
.id();
|
||||
commands.entity(log).insert(VisibleGameEntity);
|
||||
tree_positions.push(above_pos);
|
||||
}
|
||||
}
|
||||
@@ -475,6 +483,38 @@ pub fn absolute_z_to_world_z(z: f32) -> f32 {
|
||||
z - Z_BELOW * ITILE_SIZE as f32
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct VisibleGameEntity;
|
||||
|
||||
pub fn compute_visibility_of_game_entities(
|
||||
mut query: Query<(&Transform, &mut Visibility, &mut Sprite), With<VisibleGameEntity>>,
|
||||
z_index: Res<game::ZIndex>,
|
||||
) {
|
||||
query
|
||||
.par_iter_mut()
|
||||
.for_each(|(transform, mut visibility, mut sprite)| {
|
||||
// if too far away, saturation does not matter
|
||||
if (z_index.0 - transform.translation.z / TILE_SIZE) / 8.0 > 1.0 {
|
||||
*visibility = Visibility::Hidden;
|
||||
return;
|
||||
}
|
||||
// if too high, saturation does not matter
|
||||
if (transform.translation.z) / TILE_SIZE > z_index.0 + 1.0 {
|
||||
*visibility = Visibility::Hidden;
|
||||
return;
|
||||
}
|
||||
|
||||
// if visible, calculate saturation
|
||||
*visibility = Visibility::Visible;
|
||||
let saturation =
|
||||
((z_index.0 - (transform.translation.z / TILE_SIZE) + 1.) / 8.0).clamp(0.0, 1.0);
|
||||
|
||||
sprite.color = Color::hsv(194.7, saturation, 1.0 - (saturation / 2.0));
|
||||
|
||||
sprite.color.set_alpha(1.0 - saturation);
|
||||
});
|
||||
}
|
||||
|
||||
pub struct TilemapPlugin;
|
||||
|
||||
impl Plugin for TilemapPlugin {
|
||||
@@ -503,6 +543,7 @@ impl Plugin for TilemapPlugin {
|
||||
)
|
||||
.chain(),
|
||||
)
|
||||
.add_systems(FixedUpdate, generate_chunks_from_algo);
|
||||
.add_systems(FixedUpdate, generate_chunks_from_algo)
|
||||
.add_systems(Update, compute_visibility_of_game_entities);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user