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::{
|
use crate::{
|
||||||
constants::*,
|
constants::*,
|
||||||
game,
|
game,
|
||||||
tilemap::{ChunkMap, CHUNK_SIZE},
|
tilemap::{ChunkMap, VisibleGameEntity, CHUNK_SIZE},
|
||||||
};
|
};
|
||||||
use bevy::{math::ivec3, prelude::*};
|
use bevy::{math::ivec3, prelude::*};
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ impl Citizen {
|
|||||||
pub fn new(asset_server: &Res<AssetServer>, position: Vec3) -> Self {
|
pub fn new(asset_server: &Res<AssetServer>, position: Vec3) -> Self {
|
||||||
Citizen {
|
Citizen {
|
||||||
ambulatory: Ambulatory {
|
ambulatory: Ambulatory {
|
||||||
walk_speed: 0.,
|
walk_speed: 8.,
|
||||||
run_speed: 6.,
|
run_speed: 6.,
|
||||||
target: None,
|
target: None,
|
||||||
current_path: None,
|
current_path: None,
|
||||||
@@ -189,24 +189,6 @@ pub fn citizen_movement(
|
|||||||
} else if direction.x < 0.0 {
|
} else if direction.x < 0.0 {
|
||||||
transform.scale.x = -PIXEL_RATIO;
|
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
|
// Check if we've reached the next point
|
||||||
if transform.translation.distance(next_point) < TILE_SIZE {
|
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;
|
let mut position = Vec3::new(x.round(), y.round(), 35.0) * TILE_SIZE;
|
||||||
position.z += 0.1;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-6
@@ -2,6 +2,7 @@ use std::sync::Mutex;
|
|||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use crate::constants::{ITILE_SIZE, TILE_SIZE};
|
use crate::constants::{ITILE_SIZE, TILE_SIZE};
|
||||||
|
use crate::game;
|
||||||
use crate::tile::{FixtureTile, FloorTile, NeedsOccluded, TileMap};
|
use crate::tile::{FixtureTile, FloorTile, NeedsOccluded, TileMap};
|
||||||
use crate::tiles::{
|
use crate::tiles::{
|
||||||
CurrentWorldSpriteState, FixtureTilePrefab, FloorTilePrefab, TerrainSpriteState, TextureIDs,
|
CurrentWorldSpriteState, FixtureTilePrefab, FloorTilePrefab, TerrainSpriteState, TextureIDs,
|
||||||
@@ -365,7 +366,7 @@ fn generate_chunk_weathering_and_precipitation(// mut commands: Commands,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn generate_chunk_forrestry(
|
fn generate_chunk_forrestry(
|
||||||
commands: ParallelCommands<'_, '_>, // Use ParallelCommands for parallel spawning
|
commands: ParallelCommands<'_, '_>,
|
||||||
mut events: EventReader<ChunkForrestryEvent>,
|
mut events: EventReader<ChunkForrestryEvent>,
|
||||||
mut tilemap: ResMut<TileMap>,
|
mut tilemap: ResMut<TileMap>,
|
||||||
texture_ids: Res<TextureIDs>,
|
texture_ids: Res<TextureIDs>,
|
||||||
@@ -402,10 +403,17 @@ fn generate_chunk_forrestry(
|
|||||||
image: texture.clone(),
|
image: texture.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
commands.spawn((
|
let log = commands
|
||||||
sprite,
|
.spawn((
|
||||||
Transform::from_xyz(above_pos.x, above_pos.y, above_pos.z),
|
sprite,
|
||||||
));
|
Transform::from_xyz(
|
||||||
|
above_pos.x,
|
||||||
|
above_pos.y,
|
||||||
|
above_pos.z,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.id();
|
||||||
|
commands.entity(log).insert(VisibleGameEntity);
|
||||||
tree_positions.push(above_pos);
|
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
|
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;
|
pub struct TilemapPlugin;
|
||||||
|
|
||||||
impl Plugin for TilemapPlugin {
|
impl Plugin for TilemapPlugin {
|
||||||
@@ -503,6 +543,7 @@ impl Plugin for TilemapPlugin {
|
|||||||
)
|
)
|
||||||
.chain(),
|
.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