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