315 lines
9.6 KiB
Rust
315 lines
9.6 KiB
Rust
|
|
use crate::tile::{FixtureTile, FloorTile, NeedsOccluded, TileState};
|
|
use crate::{constants::*, game};
|
|
use bevy::prelude::*;
|
|
use bevy_platform::collections::hash_map::HashMap;
|
|
|
|
#[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, 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;
|
|
|
|
#[derive(Component)]
|
|
pub struct TerrainSprite;
|
|
|
|
// TODO: re-rendering on z-index change is inefficient, replace with shifting pool system for z-index change
|
|
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>,
|
|
query_1: Query<Entity, With<TerrainSprite>>,
|
|
) {
|
|
if cwss.state != WorldSpriteState::WaitingForRender {
|
|
return;
|
|
}
|
|
|
|
// despawn all query_1 entities
|
|
for entity in query_1.iter() {
|
|
commands.entity(entity).despawn();
|
|
}
|
|
|
|
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, TerrainSprite));
|
|
}
|
|
}
|
|
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,
|
|
));
|
|
}
|
|
}
|