2024-08-02 16:32:28 -05:00
use crate ::{ inspector ::HideFromInspector , prelude ::* } ;
2024-08-02 17:04:16 -05:00
use bevy ::{
ecs ::world ::CommandQueue ,
tasks ::{ block_on , futures_lite ::future , AsyncComputeTaskPool , Task } ,
} ;
2024-08-02 16:32:28 -05:00
// use bevy::{
// ecs::world::CommandQueue,
// tasks::{AsyncComputeTaskPool, Task},
// };
2024-08-02 16:43:30 -05:00
use bevy_ecs_tilemap ::prelude ::* ;
2024-08-02 13:40:43 -05:00
use rand ::prelude ::* ;
use rand_pcg ::Pcg64 ;
use rand_seeder ::Seeder ;
2024-08-02 17:04:16 -05:00
use std ::sync ::mpsc ::channel ;
2024-08-02 13:40:43 -05:00
#[ derive(Component, Debug) ]
pub struct Tilemap ;
2024-08-02 17:04:16 -05:00
#[ derive(Component) ]
struct MapGen ( Task < TileBundleBuilder > ) ;
2024-08-02 16:32:28 -05:00
2024-08-02 16:43:30 -05:00
pub fn spawn ( mut commands : Commands , assets : Res < AssetServer > ) {
2024-08-02 17:04:16 -05:00
// 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?
2024-08-02 13:40:43 -05:00
2024-08-02 16:32:28 -05:00
let mut rng : Pcg64 = Seeder ::from ( " default_seed " ) . make_rng ( ) ;
2024-08-02 16:43:30 -05:00
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);
2024-08-02 17:04:16 -05:00
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 ( )
} ) ;
}
}
} ) ;
2024-08-02 16:43:30 -05:00
for x in 0 .. size . x {
for y in 0 .. size . y {
2024-08-02 17:04:16 -05:00
let tile = commands . spawn ( ) . id ( ) ;
2024-08-02 16:43:30 -05:00
storage . set ( & position , tile ) ;
}
}
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 ;
commands . entity ( tilemap ) . insert ( TilemapBundle {
grid_size ,
map_type ,
size ,
storage ,
texture ,
tile_size ,
transform : get_tilemap_center_transform ( & size , & grid_size , & map_type , f32 ::MIN ) ,
.. Default ::default ( )
} ) ;
2024-08-02 16:32:28 -05:00
}
2024-08-02 13:40:43 -05:00
2024-08-02 16:32:28 -05:00
// 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);
// });
// }
// }
2024-08-02 13:40:43 -05:00
2024-08-02 16:32:28 -05:00
// 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()
// },
// ));
// });
2024-08-02 13:40:43 -05:00
2024-08-02 16:32:28 -05:00
// queue
// });
2024-08-02 13:40:43 -05:00
2024-08-02 16:32:28 -05:00
// commands.entity(tilemap_entity).insert(MapGen(task));
// }
2024-08-02 13:40:43 -05:00
2024-08-02 16:32:28 -05:00
// 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);
// }
// }
// }
2024-08-02 13:40:43 -05:00
2024-08-02 17:04:16 -05:00
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 ) ;
}
}
}
2024-08-02 13:40:43 -05:00
pub fn exit ( mut commands : Commands , q : Query < Entity , With < Tilemap > > ) {
for id in q . iter ( ) {
commands . entity ( id ) . despawn_recursive ( ) ;
}
}