Update bevy version, implement bevy_rand
This commit is contained in:
+64
-59
@@ -1,9 +1,16 @@
|
||||
use crate::constants::TILE_SIZE;
|
||||
use crate::tile::TileMap;
|
||||
use crate::{
|
||||
constants::*,
|
||||
game,
|
||||
tilemap::{ChunkMap, VisibleGameEntity, CHUNK_SIZE},
|
||||
};
|
||||
use bevy::{math::ivec3, prelude::*};
|
||||
use bevy_rand::prelude::*;
|
||||
use rand::Rng;
|
||||
use std::{
|
||||
collections::{BinaryHeap, HashMap, HashSet},
|
||||
process::exit,
|
||||
};
|
||||
|
||||
#[derive(Bundle)]
|
||||
pub struct Citizen {
|
||||
@@ -34,14 +41,6 @@ impl Citizen {
|
||||
}
|
||||
}
|
||||
|
||||
use crate::constants::TILE_SIZE;
|
||||
use crate::tile::TileMap;
|
||||
use rand::{seq::IndexedRandom, Rng};
|
||||
use std::{
|
||||
collections::{BinaryHeap, HashMap, HashSet},
|
||||
process::exit,
|
||||
};
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Ambulatory {
|
||||
pub walk_speed: f32,
|
||||
@@ -86,43 +85,46 @@ pub fn update_citizen_wandering_targets(
|
||||
mut query: Query<(&mut Ambulatory, &Transform)>,
|
||||
tilemap: Res<TileMap>,
|
||||
chunk_map: Res<ChunkMap>,
|
||||
mut rng_q: Query<&mut Entropy<WyRand>, With<Global>>,
|
||||
) {
|
||||
let mut rng: rand::prelude::ThreadRng = rand::rng();
|
||||
if let Ok(mut rng) = rng_q.single_mut() {
|
||||
for (mut ambulatory, _) in query.iter_mut() {
|
||||
if ambulatory.target.is_none()
|
||||
|| (ambulatory.current_path.is_some()
|
||||
&& ambulatory.path_index >= ambulatory.current_path.as_ref().unwrap().len())
|
||||
{
|
||||
// Find a random loaded chunk
|
||||
let loaded_chunks: Vec<&IVec2> = chunk_map.loaded_chunks.keys().collect();
|
||||
if !loaded_chunks.is_empty() {
|
||||
let random_index = rng.random_range(0..loaded_chunks.len());
|
||||
if let Some(&chunk_pos) = loaded_chunks.get(random_index) {
|
||||
// Generate random position within chunk
|
||||
let chunk_x = chunk_pos.x * CHUNK_SIZE;
|
||||
let chunk_y = chunk_pos.y * CHUNK_SIZE;
|
||||
|
||||
for (mut ambulatory, _) in query.iter_mut() {
|
||||
if ambulatory.target.is_none()
|
||||
|| (ambulatory.current_path.is_some()
|
||||
&& ambulatory.path_index >= ambulatory.current_path.as_ref().unwrap().len())
|
||||
{
|
||||
// Find a random loaded chunk
|
||||
let loaded_chunks: Vec<&IVec2> = chunk_map.loaded_chunks.keys().collect();
|
||||
if let Some(&chunk_pos) = loaded_chunks.choose(&mut rng) {
|
||||
// Generate random position within chunk
|
||||
let chunk_x = chunk_pos.x * CHUNK_SIZE;
|
||||
let chunk_y = chunk_pos.y * CHUNK_SIZE;
|
||||
let target_x = chunk_x + rng.random_range(0..CHUNK_SIZE);
|
||||
let target_y = chunk_y + rng.random_range(0..CHUNK_SIZE);
|
||||
|
||||
let target_x = chunk_x + rng.random_range(0..CHUNK_SIZE);
|
||||
let target_y = chunk_y + rng.random_range(0..CHUNK_SIZE);
|
||||
// Get height at position
|
||||
let surface_height = 0;
|
||||
|
||||
// Get height at position
|
||||
let surface_height = 0;
|
||||
|
||||
// Find a valid z-level near the surface
|
||||
for z in (surface_height - 3)..=(surface_height + 4) {
|
||||
let mut target_pos = IVec3::new(target_x, target_y, z) * ITILE_SIZE;
|
||||
if let Some(_) = tilemap.floor_tiles.get(&target_pos) {
|
||||
target_pos.z += ITILE_SIZE;
|
||||
if let Some(_base_texture) = tilemap.floor_tiles.get(&target_pos) {
|
||||
if is_standable_tile(&tilemap, target_pos) {
|
||||
// If tile is walkable, set target
|
||||
ambulatory.target = Some(Vec3::new(
|
||||
target_pos.x as f32,
|
||||
target_pos.y as f32,
|
||||
target_pos.z as f32 + 1.0,
|
||||
));
|
||||
ambulatory.current_path = None;
|
||||
ambulatory.path_index = 0;
|
||||
break;
|
||||
// Find a valid z-level near the surface
|
||||
for z in (surface_height - 3)..=(surface_height + 4) {
|
||||
let mut target_pos = IVec3::new(target_x, target_y, z) * ITILE_SIZE;
|
||||
if let Some(_) = tilemap.floor_tiles.get(&target_pos) {
|
||||
target_pos.z += ITILE_SIZE;
|
||||
if let Some(_base_texture) = tilemap.floor_tiles.get(&target_pos) {
|
||||
if is_standable_tile(&tilemap, target_pos) {
|
||||
ambulatory.target = Some(Vec3::new(
|
||||
target_pos.x as f32,
|
||||
target_pos.y as f32,
|
||||
target_pos.z as f32 + 1.0,
|
||||
));
|
||||
ambulatory.current_path = None;
|
||||
ambulatory.path_index = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -430,22 +432,25 @@ fn reconstruct_path(came_from: HashMap<IVec3, IVec3>, mut current: IVec3) -> Vec
|
||||
path.reverse();
|
||||
path
|
||||
}
|
||||
|
||||
pub fn spawn_citizens(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
let mut rng = rand::rng();
|
||||
|
||||
// Spawn a handful of citizens
|
||||
for _ in 0..10 {
|
||||
let cit = commands
|
||||
.spawn(Citizen::new(
|
||||
&asset_server,
|
||||
Vec3::new(
|
||||
rng.random_range(-8.0f32..8.0f32).round(),
|
||||
rng.random_range(-8.0f32..8.0f32).round(),
|
||||
35.0,
|
||||
) * TILE_SIZE,
|
||||
))
|
||||
.id();
|
||||
commands.entity(cit).insert(VisibleGameEntity);
|
||||
pub fn spawn_citizens(
|
||||
mut commands: Commands,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut rng_q: Query<&mut Entropy<WyRand>, With<Global>>,
|
||||
) {
|
||||
if let Ok(mut rng) = rng_q.single_mut() {
|
||||
// Spawn a handful of citizens
|
||||
for _ in 0..10 {
|
||||
let cit = commands
|
||||
.spawn(Citizen::new(
|
||||
&asset_server,
|
||||
Vec3::new(
|
||||
rng.random_range(-8.0f32..8.0f32).round(),
|
||||
rng.random_range(-8.0f32..8.0f32).round(),
|
||||
35.0,
|
||||
) * TILE_SIZE,
|
||||
))
|
||||
.id();
|
||||
commands.entity(cit).insert(VisibleGameEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,3 +2,4 @@ pub const PIXEL_RATIO: f32 = 1.0;
|
||||
pub const TILE_PIXELS: u32 = 16;
|
||||
pub const TILE_SIZE: f32 = TILE_PIXELS as f32 * PIXEL_RATIO;
|
||||
pub const ITILE_SIZE: i32 = TILE_SIZE as i32;
|
||||
pub const SEED: u32 = 420;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_rand::prelude::*;
|
||||
|
||||
mod camera;
|
||||
mod citizen;
|
||||
@@ -30,6 +31,9 @@ fn main() {
|
||||
})
|
||||
.set(ImagePlugin::default_nearest()),
|
||||
)
|
||||
.add_plugins(bevy_rand::plugin::EntropyPlugin::<WyRand>::with_seed(
|
||||
(constants::SEED as u64).to_le_bytes(),
|
||||
))
|
||||
.insert_resource(ClearColor(Color::srgb(0., 0., 0.)))
|
||||
.add_plugins(tilemap::TilemapPlugin)
|
||||
.add_plugins(citizen::PathfindingPlugin)
|
||||
|
||||
+17
-8
@@ -1,7 +1,7 @@
|
||||
use std::sync::Mutex;
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::constants::{ITILE_SIZE, TILE_SIZE};
|
||||
use crate::constants::{self, ITILE_SIZE, TILE_SIZE};
|
||||
use crate::tile::{update_tile_visibility, FloorTile, TileMap};
|
||||
use crate::tiles::{
|
||||
self, build_quilted_terrain_sprites, CurrentWorldSpriteState, FixtureTilePrefab,
|
||||
@@ -11,7 +11,11 @@ use crate::{camera, game};
|
||||
use bevy::prelude::*;
|
||||
use bevy_platform::collections::hash_map::HashMap;
|
||||
use bevy_platform::collections::HashSet;
|
||||
use bevy_rand::prelude::*;
|
||||
use noise::{NoiseFn, Perlin};
|
||||
use rand::{Rng, SeedableRng};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
pub const CHUNK_SIZE: i32 = 8;
|
||||
|
||||
@@ -21,8 +25,6 @@ pub const Z_TOTAL: f32 = Z_ABOVE + Z_BELOW;
|
||||
|
||||
const _: () = assert!(Z_TOTAL <= 255.0);
|
||||
|
||||
pub const SEED: u32 = 420;
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct ChunkMap {
|
||||
pub loaded_chunks: HashMap<IVec2, (bool, i32)>,
|
||||
@@ -180,7 +182,7 @@ pub fn calculate_visibility(pos: IVec3, tilemap: &TileMap) -> [u32; 8] {
|
||||
}
|
||||
|
||||
pub fn generate_surface_terrain(x: i32, y: i32) -> f32 {
|
||||
let noise = Perlin::new(SEED);
|
||||
let noise = Perlin::new(constants::SEED);
|
||||
let mut noise_value = 0.0;
|
||||
let mut amplitude = 1.0;
|
||||
let mut frequency = 0.008;
|
||||
@@ -264,7 +266,7 @@ fn generate_chunk_terrain(
|
||||
let start = Instant::now();
|
||||
let count: usize = events.len();
|
||||
|
||||
let cave_noise = Perlin::new(SEED);
|
||||
let cave_noise = Perlin::new(constants::SEED);
|
||||
|
||||
// Create mutexes for our shared resources
|
||||
let tilemap_updates = Mutex::new(HashMap::new());
|
||||
@@ -418,6 +420,13 @@ fn generate_chunk_forrestry(
|
||||
let mut tree_positions: Vec<Vec3> = Vec::new();
|
||||
let min_distance = 7.0 * TILE_SIZE;
|
||||
|
||||
let mut hasher = DefaultHasher::new();
|
||||
constants::SEED.hash(&mut hasher);
|
||||
event.chunk_position.x.hash(&mut hasher);
|
||||
event.chunk_position.y.hash(&mut hasher);
|
||||
let seed = hasher.finish();
|
||||
let mut rng = WyRand::seed_from_u64(seed);
|
||||
|
||||
for (position, floor_type) in floor_positions.iter() {
|
||||
let above_pos = *position + Vec3::new(0.0, 0.0, TILE_SIZE);
|
||||
|
||||
@@ -433,9 +442,9 @@ fn generate_chunk_forrestry(
|
||||
.all(|&tree_pos| above_pos.distance(tree_pos) > min_distance);
|
||||
|
||||
// 1 in 100 chance if far enough from other trees
|
||||
if is_far_enough && rand::random::<u32>() % 100 == 0 {
|
||||
if is_far_enough && rng.random::<u32>() % 100 == 0 {
|
||||
// Generate trunk
|
||||
let trunk_height = 4 + rand::random::<u32>() % 5;
|
||||
let trunk_height = 4 + rng.random::<u32>() % 5;
|
||||
for i in 0..trunk_height {
|
||||
let trunk_pos =
|
||||
above_pos + Vec3::new(0.0, 0.0, i as f32 * TILE_SIZE);
|
||||
@@ -499,7 +508,7 @@ fn generate_chunk_forrestry(
|
||||
let y_f = y as f32;
|
||||
let z_f = z as f32;
|
||||
let radius = base_leaf_radius
|
||||
* (1.0 + (rand::random::<f32>() * 0.35 - 0.1));
|
||||
* (1.0 + (rng.random::<f32>() * 0.35 - 0.1));
|
||||
|
||||
if x_f * x_f + y_f * y_f + z_f * z_f <= radius * radius {
|
||||
FixtureTilePrefab::leaves(pos).spawn(&mut commands);
|
||||
|
||||
Reference in New Issue
Block a user