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()
|
self.world.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
pub fn set_world(&mut self, world: World) {
|
||||||
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);
|
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>> {
|
pub fn new_world_async(&mut self, seed: Option<u32>) -> Task<Result<World, WorldGenError>> {
|
||||||
AsyncComputeTaskPool::get().spawn(async move {
|
AsyncComputeTaskPool::get().spawn(async move {
|
||||||
let seed = seed.unwrap_or_else(random);
|
let seed = seed.unwrap_or_else(random);
|
||||||
|
|
|
@ -25,11 +25,14 @@ impl WindowSystem for TileInfo<'_, '_> {
|
||||||
let cursor_y = cursor_position.y;
|
let cursor_y = cursor_position.y;
|
||||||
let cursor_x = cursor_position.x;
|
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
|
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 >= 0
|
||||||
&& cursor_y < world_manager.world().height.try_into().unwrap()
|
&& cursor_y < world.height.try_into().unwrap()
|
||||||
{
|
{
|
||||||
let TerrainCell {
|
let TerrainCell {
|
||||||
altitude,
|
altitude,
|
||||||
|
@ -38,7 +41,7 @@ impl WindowSystem for TileInfo<'_, '_> {
|
||||||
biome_presences,
|
biome_presences,
|
||||||
x,
|
x,
|
||||||
y,
|
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("Coordinates");
|
||||||
_ = ui.label(format!("{x}:{y}"));
|
_ = 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>,
|
windows: Res<'_, Windows>,
|
||||||
world_manager: Res<'_, WorldManager>,
|
world_manager: Res<'_, WorldManager>,
|
||||||
) {
|
) {
|
||||||
|
let Some(world) = world_manager.get_world() else {
|
||||||
|
return
|
||||||
|
};
|
||||||
let (camera, transform) = transform.single();
|
let (camera, transform) = transform.single();
|
||||||
|
|
||||||
let window = match camera.target {
|
let window = match camera.target {
|
||||||
|
@ -61,7 +64,6 @@ fn update_cursor_map_position(
|
||||||
let world_position =
|
let world_position =
|
||||||
ndc_to_world.project_point3(ndc.extend(-1.0)).truncate() / WORLD_SCALE as f32;
|
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.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;
|
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 let Some(task) = &mut generate_world_task.0 {
|
||||||
if task.is_finished() {
|
if task.is_finished() {
|
||||||
debug!("Done");
|
debug!("Done generating world");
|
||||||
if let Some(result) = block_on(poll_once(task)) {
|
if let Some(result) = block_on(poll_once(task)) {
|
||||||
match result {
|
match result {
|
||||||
Ok(world) => {
|
Ok(world) => {
|
||||||
|
@ -82,6 +84,8 @@ fn handle_generate_world_task(
|
||||||
#[cfg(feature = "render")]
|
#[cfg(feature = "render")]
|
||||||
{
|
{
|
||||||
should_redraw.0 = true;
|
should_redraw.0 = true;
|
||||||
|
#[cfg(feature = "logging")]
|
||||||
|
debug!("Requesting map redraw");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(err) => error!("{err:#?}"),
|
Err(err) => error!("{err:#?}"),
|
||||||
|
@ -89,7 +93,7 @@ fn handle_generate_world_task(
|
||||||
}
|
}
|
||||||
generate_world_task.0 = None;
|
generate_world_task.0 = None;
|
||||||
} else {
|
} else {
|
||||||
debug!("Working")
|
debug!("Still generating world")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,13 +101,11 @@ fn handle_generate_world_task(
|
||||||
#[cfg(feature = "render")]
|
#[cfg(feature = "render")]
|
||||||
fn generate_graphics(
|
fn generate_graphics(
|
||||||
mut commands: Commands<'_, '_>,
|
mut commands: Commands<'_, '_>,
|
||||||
world_manager: ResMut<'_, WorldManager>,
|
|
||||||
images: ResMut<'_, Assets<Image>>,
|
images: ResMut<'_, Assets<Image>>,
|
||||||
egui_context: ResMut<'_, EguiContext>,
|
egui_context: ResMut<'_, EguiContext>,
|
||||||
render_settings: ResMut<'_, WorldRenderSettings>,
|
render_settings: ResMut<'_, WorldRenderSettings>,
|
||||||
) {
|
) {
|
||||||
// Add Julia-Mono font to egui
|
// Add Julia-Mono font to egui
|
||||||
|
|
||||||
{
|
{
|
||||||
let egui_context = egui_context.into_inner();
|
let egui_context = egui_context.into_inner();
|
||||||
let ctx = egui_context.ctx_mut();
|
let ctx = egui_context.ctx_mut();
|
||||||
|
@ -126,19 +128,15 @@ fn generate_graphics(
|
||||||
ctx.set_fonts(fonts);
|
ctx.set_fonts(fonts);
|
||||||
|
|
||||||
let mut style = (*ctx.style()).clone();
|
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() {
|
for style in style.text_styles.iter_mut() {
|
||||||
style.1.size *= 16.0 / 12.0;
|
style.1.size *= 16.0 / 12.0;
|
||||||
}
|
}
|
||||||
ctx.set_style(style);
|
ctx.set_style(style);
|
||||||
#[cfg(feature = "logging")]
|
// #[cfg(feature = "logging")]
|
||||||
debug!("Fonts: {:#?}", &ctx.style().text_styles);
|
// 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
|
// Set up 2D map mode
|
||||||
{
|
{
|
||||||
use bevy::render::render_resource::{
|
use bevy::render::render_resource::{
|
||||||
|
@ -150,7 +148,7 @@ fn generate_graphics(
|
||||||
let images = images.into_inner();
|
let images = images.into_inner();
|
||||||
let mut render_settings = render_settings.into_inner();
|
let mut render_settings = render_settings.into_inner();
|
||||||
let map_image_handle = images.add(Image {
|
let map_image_handle = images.add(Image {
|
||||||
data: vec![],
|
data: vec![0; 16],
|
||||||
texture_descriptor: TextureDescriptor {
|
texture_descriptor: TextureDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
size: default(),
|
size: default(),
|
||||||
|
@ -167,12 +165,7 @@ fn generate_graphics(
|
||||||
|
|
||||||
// TODO: Switch to egui
|
// TODO: Switch to egui
|
||||||
_ = commands.spawn(SpriteBundle {
|
_ = commands.spawn(SpriteBundle {
|
||||||
texture: images
|
texture: images.get_handle(render_settings.map_image_handle_id.unwrap()),
|
||||||
.get_handle(unsafe { render_settings.map_image_handle_id.unwrap_unchecked() }),
|
|
||||||
sprite: Sprite {
|
|
||||||
custom_size: Some(custom_sprite_size),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -224,7 +217,17 @@ fn redraw_map(
|
||||||
world_manager: Res<WorldManager>,
|
world_manager: Res<WorldManager>,
|
||||||
render_settings: Res<'_, WorldRenderSettings>,
|
render_settings: Res<'_, WorldRenderSettings>,
|
||||||
mut images: ResMut<Assets<Image>>,
|
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 {
|
if should_redraw.0 {
|
||||||
let world_manager: &WorldManager = &world_manager;
|
let world_manager: &WorldManager = &world_manager;
|
||||||
let render_settings: &WorldRenderSettings = &render_settings;
|
let render_settings: &WorldRenderSettings = &render_settings;
|
||||||
|
@ -239,60 +242,61 @@ fn redraw_map(
|
||||||
let map_image = images
|
let map_image = images
|
||||||
.get_mut(&map_image_handle)
|
.get_mut(&map_image_handle)
|
||||||
.expect("Map image handle pointing to non-existing image");
|
.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 {
|
map_image.resize(bevy::render::render_resource::Extent3d {
|
||||||
width: world_manager.world().width,
|
width: world.width,
|
||||||
height: world_manager.world().height,
|
height: world.height,
|
||||||
depth_or_array_layers: 1,
|
..default()
|
||||||
});
|
});
|
||||||
map_image.data = world_manager.map_color_bytes(render_settings);
|
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;
|
should_redraw.0 = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "render")]
|
#[cfg(feature = "render")]
|
||||||
const WORLD_SCALE: i32 = 2;
|
const WORLD_SCALE: i32 = 4;
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
let mut manager = WorldManager::new();
|
|
||||||
#[cfg(feature = "render")]
|
#[cfg(feature = "render")]
|
||||||
{
|
{
|
||||||
use bevy::winit::WinitSettings;
|
use bevy::winit::{UpdateMode, WinitSettings};
|
||||||
|
|
||||||
let world = manager.new_world(Some(0))?;
|
|
||||||
_ = app
|
_ = 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(CursorMapPosition::default())
|
||||||
.insert_resource(OpenedWindows::default())
|
.insert_resource(OpenedWindows::default())
|
||||||
.insert_resource(WorldRenderSettings::default())
|
.insert_resource(WorldRenderSettings::default())
|
||||||
.insert_resource(ShouldRedraw::default())
|
.insert_resource(ShouldRedraw::default())
|
||||||
.insert_resource(GenerateWorldTask::default())
|
|
||||||
.add_startup_system(generate_graphics)
|
.add_startup_system(generate_graphics)
|
||||||
.add_system(update_gui)
|
.add_system(update_gui)
|
||||||
.add_system(update_cursor_map_position)
|
.add_system(update_cursor_map_position)
|
||||||
.add_system(open_tile_info)
|
.add_system(open_tile_info)
|
||||||
.add_system(redraw_map);
|
.add_system(redraw_map);
|
||||||
|
|
||||||
app.add_plugins(WorldPlugins.set(WindowPlugin {
|
app.add_plugins(WorldPlugins);
|
||||||
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()
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "render"))]
|
#[cfg(not(feature = "render"))]
|
||||||
{
|
{
|
||||||
_ = manager.new_world(Some(0))?;
|
|
||||||
|
|
||||||
app.add_plugins(WorldPlugins);
|
app.add_plugins(WorldPlugins);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.add_system(handle_generate_world_task)
|
app.insert_resource(WorldManager::new())
|
||||||
.insert_resource(manager)
|
.insert_resource(GenerateWorldTask(
|
||||||
|
/* Some(manager.new_world_async(Some(0))) */ None,
|
||||||
|
))
|
||||||
|
.add_system(handle_generate_world_task)
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -173,7 +173,10 @@ pub(crate) trait WorldRenderer {
|
||||||
impl WorldRenderer for WorldManager {
|
impl WorldRenderer for WorldManager {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn map_color_bytes(&self, render_settings: &WorldRenderSettings) -> Vec<u8> {
|
fn map_color_bytes(&self, render_settings: &WorldRenderSettings) -> Vec<u8> {
|
||||||
self.world()
|
let Some(world) = self.get_world() else {
|
||||||
|
return vec![];
|
||||||
|
};
|
||||||
|
world
|
||||||
.terrain
|
.terrain
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
|
@ -190,10 +193,11 @@ impl WorldRenderer for WorldManager {
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color {
|
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 {
|
let base_color = match render_settings.view {
|
||||||
WorldView::Biomes => biome_color(self.world(), cell),
|
WorldView::Biomes => biome_color(world, cell),
|
||||||
WorldView::Topography => altitude_contour_color(self.world(), cell.altitude),
|
WorldView::Topography => altitude_contour_color(world, cell.altitude),
|
||||||
WorldView::Coastlines => coastline_color(self.world(), cell),
|
WorldView::Coastlines => coastline_color(world, cell),
|
||||||
};
|
};
|
||||||
let mut normalizer = 1.0;
|
let mut normalizer = 1.0;
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,16 @@ impl PluginGroup for WorldPlugins {
|
||||||
group_builder = group_builder
|
group_builder = group_builder
|
||||||
.add(TransformPlugin)
|
.add(TransformPlugin)
|
||||||
.add(InputPlugin)
|
.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(AssetPlugin::default())
|
||||||
.add(RenderPlugin)
|
.add(RenderPlugin)
|
||||||
.add(ImagePlugin::default_nearest())
|
.add(ImagePlugin::default_nearest())
|
||||||
|
|
|
@ -19,15 +19,8 @@ impl Display for CursorMapPosition {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "render")]
|
#[cfg(feature = "render")]
|
||||||
#[derive(Resource)]
|
#[derive(Resource, Default)]
|
||||||
pub(crate) struct ShouldRedraw(pub(crate) bool);
|
pub(crate) struct ShouldRedraw(pub(crate) bool);
|
||||||
#[cfg(feature = "render")]
|
|
||||||
impl Default for ShouldRedraw {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "render")]
|
#[cfg(feature = "render")]
|
||||||
#[derive(Default, Resource)]
|
#[derive(Default, Resource)]
|
||||||
pub(crate) struct OpenedWindows(HashSet<WindowId>);
|
pub(crate) struct OpenedWindows(HashSet<WindowId>);
|
||||||
|
|
Loading…
Reference in a new issue