global tilemap (ish)
This commit is contained in:
+5
-1
@@ -10,6 +10,7 @@ use rand::prelude::*;
|
||||
pub struct ZIndex(pub f32);
|
||||
|
||||
pub fn setup_level(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
println!("setup_level");
|
||||
setup_tilemap(&mut commands, &asset_server);
|
||||
|
||||
for x in -10..10 {
|
||||
@@ -164,7 +165,10 @@ fn setup_tilemap(commands: &mut Commands, asset_server: &Res<AssetServer>) {
|
||||
commands.spawn(FixtureTilePrefab::rock_wall(fixture_position, asset_server));
|
||||
}
|
||||
"bedrock" => {
|
||||
commands.spawn(FixtureTilePrefab::bedrock_wall(fixture_position, asset_server));
|
||||
commands.spawn(FixtureTilePrefab::bedrock_wall(
|
||||
fixture_position,
|
||||
asset_server,
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ fn main() {
|
||||
.add_systems(
|
||||
PostStartup,
|
||||
(
|
||||
tile::build_tile_map,
|
||||
tile::tile_sprite_generate_occlusion_map,
|
||||
tile::update_tile_visibility,
|
||||
)
|
||||
|
||||
+133
-104
@@ -2,8 +2,10 @@ use crate::constants::TILE_SIZE;
|
||||
use crate::game;
|
||||
use crate::item::Item;
|
||||
use bevy::ecs::system::ParamSet;
|
||||
use bevy::math::ivec3;
|
||||
use bevy::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
use std::process::exit;
|
||||
|
||||
#[derive(Component, Clone)]
|
||||
#[require(Sprite)]
|
||||
@@ -45,9 +47,7 @@ impl Default for FixtureTile {
|
||||
}
|
||||
|
||||
#[derive(Component, Clone)]
|
||||
pub struct ConnectedTexture {
|
||||
|
||||
}
|
||||
pub struct ConnectedTexture {}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct CameraMoved(pub bool);
|
||||
@@ -73,136 +73,162 @@ pub fn camera_z_movement(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct TileMap {
|
||||
pub floors: HashMap<IVec3, (u32, bool, bool, u8, [u32; 8])>,
|
||||
pub fixtures: HashMap<IVec3, (u32, bool, [u32; 8])>,
|
||||
}
|
||||
|
||||
pub fn build_tile_map(
|
||||
mut commands: Commands,
|
||||
query1: Query<(&Transform, &FloorTile)>,
|
||||
query2: Query<(&Transform, &FixtureTile)>,
|
||||
) {
|
||||
println!("build_tile_map");
|
||||
let mut floor_tile_map = TileMap::default();
|
||||
for (transform, floor) in query1.iter() {
|
||||
floor_tile_map.floors.insert(
|
||||
transform.translation.as_ivec3(),
|
||||
(
|
||||
floor.id,
|
||||
floor.opaque,
|
||||
floor.walkable,
|
||||
floor.astar_weight,
|
||||
floor.visible_range,
|
||||
),
|
||||
);
|
||||
}
|
||||
for (transform, fixture) in query2.iter() {
|
||||
floor_tile_map.fixtures.insert(
|
||||
transform.translation.as_ivec3(),
|
||||
(fixture.id, fixture.solid, fixture.visible_range),
|
||||
);
|
||||
}
|
||||
commands.insert_resource(floor_tile_map);
|
||||
}
|
||||
|
||||
pub fn tile_sprite_generate_occlusion_map(
|
||||
tilemap: Res<TileMap>,
|
||||
mut query_set: ParamSet<(
|
||||
Query<(&Transform, &FloorTile)>,
|
||||
Query<(&Transform, &FixtureTile)>,
|
||||
Query<(&mut FloorTile, &Transform)>,
|
||||
Query<(&mut FixtureTile, &Transform)>,
|
||||
)>,
|
||||
) {
|
||||
// Create the tile map using floor query
|
||||
let floor_tile_map: HashMap<(i32, i32, i32), (bool, u32)> = {
|
||||
let mut map = HashMap::new();
|
||||
println!("tile_sprite_generate_occlusion_map");
|
||||
|
||||
query_set.p0().iter().for_each(|(transform, tile)| {
|
||||
map.insert(
|
||||
(
|
||||
transform.translation.x as i32,
|
||||
transform.translation.y as i32,
|
||||
transform.translation.z as i32,
|
||||
),
|
||||
(tile.opaque, tile.id),
|
||||
);
|
||||
});
|
||||
map
|
||||
};
|
||||
// Create the tile map using fixture query
|
||||
let fixture_tile_map: HashMap<(i32, i32, i32), (bool, u32)> = {
|
||||
let mut map = HashMap::new();
|
||||
|
||||
query_set.p1().iter().for_each(|(transform, tile)| {
|
||||
map.insert(
|
||||
(
|
||||
transform.translation.x as i32,
|
||||
transform.translation.y as i32,
|
||||
transform.translation.z as i32,
|
||||
),
|
||||
(tile.solid, tile.id),
|
||||
);
|
||||
});
|
||||
map
|
||||
};
|
||||
let tile_size = TILE_SIZE as i32;
|
||||
|
||||
// Helper function to calculate visibility
|
||||
let calculate_visibility =
|
||||
|pos: (i32, i32, i32), tile_map: &HashMap<(i32, i32, i32), (bool, u32)>| {
|
||||
let mut visible_range = [0u32; 8];
|
||||
let calculate_visibility = |pos: IVec3, tilemap: &TileMap| {
|
||||
let mut visible_range = [0u32; 8];
|
||||
|
||||
for mut camera_z in -150..100 {
|
||||
camera_z *= tile_size;
|
||||
let mut is_visible = false;
|
||||
for mut camera_z in -150..100 {
|
||||
camera_z *= tile_size;
|
||||
let mut is_visible = false;
|
||||
|
||||
if pos.2 > camera_z {
|
||||
continue;
|
||||
}
|
||||
if pos.z > camera_z {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut is_occluded = false;
|
||||
let mut is_occluded = false;
|
||||
|
||||
'vertical_check: for z_offset in 1..=35 {
|
||||
// check above
|
||||
let above_pos = (pos.0, pos.1, pos.2 + (z_offset * tile_size));
|
||||
if above_pos.2 <= camera_z {
|
||||
if let Some(&(is_opaque, _)) = tile_map.get(&above_pos) {
|
||||
if is_opaque {
|
||||
is_occluded = true;
|
||||
break 'vertical_check;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break 'vertical_check;
|
||||
}
|
||||
}
|
||||
|
||||
if !is_occluded {
|
||||
let base_pos = (pos.0, pos.1, pos.2);
|
||||
'neighbor_check: 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 = (
|
||||
base_pos.0 + x_offset * tile_size,
|
||||
base_pos.1 + y_offset * tile_size,
|
||||
base_pos.2 + z_offset * tile_size,
|
||||
);
|
||||
if let Some(&(_, id)) = tile_map.get(&neighbor_pos) {
|
||||
if id == 0 {
|
||||
is_visible = true;
|
||||
break 'neighbor_check;
|
||||
}
|
||||
}
|
||||
}
|
||||
'vertical_check: for z_offset in 1..=35 {
|
||||
// check above
|
||||
let above_pos = IVec3::new(pos.x, pos.y, pos.z + (z_offset * tile_size));
|
||||
if above_pos.z <= camera_z {
|
||||
// Check both floors and fixtures for occlusion
|
||||
if let Some(&(_, opaque, _, _, _)) = tilemap.floors.get(&above_pos) {
|
||||
if opaque {
|
||||
is_occluded = true;
|
||||
break 'vertical_check;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if is_visible {
|
||||
let z2 = ((camera_z / tile_size) + 150) as usize;
|
||||
visible_range[z2 / 32] |= 1 << ((z2 % 32) as u32);
|
||||
if let Some(&(_, solid, _)) = tilemap.fixtures.get(&above_pos) {
|
||||
if solid {
|
||||
is_occluded = true;
|
||||
break 'vertical_check;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break 'vertical_check;
|
||||
}
|
||||
}
|
||||
|
||||
visible_range
|
||||
};
|
||||
if !is_occluded {
|
||||
'neighbor_check: 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 = IVec3::new(
|
||||
pos.x + x_offset * tile_size,
|
||||
pos.y + y_offset * tile_size,
|
||||
pos.z + z_offset * tile_size,
|
||||
);
|
||||
|
||||
// Check both floors and fixtures for visibility
|
||||
if let Some(&(id, _, _, _, _)) = tilemap.floors.get(&neighbor_pos) {
|
||||
if id == 0 {
|
||||
is_visible = true;
|
||||
break 'neighbor_check;
|
||||
}
|
||||
}
|
||||
if let Some(&(id, _, _)) = tilemap.fixtures.get(&neighbor_pos) {
|
||||
if id == 0 {
|
||||
is_visible = true;
|
||||
break 'neighbor_check;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if is_visible {
|
||||
let z2 = ((camera_z / tile_size) + 150) as usize;
|
||||
visible_range[z2 / 32] |= 1 << ((z2 % 32) as u32);
|
||||
}
|
||||
}
|
||||
|
||||
visible_range
|
||||
};
|
||||
|
||||
// Update floor tiles
|
||||
query_set
|
||||
.p2()
|
||||
.p0()
|
||||
.par_iter_mut()
|
||||
.for_each(|(mut tile, transform)| {
|
||||
let pos = (
|
||||
transform.translation.x as i32,
|
||||
transform.translation.y as i32,
|
||||
transform.translation.z as i32,
|
||||
);
|
||||
tile.visible_range = calculate_visibility(pos, &floor_tile_map);
|
||||
let pos = transform.translation.as_ivec3();
|
||||
tile.visible_range = calculate_visibility(pos, &tilemap);
|
||||
});
|
||||
|
||||
// Update fixture tiles
|
||||
query_set
|
||||
.p3()
|
||||
.p1()
|
||||
.par_iter_mut()
|
||||
.for_each(|(mut fixture, transform)| {
|
||||
let pos = (
|
||||
transform.translation.x as i32,
|
||||
transform.translation.y as i32,
|
||||
transform.translation.z as i32 - 1,
|
||||
);
|
||||
fixture.visible_range = calculate_visibility(pos, &fixture_tile_map);
|
||||
let pos = transform.translation.as_ivec3() - IVec3::new(0, 0, 1);
|
||||
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(
|
||||
@@ -212,6 +238,8 @@ pub fn update_tile_visibility(
|
||||
Query<(&FixtureTile, &mut Visibility)>,
|
||||
)>,
|
||||
) {
|
||||
println!("update_tile_visibility");
|
||||
|
||||
let z_index = (z_index.0 as i32 + 150) as usize;
|
||||
|
||||
// Update floor visibility
|
||||
@@ -258,7 +286,8 @@ fn calculate_connected_texture(floor_tiles: &HashMap<(i32, i32, i32), (bool, u32
|
||||
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
|
||||
if *neighbor_id > 0 {
|
||||
// assuming wall IDs are greater than 0
|
||||
is_wall = true;
|
||||
break;
|
||||
}
|
||||
@@ -269,7 +298,7 @@ fn calculate_connected_texture(floor_tiles: &HashMap<(i32, i32, i32), (bool, u32
|
||||
|
||||
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
|
||||
(false, true) => textures.push("wall".to_string()), // or some other wall texture
|
||||
_ => panic!("Unexpected tile state"),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user