batch sprite 1

This commit is contained in:
StephenAdamson
2025-02-08 00:23:49 +00:00
parent 4089851734
commit 4ba6fecc27
6 changed files with 151 additions and 106 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

+5 -8
View File
@@ -34,10 +34,7 @@ impl Citizen {
use crate::constants::TILE_SIZE;
use crate::tile::TileMap;
use rand::{
seq::{IndexedRandom, SliceRandom},
Rng,
};
use rand::{seq::IndexedRandom, Rng};
use std::{
collections::{BinaryHeap, HashMap, HashSet},
process::exit,
@@ -100,8 +97,8 @@ pub fn update_citizen_wandering_targets(
let chunk_x = chunk_pos.x * CHUNK_SIZE;
let chunk_y = chunk_pos.y * CHUNK_SIZE;
let target_x = chunk_x + rng.gen_range(0..CHUNK_SIZE);
let target_y = chunk_y + rng.gen_range(0..CHUNK_SIZE);
let target_x = chunk_x + rng.random_range(0..CHUNK_SIZE);
let target_y = chunk_y + rng.random_range(0..CHUNK_SIZE);
// Get height at position
let surface_height = 0;
@@ -344,8 +341,8 @@ pub fn spawn_citizens(mut commands: Commands, asset_server: Res<AssetServer>) {
// Spawn a handful of citizens
for _ in 0..5 {
let x: f32 = rng.gen_range(-8.0..8.0);
let y: f32 = rng.gen_range(-8.0..8.0);
let x: f32 = rng.random_range(-8.0..8.0);
let y: f32 = rng.random_range(-8.0..8.0);
let mut position = Vec3::new(x.round(), y.round(), 30.0) * TILE_SIZE;
position.z += 0.1;
+19 -22
View File
@@ -20,14 +20,16 @@ use bevy::diagnostic::FrameTimeDiagnosticsPlugin;
fn main() {
App::new()
.insert_resource(game::ZIndex(0.0))
.add_systems(Startup, tiles::initialize_textures)
.insert_resource(tiles::CurrentWorldSpriteState {
state: tiles::WorldSpriteState::Inactive,
})
.add_systems(PreStartup, tiles::initialize_textures)
.add_plugins(
DefaultPlugins
.set(WindowPlugin {
primary_window: Some(Window {
title: String::from("Dorf"),
resizable: false,
mode: WindowMode::BorderlessFullscreen(MonitorSelection::Primary),
// mode: WindowMode::BorderlessFullscreen(MonitorSelection::Primary),
..Default::default()
}),
..Default::default()
@@ -51,29 +53,24 @@ fn main() {
(
// camera::camera_movement,
cursor::move_cursor,
// citizen::check_citizen_positions_for_chunks,
tiles::build_world_sprites,
tile::update_tile_visibility.run_if(|cwss: Res<tiles::CurrentWorldSpriteState>| {
cwss.state == tiles::WorldSpriteState::RenderReady
}),
),
)
.init_resource::<tile::CameraMoved>()
.add_systems(
Update,
(
// tile::camera_z_movement,
tile::update_tile_visibility
.run_if(|camera_moved: Res<tile::CameraMoved>| camera_moved.0),
// log_fps_system,
),
)
// .add_systems(
// Update,
// (
// tile::camera_z_movement,
// tile::update_tile_visibility
// .run_if(|camera_moved: Res<tile::CameraMoved>| camera_moved.0),
// log_fps_system,
// ),
// )
.init_resource::<DiagnosticsRecorder>()
.add_systems(
Update,
(
start_recording_system,
record_diagnostics_system,
tile::update_tile_visibility
.run_if(|camera_moved: Res<tile::CameraMoved>| camera_moved.0),
),
)
.add_systems(Update, (start_recording_system, record_diagnostics_system))
.run();
}
+2 -2
View File
@@ -1,10 +1,9 @@
use crate::game;
use crate::{game, tiles};
use bevy::ecs::system::ParamSet;
use bevy::prelude::*;
use std::collections::HashMap;
#[derive(Component, Clone)]
#[require(Sprite)]
pub struct FloorTile {
pub id: u32,
pub opaque: bool,
@@ -76,6 +75,7 @@ pub struct TileMap {
pub fixture_tiles: HashMap<IVec3, (u32, bool, [u32; 8])>,
}
//TODO, redo
pub fn update_tile_visibility(
z_index: ResMut<game::ZIndex>,
mut query_set: ParamSet<(
+14 -14
View File
@@ -1,7 +1,8 @@
use crate::constants::{ITILE_SIZE, TILE_SIZE};
use crate::tile::{self, FixtureTile, FloorTile, NeedsOccluded, TileMap};
use crate::tiles::{FixtureTilePrefab, FloorTilePrefab, Textures};
use crate::tiles::{self, FixtureTilePrefab, FloorTilePrefab, Textures};
use bevy::prelude::*;
use bevy::text::cosmic_text::ttf_parser::gpos::PositioningSubtable;
use noise::{NoiseFn, Perlin};
use std::collections::HashMap;
@@ -38,6 +39,7 @@ pub fn handle_tile_occlusion_updates(
Query<(&mut FixtureTile, &Transform, &mut NeedsOccluded)>,
Query<(Entity, &mut NeedsOccluded)>,
)>,
mut cwss: ResMut<tiles::CurrentWorldSpriteState>,
) {
query_set
.p0()
@@ -68,6 +70,7 @@ pub fn handle_tile_occlusion_updates(
commands.entity(entity).remove::<NeedsOccluded>();
}
}
cwss.state = tiles::WorldSpriteState::WaitingForRender;
}
pub fn calculate_visibility(pos: IVec3, tilemap: &TileMap) -> [u32; 8] {
@@ -211,19 +214,19 @@ fn handle_chunk_loading(
z as f64 * 0.05,
]);
if noise_value < -0.5 {
FloorTilePrefab::air(position, &textures).spawn(&mut commands);
FloorTilePrefab::air(position).spawn(&mut commands);
tilemap
.floor_tiles
.insert(pos_ivec, (0, false, true, 0, [0; 8])); // Air tile
floor_positions.push((position, "air"));
} else if noise_value < 0.8 {
FloorTilePrefab::rock(position, &textures).spawn(&mut commands);
FloorTilePrefab::rock(position).spawn(&mut commands);
tilemap
.floor_tiles
.insert(pos_ivec, (2, true, false, 50, [0; 8])); // Rock tile
floor_positions.push((position, "rock"));
} else {
FloorTilePrefab::dirt(position, &textures).spawn(&mut commands);
FloorTilePrefab::dirt(position).spawn(&mut commands);
tilemap
.floor_tiles
.insert(pos_ivec, (1, true, true, 85, [0; 8])); // Dirt tile
@@ -233,20 +236,20 @@ fn handle_chunk_loading(
if (generate_surface_noise(world_x, world_y) * TILE_SIZE).round()
<= position.z + TILE_SIZE
{
FloorTilePrefab::grass(position, &textures).spawn(&mut commands);
FloorTilePrefab::grass(position).spawn(&mut commands);
tilemap
.floor_tiles
.insert(pos_ivec, (1, true, true, 100, [0; 8])); // Dirt tile (grass)
floor_positions.push((position, "dirt"));
} else {
FloorTilePrefab::dirt(position, &textures).spawn(&mut commands);
FloorTilePrefab::dirt(position).spawn(&mut commands);
tilemap
.floor_tiles
.insert(pos_ivec, (1, true, true, 85, [0; 8])); // Dirt tile
floor_positions.push((position, "dirt"));
}
} else {
FloorTilePrefab::air(position, &textures).spawn(&mut commands);
FloorTilePrefab::air(position).spawn(&mut commands);
tilemap
.floor_tiles
.insert(pos_ivec, (0, false, true, 0, [0; 8])); // Air tile
@@ -263,17 +266,17 @@ fn handle_chunk_loading(
match *floor_type {
"dirt" => {
FixtureTilePrefab::dirt_wall(above_pos, &textures).spawn(&mut commands);
FixtureTilePrefab::dirt_wall(above_pos).spawn(&mut commands);
tilemap.fixture_tiles.insert(above_ivec, (1, true, [0; 8]));
// Dirt wall
}
"rock" => {
FixtureTilePrefab::rock_wall(above_pos, &textures).spawn(&mut commands);
FixtureTilePrefab::rock_wall(above_pos).spawn(&mut commands);
tilemap.fixture_tiles.insert(above_ivec, (2, true, [0; 8]));
// Rock wall
}
"bedrock" => {
FixtureTilePrefab::bedrock_wall(above_pos, &textures).spawn(&mut commands);
FixtureTilePrefab::bedrock_wall(above_pos).spawn(&mut commands);
tilemap.fixture_tiles.insert(above_ivec, (3, true, [0; 8]));
// Bedrock wall
}
@@ -310,9 +313,6 @@ impl Plugin for TilemapPlugin {
)
.chain(),
)
.add_systems(
FixedUpdate,
(handle_chunk_loading, handle_tile_occlusion_updates).chain(),
);
.add_systems(FixedUpdate, (handle_chunk_loading).chain());
}
}
+111 -60
View File
@@ -1,47 +1,133 @@
use std::process::exit;
use crate::constants::*;
use crate::tile::{FixtureTile, FloorTile, NeedsOccluded, TileState};
use bevy::prelude::*;
use bevy::utils::HashMap;
use bevy::{prelude::*, transform};
#[derive(Resource)]
pub struct Textures {
pub handles: HashMap<String, Handle<Image>>,
}
#[derive(Resource)]
pub struct TextureIDs {
pub refs: HashMap<u32, String>,
}
const FLOOR_ID_OFFSET: u32 = 0;
const FIXTURE_ID_OFFSET: u32 = 500000;
pub const DEFAULT_TEXTURE: &str = "default.png";
const GRASS_FLOOR_PATH: &str = "grass_floor.png";
const DIRT_FLOOR_PATH: &str = "dirt_floor.png";
const ROCK_FLOOR_PATH: &str = "rock_floor.png";
const BEDROCK_FLOOR_PATH: &str = "bedrock_floor.png";
const SKY_PATH: &str = "sky.png";
const DIRT_WALL_PATH: &str = "dirt_wall.png";
const ROCK_WALL_PATH: &str = "rock_wall.png";
const BEDROCK_WALL_PATH: &str = "bedrock_wall.png";
pub fn initialize_textures(mut commands: Commands, asset_server: Res<AssetServer>) {
let mut textures = HashMap::new();
let mut textures: HashMap<String, Handle<Image>> = HashMap::new();
let mut texture_ids: HashMap<u32, String> = HashMap::new();
texture_ids.insert(u32::MAX, DEFAULT_TEXTURE.to_string());
texture_ids.insert(FLOOR_ID_OFFSET + 0, SKY_PATH.to_string());
textures.insert(SKY_PATH.to_string(), asset_server.load(SKY_PATH));
texture_ids.insert(FLOOR_ID_OFFSET + 1, GRASS_FLOOR_PATH.to_string());
textures.insert(
"grass_floor".to_string(),
asset_server.load("grass_floor.png"),
GRASS_FLOOR_PATH.to_string(),
asset_server.load(GRASS_FLOOR_PATH),
);
texture_ids.insert(FLOOR_ID_OFFSET + 2, DIRT_FLOOR_PATH.to_string());
textures.insert(
"dirt_floor".to_string(),
asset_server.load("dirt_floor.png"),
DIRT_FLOOR_PATH.to_string(),
asset_server.load(DIRT_FLOOR_PATH),
);
texture_ids.insert(FLOOR_ID_OFFSET + 3, ROCK_FLOOR_PATH.to_string());
textures.insert(
"rock_floor".to_string(),
asset_server.load("rock_floor.png"),
ROCK_FLOOR_PATH.to_string(),
asset_server.load(ROCK_FLOOR_PATH),
);
texture_ids.insert(FLOOR_ID_OFFSET + 4, BEDROCK_FLOOR_PATH.to_string());
textures.insert(
"bedrock_floor".to_string(),
asset_server.load("bedrock_floor.png"),
BEDROCK_FLOOR_PATH.to_string(),
asset_server.load(BEDROCK_FLOOR_PATH),
);
textures.insert("sky".to_string(), asset_server.load("sky.png"));
textures.insert("dirt_wall".to_string(), asset_server.load("dirt_wall.png"));
textures.insert("rock_wall".to_string(), asset_server.load("rock_wall.png"));
texture_ids.insert(FIXTURE_ID_OFFSET + 1, DIRT_WALL_PATH.to_string());
textures.insert(
"bedrock_wall".to_string(),
asset_server.load("bedrock_wall.png"),
DIRT_WALL_PATH.to_string(),
asset_server.load(DIRT_WALL_PATH),
);
texture_ids.insert(FIXTURE_ID_OFFSET + 2, ROCK_WALL_PATH.to_string());
textures.insert(
ROCK_WALL_PATH.to_string(),
asset_server.load(ROCK_WALL_PATH),
);
texture_ids.insert(FIXTURE_ID_OFFSET + 3, BEDROCK_WALL_PATH.to_string());
textures.insert(
BEDROCK_WALL_PATH.to_string(),
asset_server.load(BEDROCK_WALL_PATH),
);
// Insert the textures resource into the world
commands.insert_resource(Textures { handles: textures });
commands.insert_resource(TextureIDs { refs: texture_ids });
}
#[derive(Debug, PartialEq)]
pub enum WorldSpriteState {
Inactive,
WaitingForRender,
InProgress,
RenderReady,
}
#[derive(Resource)]
pub struct CurrentWorldSpriteState {
pub state: WorldSpriteState,
}
use std::time::Instant;
pub fn build_world_sprites(
mut query: Query<(&FloorTile, &Transform)>,
mut commands: Commands,
mut cwss: ResMut<CurrentWorldSpriteState>,
textures: Res<Textures>,
texture_ids: Res<TextureIDs>,
) {
if cwss.state != WorldSpriteState::WaitingForRender {
return;
}
let now = Instant::now();
if cwss.state == WorldSpriteState::WaitingForRender {
cwss.state = WorldSpriteState::InProgress;
// async/thread this so we don't block the main thread
for (floortile, transform) in query.iter_mut() {
let id = floortile.id;
let texture_id = texture_ids.refs.get(&id).unwrap();
let texture = textures.handles.get(texture_id).unwrap();
let sprite = Sprite {
image: texture.clone(),
..Default::default()
};
commands.spawn((sprite, *transform));
}
cwss.state = WorldSpriteState::RenderReady;
}
println!("{:?}", cwss.state);
let elapsed = now.elapsed();
println!("Elapsed: {:.2?}", elapsed);
// exit(0);
}
#[derive(Bundle)]
pub struct FloorTilePrefab {
transform: Transform,
sprite: Sprite,
tile: FloorTile,
tile_state: TileState,
visibility: Visibility,
@@ -49,13 +135,9 @@ pub struct FloorTilePrefab {
}
impl FloorTilePrefab {
pub fn grass(position: Vec3, textures: &Res<Textures>) -> Self {
pub fn grass(position: Vec3) -> Self {
FloorTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
sprite: Sprite {
image: textures.handles.get("grass_floor").unwrap().clone(),
..Default::default()
},
tile: FloorTile {
id: 1,
astar_weight: 100,
@@ -71,13 +153,9 @@ impl FloorTilePrefab {
}
}
pub fn dirt(position: Vec3, textures: &Res<Textures>) -> Self {
pub fn dirt(position: Vec3) -> Self {
FloorTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
sprite: Sprite {
image: textures.handles.get("dirt_floor").unwrap().clone(),
..Default::default()
},
tile: FloorTile {
id: 2,
astar_weight: 85,
@@ -93,13 +171,9 @@ impl FloorTilePrefab {
}
}
pub fn rock(position: Vec3, textures: &Res<Textures>) -> Self {
pub fn rock(position: Vec3) -> Self {
FloorTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
sprite: Sprite {
image: textures.handles.get("rock_floor").unwrap().clone(),
..Default::default()
},
tile: FloorTile {
id: 3,
astar_weight: 50,
@@ -115,13 +189,9 @@ impl FloorTilePrefab {
}
}
pub fn air(position: Vec3, textures: &Res<Textures>) -> Self {
pub fn air(position: Vec3) -> Self {
FloorTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
sprite: Sprite {
image: textures.handles.get("sky").unwrap().clone(),
..Default::default()
},
tile: FloorTile {
id: 0,
opaque: false,
@@ -138,13 +208,9 @@ impl FloorTilePrefab {
}
}
pub fn bedrock(position: Vec3, textures: &Res<Textures>) -> Self {
pub fn bedrock(position: Vec3) -> Self {
FloorTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
sprite: Sprite {
image: textures.handles.get("bedrock_floor").unwrap().clone(),
..Default::default()
},
tile: FloorTile {
id: 4,
astar_weight: 150,
@@ -164,7 +230,6 @@ impl FloorTilePrefab {
commands.spawn((
self.tile,
self.transform,
self.sprite,
self.tile_state,
self.visibility,
self.needs_occluded,
@@ -175,22 +240,17 @@ impl FloorTilePrefab {
#[derive(Bundle)]
pub struct FixtureTilePrefab {
transform: Transform,
sprite: Sprite,
tile: FixtureTile,
visibility: Visibility,
needs_occluded: NeedsOccluded,
}
impl FixtureTilePrefab {
pub fn dirt_wall(position: Vec3, textures: &Res<Textures>) -> Self {
pub fn dirt_wall(position: Vec3) -> Self {
FixtureTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
sprite: Sprite {
image: textures.handles.get("dirt_wall").unwrap().clone(),
..Default::default()
},
tile: FixtureTile {
id: 1,
id: FIXTURE_ID_OFFSET + 1,
..Default::default()
},
visibility: Visibility::Hidden,
@@ -200,13 +260,9 @@ impl FixtureTilePrefab {
}
}
pub fn rock_wall(position: Vec3, textures: &Res<Textures>) -> Self {
pub fn rock_wall(position: Vec3) -> Self {
FixtureTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
sprite: Sprite {
image: textures.handles.get("rock_wall").unwrap().clone(),
..Default::default()
},
tile: FixtureTile {
id: 2,
..Default::default()
@@ -218,13 +274,9 @@ impl FixtureTilePrefab {
}
}
pub fn bedrock_wall(position: Vec3, textures: &Res<Textures>) -> Self {
pub fn bedrock_wall(position: Vec3) -> Self {
FixtureTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
sprite: Sprite {
image: textures.handles.get("bedrock_wall").unwrap().clone(),
..Default::default()
},
tile: FixtureTile {
id: 0,
..Default::default()
@@ -240,7 +292,6 @@ impl FixtureTilePrefab {
commands.spawn((
self.tile,
self.transform,
self.sprite,
self.visibility,
self.needs_occluded,
));