Don't generate world on startup
This commit is contained in:
parent
f65f29e6b0
commit
b9e402ecf9
6 changed files with 73 additions and 78 deletions
|
@ -162,28 +162,10 @@ impl WorldManager {
|
|||
self.world.as_ref()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn world(&self) -> &World {
|
||||
assert!(self.world.is_some(), "No world.");
|
||||
self.get_world().unwrap()
|
||||
}
|
||||
|
||||
pub fn set_world(&mut self, world: World) {
|
||||
self.world = Some(world);
|
||||
}
|
||||
|
||||
pub fn new_world(&mut self, seed: Option<u32>) -> Result<&World, WorldGenError> {
|
||||
let seed = seed.unwrap_or_else(random);
|
||||
let mut new_world = World::new(
|
||||
WorldManager::NEW_WORLD_WIDTH,
|
||||
WorldManager::NEW_WORLD_HEIGHT,
|
||||
seed,
|
||||
);
|
||||
new_world.generate()?;
|
||||
self.world = Some(new_world);
|
||||
Ok(self.get_world().unwrap())
|
||||
}
|
||||
|
||||
pub fn new_world_async(&mut self, seed: Option<u32>) -> Task<Result<World, WorldGenError>> {
|
||||
AsyncComputeTaskPool::get().spawn(async move {
|
||||
let seed = seed.unwrap_or_else(random);
|
||||
|
|
|
@ -25,11 +25,14 @@ impl WindowSystem for TileInfo<'_, '_> {
|
|||
let cursor_y = cursor_position.y;
|
||||
let cursor_x = cursor_position.x;
|
||||
|
||||
let world_manager = world.resource::<WorldManager>();
|
||||
let Some(world) = world.resource::<WorldManager>().get_world() else {
|
||||
ui.label("No world.");
|
||||
return;
|
||||
};
|
||||
if cursor_x >= 0
|
||||
&& cursor_x < world_manager.world().width.try_into().unwrap()
|
||||
&& cursor_x < world.width.try_into().unwrap()
|
||||
&& cursor_y >= 0
|
||||
&& cursor_y < world_manager.world().height.try_into().unwrap()
|
||||
&& cursor_y < world.height.try_into().unwrap()
|
||||
{
|
||||
let TerrainCell {
|
||||
altitude,
|
||||
|
@ -38,7 +41,7 @@ impl WindowSystem for TileInfo<'_, '_> {
|
|||
biome_presences,
|
||||
x,
|
||||
y,
|
||||
} = &world_manager.world().terrain[cursor_y as usize][cursor_x as usize];
|
||||
} = &world.terrain[cursor_y as usize][cursor_x as usize];
|
||||
|
||||
_ = ui.label("Coordinates");
|
||||
_ = ui.label(format!("{x}:{y}"));
|
||||
|
|
88
src/main.rs
88
src/main.rs
|
@ -42,6 +42,9 @@ fn update_cursor_map_position(
|
|||
windows: Res<'_, Windows>,
|
||||
world_manager: Res<'_, WorldManager>,
|
||||
) {
|
||||
let Some(world) = world_manager.get_world() else {
|
||||
return
|
||||
};
|
||||
let (camera, transform) = transform.single();
|
||||
|
||||
let window = match camera.target {
|
||||
|
@ -61,7 +64,6 @@ fn update_cursor_map_position(
|
|||
let world_position =
|
||||
ndc_to_world.project_point3(ndc.extend(-1.0)).truncate() / WORLD_SCALE as f32;
|
||||
|
||||
let world = world_manager.world();
|
||||
cursor_map_position.x = world.width as i32 / 2 + f32::ceil(world_position.x) as i32 - 1;
|
||||
cursor_map_position.y = world.height as i32 / 2 + f32::ceil(world_position.y) as i32 - 1;
|
||||
}
|
||||
|
@ -74,7 +76,7 @@ fn handle_generate_world_task(
|
|||
) {
|
||||
if let Some(task) = &mut generate_world_task.0 {
|
||||
if task.is_finished() {
|
||||
debug!("Done");
|
||||
debug!("Done generating world");
|
||||
if let Some(result) = block_on(poll_once(task)) {
|
||||
match result {
|
||||
Ok(world) => {
|
||||
|
@ -82,6 +84,8 @@ fn handle_generate_world_task(
|
|||
#[cfg(feature = "render")]
|
||||
{
|
||||
should_redraw.0 = true;
|
||||
#[cfg(feature = "logging")]
|
||||
debug!("Requesting map redraw");
|
||||
}
|
||||
},
|
||||
Err(err) => error!("{err:#?}"),
|
||||
|
@ -89,7 +93,7 @@ fn handle_generate_world_task(
|
|||
}
|
||||
generate_world_task.0 = None;
|
||||
} else {
|
||||
debug!("Working")
|
||||
debug!("Still generating world")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,13 +101,11 @@ fn handle_generate_world_task(
|
|||
#[cfg(feature = "render")]
|
||||
fn generate_graphics(
|
||||
mut commands: Commands<'_, '_>,
|
||||
world_manager: ResMut<'_, WorldManager>,
|
||||
images: ResMut<'_, Assets<Image>>,
|
||||
egui_context: ResMut<'_, EguiContext>,
|
||||
render_settings: ResMut<'_, WorldRenderSettings>,
|
||||
) {
|
||||
// Add Julia-Mono font to egui
|
||||
|
||||
{
|
||||
let egui_context = egui_context.into_inner();
|
||||
let ctx = egui_context.ctx_mut();
|
||||
|
@ -126,19 +128,15 @@ fn generate_graphics(
|
|||
ctx.set_fonts(fonts);
|
||||
|
||||
let mut style = (*ctx.style()).clone();
|
||||
// Make all text 33% bigger because I have bad eyes (and the font is small)
|
||||
for style in style.text_styles.iter_mut() {
|
||||
style.1.size *= 16.0 / 12.0;
|
||||
}
|
||||
ctx.set_style(style);
|
||||
#[cfg(feature = "logging")]
|
||||
debug!("Fonts: {:#?}", &ctx.style().text_styles);
|
||||
// #[cfg(feature = "logging")]
|
||||
// debug!("Fonts: {:#?}", &ctx.style().text_styles);
|
||||
}
|
||||
|
||||
let world = world_manager.world();
|
||||
let custom_sprite_size = Vec2 {
|
||||
x: (WORLD_SCALE * world.width as i32) as f32,
|
||||
y: (WORLD_SCALE * world.height as i32) as f32,
|
||||
};
|
||||
// Set up 2D map mode
|
||||
{
|
||||
use bevy::render::render_resource::{
|
||||
|
@ -150,7 +148,7 @@ fn generate_graphics(
|
|||
let images = images.into_inner();
|
||||
let mut render_settings = render_settings.into_inner();
|
||||
let map_image_handle = images.add(Image {
|
||||
data: vec![],
|
||||
data: vec![0; 16],
|
||||
texture_descriptor: TextureDescriptor {
|
||||
label: None,
|
||||
size: default(),
|
||||
|
@ -167,12 +165,7 @@ fn generate_graphics(
|
|||
|
||||
// TODO: Switch to egui
|
||||
_ = commands.spawn(SpriteBundle {
|
||||
texture: images
|
||||
.get_handle(unsafe { render_settings.map_image_handle_id.unwrap_unchecked() }),
|
||||
sprite: Sprite {
|
||||
custom_size: Some(custom_sprite_size),
|
||||
..default()
|
||||
},
|
||||
texture: images.get_handle(render_settings.map_image_handle_id.unwrap()),
|
||||
..default()
|
||||
});
|
||||
}
|
||||
|
@ -224,7 +217,17 @@ fn redraw_map(
|
|||
world_manager: Res<WorldManager>,
|
||||
render_settings: Res<'_, WorldRenderSettings>,
|
||||
mut images: ResMut<Assets<Image>>,
|
||||
mut map_sprite: Query<'_, '_, &mut Sprite>,
|
||||
) {
|
||||
let Some(world) = world_manager.get_world() else {
|
||||
#[cfg(feature = "logging")]
|
||||
if should_redraw.0 {
|
||||
debug!("Couldn't redraw map despite wanting to, because world isn't generated");
|
||||
}
|
||||
return;
|
||||
};
|
||||
assert!(world.width > 0);
|
||||
|
||||
if should_redraw.0 {
|
||||
let world_manager: &WorldManager = &world_manager;
|
||||
let render_settings: &WorldRenderSettings = &render_settings;
|
||||
|
@ -239,60 +242,61 @@ fn redraw_map(
|
|||
let map_image = images
|
||||
.get_mut(&map_image_handle)
|
||||
.expect("Map image handle pointing to non-existing image");
|
||||
#[cfg(feature = "logging")]
|
||||
debug!("Resizing image to {}x{}", world.width, world.height);
|
||||
map_image.resize(bevy::render::render_resource::Extent3d {
|
||||
width: world_manager.world().width,
|
||||
height: world_manager.world().height,
|
||||
depth_or_array_layers: 1,
|
||||
width: world.width,
|
||||
height: world.height,
|
||||
..default()
|
||||
});
|
||||
map_image.data = world_manager.map_color_bytes(render_settings);
|
||||
map_sprite.single_mut().custom_size = Some(Vec2 {
|
||||
x: (world.width * WORLD_SCALE as u32) as f32,
|
||||
y: (world.height * WORLD_SCALE as u32) as f32,
|
||||
});
|
||||
|
||||
should_redraw.0 = false;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
const WORLD_SCALE: i32 = 2;
|
||||
const WORLD_SCALE: i32 = 4;
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut app = App::new();
|
||||
let mut manager = WorldManager::new();
|
||||
#[cfg(feature = "render")]
|
||||
{
|
||||
use bevy::winit::WinitSettings;
|
||||
use bevy::winit::{UpdateMode, WinitSettings};
|
||||
|
||||
let world = manager.new_world(Some(0))?;
|
||||
_ = app
|
||||
.insert_resource(WinitSettings::game())
|
||||
.insert_resource(WinitSettings {
|
||||
focused_mode: UpdateMode::Continuous,
|
||||
unfocused_mode: UpdateMode::ReactiveLowPower {
|
||||
max_wait: std::time::Duration::from_secs(10),
|
||||
},
|
||||
..default()
|
||||
})
|
||||
.insert_resource(CursorMapPosition::default())
|
||||
.insert_resource(OpenedWindows::default())
|
||||
.insert_resource(WorldRenderSettings::default())
|
||||
.insert_resource(ShouldRedraw::default())
|
||||
.insert_resource(GenerateWorldTask::default())
|
||||
.add_startup_system(generate_graphics)
|
||||
.add_system(update_gui)
|
||||
.add_system(update_cursor_map_position)
|
||||
.add_system(open_tile_info)
|
||||
.add_system(redraw_map);
|
||||
|
||||
app.add_plugins(WorldPlugins.set(WindowPlugin {
|
||||
window: WindowDescriptor {
|
||||
width: (WORLD_SCALE * world.width as i32) as f32,
|
||||
height: (WORLD_SCALE * world.height as i32) as f32,
|
||||
title: String::from("World-RS"),
|
||||
resizable: true,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
}));
|
||||
app.add_plugins(WorldPlugins);
|
||||
}
|
||||
#[cfg(not(feature = "render"))]
|
||||
{
|
||||
_ = manager.new_world(Some(0))?;
|
||||
|
||||
app.add_plugins(WorldPlugins);
|
||||
}
|
||||
|
||||
app.add_system(handle_generate_world_task)
|
||||
.insert_resource(manager)
|
||||
app.insert_resource(WorldManager::new())
|
||||
.insert_resource(GenerateWorldTask(
|
||||
/* Some(manager.new_world_async(Some(0))) */ None,
|
||||
))
|
||||
.add_system(handle_generate_world_task)
|
||||
.run();
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -173,7 +173,10 @@ pub(crate) trait WorldRenderer {
|
|||
impl WorldRenderer for WorldManager {
|
||||
#[must_use]
|
||||
fn map_color_bytes(&self, render_settings: &WorldRenderSettings) -> Vec<u8> {
|
||||
self.world()
|
||||
let Some(world) = self.get_world() else {
|
||||
return vec![];
|
||||
};
|
||||
world
|
||||
.terrain
|
||||
.iter()
|
||||
.rev()
|
||||
|
@ -190,10 +193,11 @@ impl WorldRenderer for WorldManager {
|
|||
|
||||
#[must_use]
|
||||
fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color {
|
||||
let world = self.get_world().expect("No world in generate_color");
|
||||
let base_color = match render_settings.view {
|
||||
WorldView::Biomes => biome_color(self.world(), cell),
|
||||
WorldView::Topography => altitude_contour_color(self.world(), cell.altitude),
|
||||
WorldView::Coastlines => coastline_color(self.world(), cell),
|
||||
WorldView::Biomes => biome_color(world, cell),
|
||||
WorldView::Topography => altitude_contour_color(world, cell.altitude),
|
||||
WorldView::Coastlines => coastline_color(world, cell),
|
||||
};
|
||||
let mut normalizer = 1.0;
|
||||
|
||||
|
|
|
@ -46,7 +46,16 @@ impl PluginGroup for WorldPlugins {
|
|||
group_builder = group_builder
|
||||
.add(TransformPlugin)
|
||||
.add(InputPlugin)
|
||||
.add(WindowPlugin::default())
|
||||
.add(WindowPlugin {
|
||||
window: WindowDescriptor {
|
||||
width: 1600.0,
|
||||
height: 800.0,
|
||||
title: String::from("World-RS"),
|
||||
resizable: true,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
})
|
||||
.add(AssetPlugin::default())
|
||||
.add(RenderPlugin)
|
||||
.add(ImagePlugin::default_nearest())
|
||||
|
|
|
@ -19,15 +19,8 @@ impl Display for CursorMapPosition {
|
|||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
#[derive(Resource)]
|
||||
#[derive(Resource, Default)]
|
||||
pub(crate) struct ShouldRedraw(pub(crate) bool);
|
||||
#[cfg(feature = "render")]
|
||||
impl Default for ShouldRedraw {
|
||||
fn default() -> Self {
|
||||
Self(true)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
#[derive(Default, Resource)]
|
||||
pub(crate) struct OpenedWindows(HashSet<WindowId>);
|
||||
|
|
Loading…
Reference in a new issue