partial chunking
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 577 B |
Binary file not shown.
|
After Width: | Height: | Size: 745 B |
+60
-20
@@ -1,4 +1,7 @@
|
|||||||
use crate::constants::*;
|
use crate::{
|
||||||
|
constants::{self, *},
|
||||||
|
tilemap,
|
||||||
|
};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
|
|
||||||
@@ -10,7 +13,7 @@ pub struct Ambulatory {
|
|||||||
|
|
||||||
#[derive(Bundle)]
|
#[derive(Bundle)]
|
||||||
pub struct Citizen {
|
pub struct Citizen {
|
||||||
walker: Ambulatory,
|
walkness: Ambulatory,
|
||||||
sprite: Sprite,
|
sprite: Sprite,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
}
|
}
|
||||||
@@ -18,9 +21,9 @@ pub struct Citizen {
|
|||||||
impl Citizen {
|
impl Citizen {
|
||||||
pub fn new(asset_server: &Res<AssetServer>, position: Vec3) -> Self {
|
pub fn new(asset_server: &Res<AssetServer>, position: Vec3) -> Self {
|
||||||
Citizen {
|
Citizen {
|
||||||
walker: Ambulatory { speed: TILE_SIZE },
|
walkness: Ambulatory { speed: TILE_SIZE },
|
||||||
sprite: Sprite {
|
sprite: Sprite {
|
||||||
image: asset_server.load("character.png"),
|
image: asset_server.load("dorf.png"),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
|
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
|
||||||
@@ -30,29 +33,66 @@ impl Citizen {
|
|||||||
|
|
||||||
pub fn citizen_movement(mut query: Query<(&Ambulatory, &mut Transform), With<Ambulatory>>) {
|
pub fn citizen_movement(mut query: Query<(&Ambulatory, &mut Transform), With<Ambulatory>>) {
|
||||||
for (citizen, mut transform) in query.iter_mut() {
|
for (citizen, mut transform) in query.iter_mut() {
|
||||||
if random::<f32>() < 0.66666 {
|
// Skip processing if the random check fails
|
||||||
|
if rand::random::<f32>() >= 0.66666 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let mut direction = Vec2::ZERO;
|
|
||||||
|
|
||||||
direction.y += rand::random::<f32>();
|
// Generate random directions
|
||||||
direction.y -= rand::random::<f32>();
|
let direction_x = (rand::random::<f32>() - rand::random::<f32>()).round();
|
||||||
direction.x -= rand::random::<f32>();
|
let direction_y = (rand::random::<f32>() - rand::random::<f32>()).round();
|
||||||
direction.x += rand::random::<f32>();
|
|
||||||
|
|
||||||
if direction.length() > 0.0 {
|
// Skip if there's no movement
|
||||||
direction.x = direction.x.round();
|
if direction_x == 0.0 && direction_y == 0.0 {
|
||||||
direction.y = direction.y.round();
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let movement = direction * citizen.speed;
|
// Calculate movement only once
|
||||||
transform.translation.x += movement.x;
|
let speed = citizen.speed;
|
||||||
transform.translation.y += movement.y;
|
transform.translation.x += direction_x * speed;
|
||||||
|
transform.translation.y += direction_y * speed;
|
||||||
|
|
||||||
if direction.x > 0.0 {
|
// Adjust scale for x direction
|
||||||
transform.scale.x = PIXEL_RATIO;
|
if direction_x != 0.0 {
|
||||||
} else if direction.x < 0.0 {
|
transform.scale.x = PIXEL_RATIO * direction_x.signum();
|
||||||
transform.scale.x = -PIXEL_RATIO;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn spawn_citizens(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
|
// Spawn a handful of citizens
|
||||||
|
for _ in 0..10 {
|
||||||
|
let x = rng.gen_range(-10.0..10.0);
|
||||||
|
let y = rng.gen_range(-10.0..10.0);
|
||||||
|
let position = Vec3::new(x, y, 0.0) * PIXEL_RATIO;
|
||||||
|
|
||||||
|
commands.spawn(Citizen::new(&asset_server, position));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_citizen_positions_for_chunks(
|
||||||
|
query: Query<&Transform, With<Ambulatory>>,
|
||||||
|
chunk_map: Res<tilemap::ChunkMap>,
|
||||||
|
mut event_writer: EventWriter<tilemap::LoadChunkEvent>,
|
||||||
|
) {
|
||||||
|
for transform in query.iter() {
|
||||||
|
let position = transform.translation;
|
||||||
|
|
||||||
|
// Convert citizen position to chunk coordinates
|
||||||
|
let chunk_x =
|
||||||
|
(position.x / (tilemap::CHUNK_SIZE as f32 * constants::TILE_SIZE)).floor() as i32;
|
||||||
|
let chunk_y =
|
||||||
|
(position.y / (tilemap::CHUNK_SIZE as f32 * constants::TILE_SIZE)).floor() as i32;
|
||||||
|
|
||||||
|
let chunk_pos = IVec2::new(chunk_x, chunk_y);
|
||||||
|
|
||||||
|
// Load chunk if not already loaded
|
||||||
|
if !chunk_map.loaded_chunks.contains_key(&chunk_pos) {
|
||||||
|
event_writer.send(tilemap::LoadChunkEvent {
|
||||||
|
chunk_position: chunk_pos,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
pub const PIXEL_RATIO: f32 = 3.;
|
pub const PIXEL_RATIO: f32 = 1.;
|
||||||
pub const TILE_SIZE: f32 = 16.0 * PIXEL_RATIO;
|
pub const TILE_SIZE: f32 = 16.0 * PIXEL_RATIO;
|
||||||
|
|||||||
+51
-1
@@ -1,4 +1,7 @@
|
|||||||
|
use std::process::exit;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
use camera::PanningCamera;
|
||||||
|
|
||||||
mod camera;
|
mod camera;
|
||||||
mod citizen;
|
mod citizen;
|
||||||
@@ -7,6 +10,7 @@ mod cursor;
|
|||||||
mod game;
|
mod game;
|
||||||
mod item;
|
mod item;
|
||||||
mod tile;
|
mod tile;
|
||||||
|
mod tilemap;
|
||||||
mod tiles;
|
mod tiles;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -24,12 +28,14 @@ fn main() {
|
|||||||
.set(ImagePlugin::default_nearest()),
|
.set(ImagePlugin::default_nearest()),
|
||||||
)
|
)
|
||||||
.insert_resource(ClearColor(Color::srgb(0.0, 0.0, 0.0)))
|
.insert_resource(ClearColor(Color::srgb(0.0, 0.0, 0.0)))
|
||||||
|
.add_plugins(tilemap::TilemapPlugin)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Startup,
|
Startup,
|
||||||
(
|
(
|
||||||
game::setup_level,
|
setup_initial_chunks,
|
||||||
camera::spawn_panning_camera,
|
camera::spawn_panning_camera,
|
||||||
cursor::setup_cursor,
|
cursor::setup_cursor,
|
||||||
|
citizen::spawn_citizens, // New citizen spawning system
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
@@ -47,6 +53,8 @@ fn main() {
|
|||||||
camera::camera_movement,
|
camera::camera_movement,
|
||||||
citizen::citizen_movement,
|
citizen::citizen_movement,
|
||||||
cursor::move_cursor,
|
cursor::move_cursor,
|
||||||
|
check_camera_position_for_chunks,
|
||||||
|
citizen::check_citizen_positions_for_chunks, // New citizen-based chunk loading system
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.init_resource::<tile::CameraMoved>()
|
.init_resource::<tile::CameraMoved>()
|
||||||
@@ -60,3 +68,45 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn setup_initial_chunks(mut event_writer: EventWriter<tilemap::LoadChunkEvent>) {
|
||||||
|
// Spawn a 3x3 grid of chunks around the origin
|
||||||
|
for x in -1..=1 {
|
||||||
|
for y in -1..=1 {
|
||||||
|
println!("setup_initial_chunks: x = {}, y = {}", x, y);
|
||||||
|
event_writer.send(tilemap::LoadChunkEvent {
|
||||||
|
chunk_position: IVec2::new(x, y),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New system to check camera position and load nearby chunks
|
||||||
|
fn check_camera_position_for_chunks(
|
||||||
|
camera_query: Query<&Transform, With<Camera>>,
|
||||||
|
chunk_map: Res<tilemap::ChunkMap>,
|
||||||
|
mut event_writer: EventWriter<tilemap::LoadChunkEvent>,
|
||||||
|
) {
|
||||||
|
let camera_transform = camera_query.single();
|
||||||
|
let camera_pos = camera_transform.translation;
|
||||||
|
|
||||||
|
// Convert camera position to chunk coordinates
|
||||||
|
let chunk_x =
|
||||||
|
(camera_pos.x / (tilemap::CHUNK_SIZE as f32 * constants::TILE_SIZE)).floor() as i32;
|
||||||
|
let chunk_y =
|
||||||
|
(camera_pos.y / (tilemap::CHUNK_SIZE as f32 * constants::TILE_SIZE)).floor() as i32;
|
||||||
|
|
||||||
|
// Check a 3x3 area around the camera's current chunk
|
||||||
|
for x in (chunk_x - 1)..=(chunk_x + 1) {
|
||||||
|
for y in (chunk_y - 1)..=(chunk_y + 1) {
|
||||||
|
let chunk_pos = IVec2::new(x, y);
|
||||||
|
|
||||||
|
// Only spawn new chunks if they haven't been loaded yet
|
||||||
|
if !chunk_map.loaded_chunks.contains_key(&chunk_pos) {
|
||||||
|
event_writer.send(tilemap::LoadChunkEvent {
|
||||||
|
chunk_position: chunk_pos,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
-97
@@ -1,11 +1,8 @@
|
|||||||
use crate::constants::TILE_SIZE;
|
use crate::constants::TILE_SIZE;
|
||||||
use crate::game;
|
use crate::game;
|
||||||
use crate::item::Item;
|
|
||||||
use bevy::ecs::system::ParamSet;
|
use bevy::ecs::system::ParamSet;
|
||||||
use bevy::math::ivec3;
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::process::exit;
|
|
||||||
|
|
||||||
#[derive(Component, Clone)]
|
#[derive(Component, Clone)]
|
||||||
#[require(Sprite)]
|
#[require(Sprite)]
|
||||||
@@ -46,9 +43,6 @@ impl Default for FixtureTile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Clone)]
|
|
||||||
pub struct ConnectedTexture {}
|
|
||||||
|
|
||||||
#[derive(Resource, Default)]
|
#[derive(Resource, Default)]
|
||||||
pub struct CameraMoved(pub bool);
|
pub struct CameraMoved(pub bool);
|
||||||
|
|
||||||
@@ -211,24 +205,6 @@ pub fn tile_sprite_generate_occlusion_map(
|
|||||||
let pos = transform.translation.as_ivec3() - IVec3::new(0, 0, 1);
|
let pos = transform.translation.as_ivec3() - IVec3::new(0, 0, 1);
|
||||||
fixture.visible_range = calculate_visibility(pos, &tilemap);
|
fixture.visible_range = calculate_visibility(pos, &tilemap);
|
||||||
});
|
});
|
||||||
|
|
||||||
use std::time::Instant;
|
|
||||||
let total: Instant = Instant::now();
|
|
||||||
|
|
||||||
for i in 0..1000000 {
|
|
||||||
let now: Instant = Instant::now();
|
|
||||||
for x in -1..=1 {
|
|
||||||
for y in -1..=1 {
|
|
||||||
for z in 0..=1 {
|
|
||||||
tilemap.floors.get(&IVec3::new(x, y, z));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let elapsed = now.elapsed();
|
|
||||||
}
|
|
||||||
let elapsed = total.elapsed();
|
|
||||||
print!("{:.4?}, ", elapsed / 1000000);
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_tile_visibility(
|
pub fn update_tile_visibility(
|
||||||
@@ -270,79 +246,6 @@ pub fn update_tile_visibility(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_connected_texture(floor_tiles: &HashMap<(i32, i32, i32), (bool, u32)>) -> Vec<String> {
|
|
||||||
let mut textures = vec![];
|
|
||||||
|
|
||||||
for ((x, y, z), (is_floor, tile_id)) in floor_tiles.iter() {
|
|
||||||
let mut is_wall = false;
|
|
||||||
|
|
||||||
for x_offset in -1..=1 {
|
|
||||||
for y_offset in -1..=1 {
|
|
||||||
for z_offset in 0..=1 {
|
|
||||||
if x_offset == 0 && y_offset == 0 && z_offset == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let neighbor_pos = (x + x_offset, y + y_offset, z + z_offset);
|
|
||||||
|
|
||||||
if let Some((_, neighbor_id)) = floor_tiles.get(&neighbor_pos) {
|
|
||||||
if *neighbor_id > 0 {
|
|
||||||
// assuming wall IDs are greater than 0
|
|
||||||
is_wall = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match (is_floor, is_wall) {
|
|
||||||
(true, false) => textures.push("floor".to_string()), // or some other floor texture
|
|
||||||
(false, true) => textures.push("wall".to_string()), // or some other wall texture
|
|
||||||
_ => panic!("Unexpected tile state"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
textures
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tile_item_sprite_update(
|
|
||||||
time: Res<Time>,
|
|
||||||
mut query_tile: Query<(Entity, &Children, &mut TileState)>,
|
|
||||||
mut query_item: Query<(&mut Visibility, &Item)>,
|
|
||||||
) {
|
|
||||||
for (_, children, mut state) in query_tile.iter_mut() {
|
|
||||||
state.timer.tick(time.delta());
|
|
||||||
if !state.timer.finished() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut visible_index: Option<usize> = None;
|
|
||||||
|
|
||||||
for (i, &child) in children.iter().enumerate() {
|
|
||||||
if let Ok((mut visibility, _)) = query_item.get_mut(child) {
|
|
||||||
if matches!(*visibility, Visibility::Visible) {
|
|
||||||
visible_index = Some(i);
|
|
||||||
*visibility = Visibility::Hidden;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let next_index = if let Some(current_index) = visible_index {
|
|
||||||
(current_index + 1) % children.len()
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(&next_child) = children.get(next_index) {
|
|
||||||
if let Ok((mut visibility, _)) = query_item.get_mut(next_child) {
|
|
||||||
*visibility = Visibility::Visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct TileState {
|
pub struct TileState {
|
||||||
pub timer: Timer,
|
pub timer: Timer,
|
||||||
|
|||||||
+192
@@ -0,0 +1,192 @@
|
|||||||
|
use crate::constants::TILE_SIZE;
|
||||||
|
use crate::tiles::{FixtureTilePrefab, FloorTilePrefab};
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use noise::{NoiseFn, Perlin};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::process::exit;
|
||||||
|
|
||||||
|
pub const CHUNK_SIZE: i32 = 8;
|
||||||
|
pub const CHUNK_HEIGHT: i32 = 200;
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
|
pub struct ChunkMap {
|
||||||
|
pub loaded_chunks: HashMap<IVec2, bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ChunkMap {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
loaded_chunks: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Event)]
|
||||||
|
pub struct LoadChunkEvent {
|
||||||
|
pub chunk_position: IVec2,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_chunk_system(mut commands: Commands) {
|
||||||
|
commands.insert_resource(ChunkMap::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_chunk_loading(
|
||||||
|
mut commands: Commands,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
mut events: EventReader<LoadChunkEvent>,
|
||||||
|
mut chunk_map: ResMut<ChunkMap>,
|
||||||
|
) {
|
||||||
|
let noise = Perlin::new(0);
|
||||||
|
|
||||||
|
for event in events.read() {
|
||||||
|
let chunk_pos = event.chunk_position;
|
||||||
|
// Skip if chunk is already loaded
|
||||||
|
if chunk_map.loaded_chunks.contains_key(&chunk_pos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark chunk as loaded
|
||||||
|
chunk_map.loaded_chunks.insert(chunk_pos, true);
|
||||||
|
|
||||||
|
// Calculate world space coordinates for chunk
|
||||||
|
let start_x = chunk_pos.x * CHUNK_SIZE;
|
||||||
|
let start_y = chunk_pos.y * CHUNK_SIZE;
|
||||||
|
|
||||||
|
let mut floor_positions = Vec::new();
|
||||||
|
|
||||||
|
// Generate tiles for this chunk
|
||||||
|
for local_y in 0..CHUNK_SIZE {
|
||||||
|
for local_x in 0..CHUNK_SIZE {
|
||||||
|
let world_x = start_x + local_x;
|
||||||
|
let world_y = start_y + local_y;
|
||||||
|
|
||||||
|
let noise_value_a =
|
||||||
|
noise.get([world_x as f64 * 0.01, world_y as f64 * 0.01]) * 1.25;
|
||||||
|
let noise_value_b =
|
||||||
|
noise.get([world_x as f64 * 0.05, world_y as f64 * 0.05]) * 0.25;
|
||||||
|
let combined_noise_value = noise_value_a + noise_value_b;
|
||||||
|
|
||||||
|
let noise_position = Vec3::new(
|
||||||
|
(world_x as f32 * TILE_SIZE).round(),
|
||||||
|
(world_y as f32 * TILE_SIZE).round(),
|
||||||
|
(combined_noise_value * 4.).round() as f32 * TILE_SIZE,
|
||||||
|
);
|
||||||
|
generate_vertical_slice(
|
||||||
|
&mut commands,
|
||||||
|
&asset_server,
|
||||||
|
world_x,
|
||||||
|
world_y,
|
||||||
|
&noise,
|
||||||
|
noise_position,
|
||||||
|
&mut floor_positions,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate fixtures after floor tiles
|
||||||
|
generate_fixtures_for_chunk(&mut commands, &asset_server, &floor_positions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_vertical_slice(
|
||||||
|
commands: &mut Commands,
|
||||||
|
asset_server: &Res<AssetServer>,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
noise: &Perlin,
|
||||||
|
noise_position: Vec3,
|
||||||
|
floor_positions: &mut Vec<(Vec3, &'static str)>,
|
||||||
|
) {
|
||||||
|
for z in -150..50 {
|
||||||
|
let position = Vec3::new(
|
||||||
|
(x as f32 * TILE_SIZE).round(),
|
||||||
|
(y as f32 * TILE_SIZE).round(),
|
||||||
|
(z as f32 * TILE_SIZE).round(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let floor_type = if noise_position.z > position.z {
|
||||||
|
if z < -15 {
|
||||||
|
let noise_value = noise.get([x as f64 * 0.05, y as f64 * 0.05, z as f64 * 0.05]);
|
||||||
|
if noise_value < -0.5 {
|
||||||
|
spawn_tile(commands, FloorTilePrefab::air(position, asset_server));
|
||||||
|
Some("air")
|
||||||
|
} else if noise_value < 0.8 {
|
||||||
|
spawn_tile(commands, FloorTilePrefab::rock(position, asset_server));
|
||||||
|
Some("rock")
|
||||||
|
} else {
|
||||||
|
spawn_tile(commands, FloorTilePrefab::dirt(position, asset_server));
|
||||||
|
Some("dirt")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spawn_tile(commands, FloorTilePrefab::dirt(position, asset_server));
|
||||||
|
Some("dirt")
|
||||||
|
}
|
||||||
|
} else if noise_position.z < position.z {
|
||||||
|
spawn_tile(commands, FloorTilePrefab::air(position, asset_server));
|
||||||
|
Some("air")
|
||||||
|
} else {
|
||||||
|
spawn_tile(commands, FloorTilePrefab::dirt(position, asset_server));
|
||||||
|
Some("dirt")
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(floor_type) = floor_type {
|
||||||
|
floor_positions.push((position, floor_type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_tile(commands: &mut Commands, bundle: impl Bundle) -> Entity {
|
||||||
|
commands.spawn(bundle).id()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_fixtures_for_chunk(
|
||||||
|
commands: &mut Commands,
|
||||||
|
asset_server: &Res<AssetServer>,
|
||||||
|
floor_positions: &[(Vec3, &str)],
|
||||||
|
) {
|
||||||
|
let floor_map: HashMap<(i32, i32, i32), &str> = floor_positions
|
||||||
|
.iter()
|
||||||
|
.map(|(pos, floor_type)| ((pos.x as i32, pos.y as i32, pos.z as i32), *floor_type))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for (position, _) in floor_positions {
|
||||||
|
let x = position.x as i32;
|
||||||
|
let y = position.y as i32;
|
||||||
|
let z = position.z as i32;
|
||||||
|
|
||||||
|
if let Some(&above_floor_type) = floor_map.get(&(x, y, z + TILE_SIZE as i32)) {
|
||||||
|
if above_floor_type == "air" {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let fixture_position = Vec3::new(position.x, position.y, position.z + 1.);
|
||||||
|
|
||||||
|
match above_floor_type {
|
||||||
|
"dirt" => {
|
||||||
|
commands.spawn(FixtureTilePrefab::dirt_wall(fixture_position, asset_server));
|
||||||
|
}
|
||||||
|
"rock" => {
|
||||||
|
commands.spawn(FixtureTilePrefab::rock_wall(fixture_position, asset_server));
|
||||||
|
}
|
||||||
|
"bedrock" => {
|
||||||
|
commands.spawn(FixtureTilePrefab::bedrock_wall(
|
||||||
|
fixture_position,
|
||||||
|
asset_server,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TilemapPlugin;
|
||||||
|
|
||||||
|
impl Plugin for TilemapPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.init_resource::<ChunkMap>()
|
||||||
|
.add_event::<LoadChunkEvent>()
|
||||||
|
.add_systems(Startup, setup_chunk_system)
|
||||||
|
.add_systems(Update, handle_chunk_loading);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user