Files
dorf/src/tiles.rs
T
2025-05-02 18:20:32 +01:00

305 lines
9.3 KiB
Rust

use std::process::exit;
use crate::tile::{FixtureTile, FloorTile, NeedsOccluded, TileState};
use crate::{constants::*, game};
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<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_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_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_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_PATH.to_string(),
asset_server.load(BEDROCK_FLOOR_PATH),
);
texture_ids.insert(FIXTURE_ID_OFFSET + 1, DIRT_WALL_PATH.to_string());
textures.insert(
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>,
z_index: ResMut<game::ZIndex>,
) {
if cwss.state != WorldSpriteState::WaitingForRender {
return;
}
let now = Instant::now();
if cwss.state == WorldSpriteState::WaitingForRender {
cwss.state = WorldSpriteState::InProgress;
let z_index = (z_index.0 as i32 + 150) as usize;
println!("z_index = {}", z_index);
for (floortile, transform) in query.iter_mut() {
let is_visible =
(floortile.visible_range[z_index / 32] & (1 << (z_index % 32) as u32)) != 0;
if is_visible {
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);
}
#[derive(Bundle)]
pub struct FloorTilePrefab {
transform: Transform,
tile: FloorTile,
tile_state: TileState,
visibility: Visibility,
needs_occluded: NeedsOccluded,
}
impl FloorTilePrefab {
pub fn grass(position: Vec3) -> Self {
FloorTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
tile: FloorTile {
id: 1,
astar_weight: 100,
..Default::default()
},
tile_state: TileState {
timer: Timer::from_seconds(1.0, TimerMode::Repeating),
},
visibility: Visibility::Hidden,
needs_occluded: NeedsOccluded {
has_been_occluded: false,
},
}
}
pub fn dirt(position: Vec3) -> Self {
FloorTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
tile: FloorTile {
id: 2,
astar_weight: 85,
..Default::default()
},
tile_state: TileState {
timer: Timer::from_seconds(1.0, TimerMode::Repeating),
},
visibility: Visibility::Hidden,
needs_occluded: NeedsOccluded {
has_been_occluded: false,
},
}
}
pub fn rock(position: Vec3) -> Self {
FloorTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
tile: FloorTile {
id: 3,
astar_weight: 50,
..Default::default()
},
tile_state: TileState {
timer: Timer::from_seconds(1.0, TimerMode::Repeating),
},
visibility: Visibility::Hidden,
needs_occluded: NeedsOccluded {
has_been_occluded: false,
},
}
}
pub fn air(position: Vec3) -> Self {
FloorTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
tile: FloorTile {
id: 0,
opaque: false,
walkable: false,
..Default::default()
},
tile_state: TileState {
timer: Timer::from_seconds(1.0, TimerMode::Repeating),
},
visibility: Visibility::Hidden,
needs_occluded: NeedsOccluded {
has_been_occluded: false,
},
}
}
pub fn bedrock(position: Vec3) -> Self {
FloorTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
tile: FloorTile {
id: 4,
astar_weight: 150,
..Default::default()
},
tile_state: TileState {
timer: Timer::from_seconds(1.0, TimerMode::Repeating),
},
visibility: Visibility::Hidden,
needs_occluded: NeedsOccluded {
has_been_occluded: false,
},
}
}
pub fn spawn(self, commands: &mut Commands) {
commands.spawn((
self.tile,
self.transform,
self.tile_state,
self.visibility,
self.needs_occluded,
));
}
}
#[derive(Bundle)]
pub struct FixtureTilePrefab {
transform: Transform,
tile: FixtureTile,
visibility: Visibility,
needs_occluded: NeedsOccluded,
}
impl FixtureTilePrefab {
pub fn dirt_wall(position: Vec3) -> Self {
FixtureTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
tile: FixtureTile {
id: FIXTURE_ID_OFFSET + 1,
..Default::default()
},
visibility: Visibility::Hidden,
needs_occluded: NeedsOccluded {
has_been_occluded: false,
},
}
}
pub fn rock_wall(position: Vec3) -> Self {
FixtureTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
tile: FixtureTile {
id: 2,
..Default::default()
},
visibility: Visibility::Hidden,
needs_occluded: NeedsOccluded {
has_been_occluded: false,
},
}
}
pub fn bedrock_wall(position: Vec3) -> Self {
FixtureTilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
tile: FixtureTile {
id: 0,
..Default::default()
},
visibility: Visibility::Hidden,
needs_occluded: NeedsOccluded {
has_been_occluded: false,
},
}
}
pub fn spawn(self, commands: &mut Commands) {
commands.spawn((
self.tile,
self.transform,
self.visibility,
self.needs_occluded,
));
}
}