Maybe progress? A task per tile because we're super lazy

This commit is contained in:
Daniel Flanagan 2024-08-02 21:43:30 -05:00
parent deabad05ee
commit 21cec093b9
7 changed files with 74 additions and 122 deletions

View file

@ -1,3 +0,0 @@
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=/nix/store/46n1qljc0drdz4r2k9smxxb8kl79di25-mold-2.32.1/bin/mold"]

View file

@ -108,18 +108,20 @@
nativeBuildInputs = buildTimeDeps pkgs;
buildInputs = linkTimeDeps pkgs;
# hash = pkgs.lib.fakeHash;
# a hack to avoid using mold as our linker when building with nix
postUnpack = ''
ls -la
rm -r ./*/.cargo
'';
};
ZSTD_SYS_USE_PKG_CONFIG = "1";
LIBSSH2_SYS_USE_PKG_CONFIG = "1";
RUSTFLAGS = pkgs.lib.optionalString pkgs.stdenv.isLinux "-C link-arg=-fuse-ld=mold";
default = outputs.packages.${pkgs.system}.kodotag;
});
apps = forSystems (system: {
kodotag = outputs.packages.${system}.kodotag;
default = outputs.apps.${system}.kodotag;
});
devShells = genPkgs (pkgs: {
default = pkgs.mkShell {
inherit (self.checks.${pkgs.system}.git-hooks) shellHook;

View file

@ -79,6 +79,8 @@ fn main() -> AppExit {
.init_state::<View>()
.init_state::<Game>();
app.enable_state_scoped_entities::<View>();
app.configure_sets(
Update,
(
@ -100,6 +102,7 @@ fn main() -> AppExit {
OnEnter(View::LoadingGame),
(player::startup, statue::startup, map::spawn),
)
.add_systems(OnEnter(View::InGame), (map::finalize))
.add_systems(
OnExit(View::InGame),
(player::exit, statue::exit, map::exit),

View file

@ -1,5 +1,7 @@
use bevy::prelude::*;
use crate::View;
#[derive(Component, Debug)]
pub struct MainMenu;
@ -7,6 +9,7 @@ pub fn startup(mut commands: Commands) {
commands
.spawn((
MainMenu,
StateScoped(View::MainMenu),
Name::new("MenuRoot"),
NodeBundle {
style: Style {

View file

@ -1,6 +1,6 @@
use crate::{inspector::HideFromInspector, prelude::*};
use bevy::{
ecs::world::CommandQueue,
ecs::{system::SystemState, world::CommandQueue},
tasks::{block_on, futures_lite::future, AsyncComputeTaskPool, Task},
};
// use bevy::{
@ -11,13 +11,15 @@ use bevy_ecs_tilemap::prelude::*;
use rand::prelude::*;
use rand_pcg::Pcg64;
use rand_seeder::Seeder;
use std::sync::mpsc::channel;
#[derive(Component, Debug)]
pub struct Tilemap;
#[derive(Component)]
struct MapGen(Task<TileBundleBuilder>);
struct MapGenTask(Task<CommandQueue>);
#[derive(Resource, Deref)]
struct TileStorageHandle(TileStorage);
pub fn spawn(mut commands: Commands, assets: Res<AssetServer>) {
// TODO: I'm pretty determined to not have this sieze up the game despite the large number of entities being added. Should work with a "loading" screen and doing this in the background?
@ -25,45 +27,65 @@ pub fn spawn(mut commands: Commands, assets: Res<AssetServer>) {
let mut rng: Pcg64 = Seeder::from("default_seed").make_rng();
let size = TilemapSize::new(1024, 1024);
let tilemap = commands.spawn((Tilemap, Name::new("Tilemap"))).id();
let mut storage = TileStorage::empty(size);
// let mutex_storage = Mutex::new(storage);
let task_pool = AsyncComputeTaskPool::get();
let (tx, rx) = channel::<TileBundle>();
let tilebundlegenerator = task_pool.spawn(async move {
// this task is for generating tilebundles
for x in 0..size.x {
for y in 0..size.y {
let position = TilePos::new(x, y);
let texture_index = TileTextureIndex(if rng.gen_range(0..1000) > 925 {
rng.gen_range(0..(16 * 8))
} else {
0
});
tx.send(TileBundle {
position,
tilemap_id: TilemapId(tilemap),
texture_index,
..Default::default()
});
}
}
});
commands.insert_resource(TileStorageHandle(TileStorage::empty(size)));
let pool = AsyncComputeTaskPool::get();
// this task is for generating tilebundles
for x in 0..size.x {
for y in 0..size.y {
let tile = commands.spawn().id();
storage.set(&position, tile);
let position = TilePos::new(x, y);
let texture_index = TileTextureIndex(if rng.gen_range(0..1000) > 925 {
rng.gen_range(0..(16 * 8))
} else {
0
});
let task = pool.spawn(async move {
let mut command_queue = CommandQueue::default();
command_queue.push(move |world: &mut World| {
let mut state = SystemState::<Res<TileStorageHandle>>::new(world);
let storage = state.get_mut(world);
let entity = world
.spawn((
HideFromInspector,
TileBundle {
position,
tilemap_id: TilemapId(tilemap),
texture_index,
..Default::default()
},
))
.id();
storage.set(&position, entity);
});
command_queue
});
}
}
}
fn load(mut commands: Commands, mut tasks: Query<&mut MapGenTask>) {
// to avoid locking up the universe we only want to handle a certain number per iteration (Update)
for mut task in &mut tasks {
if let Some(mut commands_queue) = block_on(future::poll_once(&mut task.0)) {
// append the returned command queue to have it execute later
commands.append(&mut commands_queue);
}
}
}
pub fn finalize(
mut commands: Commands,
mut storage: Res<TileStorageHandle>,
tilemap: Query<Entity, With<Tilemap>>,
assets: Res<AssetServer>,
) {
// TODO: dedupe with load
let size = TilemapSize::new(1024, 1024);
let texture = TilemapTexture::Single(assets.load("img/Tileset Grass.png"));
let tile_size = TilemapTileSize::new(16., 16.);
let grid_size = TilemapGridSize::new(16., 16.);
let map_type = TilemapType::Square;
let storage = storage.0;
let tilemap = tilemap.single();
commands.entity(tilemap).insert(TilemapBundle {
grid_size,
map_type,
@ -76,82 +98,6 @@ pub fn spawn(mut commands: Commands, assets: Res<AssetServer>) {
});
}
// pub fn spawn_in_background(mut commands: Commands, assets: Res<AssetServer>) {
// let pool = AsyncComputeTaskPool::get();
// let tilemap_entity = commands.spawn(Name::new("TilemapEntity")).id();
// let texture_handle: Handle<Image> = assets.load("img/Tileset Grass.png");
// let mut rng: Pcg64 = Seeder::from("default_seed").make_rng();
// let map_size = UVec2::new(1024, 1024);
// let tile_size = Vec2 { x: 16.0, y: 16.0 };
// // tiletypes?
// let task = pool.spawn(async move {
// let mut queue = CommandQueue::default();
// for x in 0..map_size.x {
// for y in 0..map_size.y {
// let pos = Vec2::new(x as f32, y as f32) * tile_size;
// let texture_index = TileTextureIndex(if rng.gen_range(0..1000) > 925 {
// rng.gen_range(0..(16 * 8))
// } else {
// 0
// });
// queue.push(move |world: &mut World| {
// let tile_entity = world
// .spawn((
// HideFromInspector,
// TileBundle {
// position: tile_pos,
// tilemap_id: TilemapId(tilemap_entity),
// texture_index,
// ..Default::default()
// },
// ))
// .id();
// tile_storage_ref.set(&tile_pos, tile_entity);
// });
// }
// }
// queue.push(move |world: &mut World| {
// world.spawn((
// Tilemap,
// Name::new("Tilemap"),
// TilemapBundle {
// grid_size,
// map_type,
// size,
// storage,
// texture,
// tile_size,
// transform: get_tilemap_center_transform(&size, &grid_size, &map_type, f32::MIN),
// ..default()
// },
// ));
// });
// queue
// });
// commands.entity(tilemap_entity).insert(MapGen(task));
// }
// fn handle_tasks(mut commands: Commands, mut tasks: Query<&mut MapGen>) {
// for mut task in &mut tasks {
// if let Some(mut queue) = block_on(future::poll_once(&mut task.0)) {
// commands.append(&mut queue);
// }
// }
// }
fn load(mut commands: Commands, mut tasks: Query<&mut MapGen>) {
// to avoid locking up the universe we only want to handle a certain number per iteration (Update)
for mut task in &mut tasks {
if let Some(mut commands_queue) = block_on(future::poll_once(&mut task.0)) {
// append the returned command queue to have it execute later
commands.append(&mut commands_queue);
}
}
}
pub fn exit(mut commands: Commands, q: Query<Entity, With<Tilemap>>) {
for id in q.iter() {
commands.entity(id).despawn_recursive();

View file

@ -2,7 +2,7 @@ use std::f32::consts::TAU;
use crate::camera::Watched;
use crate::movement::{Heading, Mover, Speed, Velocity, YSortable};
use crate::prelude::*;
use crate::{prelude::*, View};
use bevy::sprite::MaterialMesh2dBundle;
const PLAYER_SPEED: f32 = 200.;
@ -35,6 +35,7 @@ pub fn startup(
commands
.spawn((
Player,
StateScoped(View::InGame),
Name::new("Player"),
VisibilityBundle {
visibility: Visibility::Inherited,

View file

@ -1,5 +1,5 @@
use crate::movement::YSortable;
use crate::prelude::*;
use crate::{prelude::*, View};
#[derive(Component, Debug, Default)]
pub struct Statue;
@ -51,7 +51,7 @@ pub fn spawn_statue(
},
..default()
};
commands.spawn((Name::new("Statue"), bundle));
commands.spawn((Name::new("Statue"), StateScoped(View::InGame), bundle));
}
}