This commit is contained in:
Arkitu 2025-06-27 16:14:55 +02:00
parent 6c74ed9272
commit b4ca8bb032
7 changed files with 51 additions and 68 deletions

View File

@ -1,4 +1,4 @@
use bevy::{prelude::*, render::camera::ScalingMode};
use bevy::prelude::*;
pub struct Plugin;
impl bevy::prelude::Plugin for Plugin {
@ -10,7 +10,7 @@ impl bevy::prelude::Plugin for Plugin {
#[derive(Component)]
pub struct CameraMarker;
fn setup(mut cmds: Commands, window: Query<&Window>) {
fn setup(mut cmds: Commands) {
cmds.spawn((
CameraMarker,
Camera3d {

View File

@ -1,14 +1,8 @@
use core::f32;
use std::time::Duration;
use bevy::{
asset::RenderAssetUsages,
pbr::MaterialExtension,
picking::PickSet,
prelude::*,
render::mesh::{Indices, PrimitiveTopology},
tasks::AsyncComputeTaskPool,
utils::HashMap,
};
use noise::{Fbm, MultiFractal, NoiseFn, Perlin};
use rand::{thread_rng, Rng, SeedableRng};
@ -25,10 +19,7 @@ use cells::{
};
use picking::*;
use crate::{
map::cells::grow::{grow_thread, GrowThread},
time::GameTime,
};
use crate::{map::cells::grow::GrowThread, time::GameTime};
pub struct Plugin;
impl bevy::prelude::Plugin for Plugin {
@ -238,7 +229,6 @@ fn setup(
))
.with_children(|parent| {
for cell in ch_cells {
let kind = cell.kind;
// let id = cell.voronoi_id;
let mut cmd = parent.spawn(cell.clone());
// if let Some(ch) = hybrid_cells.get(&id) {
@ -300,12 +290,12 @@ fn update_chunk_mesh(
/// Between 0 and 1
fn get_altitude(z_noise: &Fbm<Perlin>, pos: &[f32; 2]) -> f32 {
let z_noise = ((z_noise.get([pos[0] as f64, pos[1] as f64]) as f32) + 1.) / 2.; // Noise [0; 1]
(
-0.2// Arbitrary value
+ (z_noise.exp() / 1f32.exp())
// Noise + [0; 1]
// - ((pos[0].powi(2)+pos[1].powi(2)).sqrt()*0.3)
// Distance - [0; sqrt(2)] * 0.5
)
// .clamp(-1., 1.)
}

View File

@ -1,14 +1,8 @@
use std::time::Duration;
use bevy::{prelude::*, time::common_conditions::on_timer};
use rand::{seq::IteratorRandom, thread_rng, Rng};
use bevy::prelude::*;
use crate::{time::GameTime, ui::CurrentAction};
use super::{
animals::Animal, AnimalKind, CellsEntities, MeshMarker, MeshNeedsUpdate, Voronoi,
AVERAGE_NEIGHBORS_NUMBER, CELLS_PER_CHUNK, CELL_AREA,
};
use super::{AnimalKind, CELLS_PER_CHUNK, CELL_AREA};
pub mod grow;
pub mod input;
@ -25,7 +19,8 @@ impl bevy::prelude::Plugin for Plugin {
// expand.run_if(on_timer(Duration::from_millis(300))),
// ),
// )
app.add_plugins(MaterialPlugin::<CellMaterial>::default());
app.add_plugins(MaterialPlugin::<CellMaterial>::default())
.add_plugins(grow::Plugin);
}
}
@ -44,7 +39,7 @@ impl CellKind {
pub const fn growth_duration(&self) -> u64 {
match self {
CellKind::Forest { .. } => 100 * 365 * 24 * 60 * 60, // a forest takes 100 years to mature
CellKind::Grass { .. } => (7 * 7 * 24 * 60 * 60), // grass takes 7 weeks to reach its max
CellKind::Grass { .. } => 7 * 7 * 24 * 60 * 60, // grass takes 7 weeks to reach its max
_ => unreachable!(),
}
}

View File

@ -2,21 +2,22 @@ use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use bevy::prelude::*;
use bevy::tasks::futures_lite::{future, FutureExt};
use bevy::tasks::{block_on, AsyncComputeTaskPool, IoTaskPool, Task};
use bevy::tasks::{AsyncComputeTaskPool, Task};
use rand::rngs::SmallRng;
use rand::seq::IteratorRandom;
use rand::Rng;
use voronoice::Voronoi;
use crate::map::cells::{wealth_to_unit, WealthType};
use crate::map::{CellKind, CellsEntities, Chunk, MeshNeedsUpdate};
use crate::map::{CellKind, CellsEntities, MeshNeedsUpdate};
use super::Cell;
pub struct Plugin;
impl bevy::prelude::Plugin for Plugin {
fn build(&self, app: &mut App) {}
fn build(&self, app: &mut App) {
app.add_systems(Update, rx_chunks_updates);
}
}
// Background task that manages terrain
@ -27,7 +28,7 @@ pub struct GrowThread(
pub async_channel::Receiver<Cell>,
);
impl GrowThread {
pub fn new(voronoi: Voronoi, gt: Arc<AtomicU64>, cells: Vec<Cell>, mut rng: SmallRng) -> Self {
pub fn new(voronoi: Voronoi, gt: Arc<AtomicU64>, cells: Vec<Cell>, rng: SmallRng) -> Self {
let task_pool = AsyncComputeTaskPool::get();
let (tx_control, rx_control) = async_channel::unbounded();
let (tx_update, rx_update) = async_channel::unbounded();
@ -39,13 +40,11 @@ impl GrowThread {
}
}
#[derive(Component)]
struct GetChunkTask(Task<Vec<Cell>>);
fn start_grow_task(mut cmds: Commands) {}
// #[derive(Component)]
// struct GetChunkTask(Task<Vec<Cell>>);
fn rx_chunks_updates(
mut chunks: Query<(&mut MeshNeedsUpdate)>,
mut chunks: Query<&mut MeshNeedsUpdate>,
mut cells: Query<(&mut Cell, &Parent)>,
cells_entities: Res<CellsEntities>,
grow_thread: Res<GrowThread>,
@ -54,7 +53,7 @@ fn rx_chunks_updates(
let id = c.voronoi_id;
let (mut cell, parent) = cells.get_mut(cells_entities.0[id]).unwrap();
*cell = c;
chunks.get(parent.get()).unwrap().0 = true;
chunks.get_mut(parent.get()).unwrap().0 = true;
}
}
@ -63,10 +62,10 @@ const FOREST_EXTEND_STEP: u64 = CellKind::FOREST.growth_duration();
pub async fn grow_thread(
voronoi: Voronoi,
gt: Arc<AtomicU64>,
mut cells: Vec<Cell>,
cells: Vec<Cell>,
mut rng: SmallRng,
mut rx_control: async_channel::Receiver<Cell>,
mut tx_update: async_channel::Sender<Cell>,
rx_control: async_channel::Receiver<Cell>,
tx_update: async_channel::Sender<Cell>,
) {
// Add "modified" flag
let mut cells: Vec<(Cell, bool)> = cells.into_iter().map(|c| (c, false)).collect();
@ -84,19 +83,19 @@ pub async fn grow_thread(
let gt = gt.load(Ordering::Acquire);
// Update step
let grass_grow = ((gt - last_grass_grow) / CellKind::GRASS.growth_duration()) as usize;
let forest_grow = ((gt - last_forest_grow) / CellKind::FOREST.growth_duration()) as usize;
let grass_grow = (gt - last_grass_grow) / CellKind::GRASS.growth_duration();
let forest_grow = (gt - last_forest_grow) / CellKind::FOREST.growth_duration();
if grass_grow > 0 || forest_grow > 0 {
for (c, modified) in cells.iter_mut() {
if grass_grow > 0 {
if let CellKind::Grass { mut wealth } = c.kind {
wealth = wealth.saturating_add(grass_grow as WealthType);
if let CellKind::Grass { ref mut wealth } = c.kind {
*wealth = wealth.saturating_add(grass_grow as WealthType);
*modified = true;
}
}
if forest_grow > 0 {
if let CellKind::Forest { mut wealth } = c.kind {
wealth = wealth.saturating_add(forest_grow as WealthType);
if let CellKind::Forest { ref mut wealth } = c.kind {
*wealth = wealth.saturating_add(forest_grow as WealthType);
*modified = true;
}
}
@ -107,11 +106,11 @@ pub async fn grow_thread(
if !cells[i].1 {
if let Some(wealth) = cells[i].0.kind.grass_wealth() {
if rng.gen_bool(wealth_to_unit(wealth) as f64) {
let mut target = &mut cells
let target = &mut cells
[voronoi.cell(i).iter_neighbors().choose(&mut rng).unwrap()];
if matches!(target.0.kind, CellKind::Dirt) {
target.0.kind == CellKind::Grass { wealth: 0 };
target.0.kind = CellKind::Grass { wealth: 0 };
target.1 = true;
}
}
@ -123,16 +122,15 @@ pub async fn grow_thread(
if !cells[i].1 {
if let CellKind::Forest { wealth } = cells[i].0.kind {
if rng.gen_bool(wealth_to_unit(wealth) as f64) {
let mut target = &mut cells
let target = &mut cells
[voronoi.cell(i).iter_neighbors().choose(&mut rng).unwrap()];
match target.0.kind {
CellKind::Dirt => {
target.0.kind == CellKind::Forest { wealth: 0 };
target.0.kind = CellKind::Forest { wealth: 0 };
target.1 = true;
}
CellKind::Grass { wealth: w } => {
target.0.kind
== CellKind::Forest {
target.0.kind = CellKind::Forest {
wealth: (w as f32
* CellKind::GRASS.growth_duration() as f32
/ CellKind::FOREST.growth_duration() as f32)
@ -148,9 +146,14 @@ pub async fn grow_thread(
}
}
last_grass_grow += grass_grow * CellKind::GRASS.growth_duration();
last_forest_grow += forest_grow * CellKind::FOREST.growth_duration();
last_grass_extend += GRASS_EXTEND_STEP;
last_forest_extend += FOREST_EXTEND_STEP;
// Send modifications
for (c, _) in cells.iter().filter(|(_, m)| *m) {
tx_update.send(c.clone()).await;
tx_update.send(c.clone()).await.unwrap();
}
}
}

View File

@ -4,7 +4,6 @@ use bevy::prelude::*;
use crate::{
map::{animals::Animal, MeshMarker, MeshNeedsUpdate, Voronoi},
time::GameTime,
ui::CurrentAction,
};
@ -17,7 +16,6 @@ pub fn on_click(
mut chunks: Query<&mut MeshNeedsUpdate, With<MeshMarker>>,
mut cmds: Commands,
ca: Res<CurrentAction>,
gt: Res<GameTime>,
) {
if trigger.duration > Duration::from_millis(200) {
return;

View File

@ -8,7 +8,7 @@ use bevy::{
};
use voronoice::Point;
use super::{CellsEntities, MeshMarker, Voronoi};
use super::{CellsEntities, Voronoi};
use crate::camera::CameraMarker;
pub fn picking_backend(

View File

@ -5,7 +5,6 @@ use bevy::{
picking::{focus::HoverMap, pointer::PointerId},
prelude::*,
utils::HashMap,
window::PrimaryWindow,
};
use mevy::*;
@ -190,7 +189,6 @@ fn zoom_with_scroll(
mut cam: Query<&mut Transform, With<CameraMarker>>,
mut ev_scroll: EventReader<MouseWheel>,
hover_map: Res<HoverMap>,
window: Query<&Window, With<PrimaryWindow>>,
map_ui_id: Query<Entity, With<MapUIComponent>>,
) {
let map_ui_id = map_ui_id.single();
@ -199,7 +197,6 @@ fn zoom_with_scroll(
.and_then(|hovered_ids| hovered_ids.get(&map_ui_id))
.is_some()
{
let window = window.single();
let mut cam = cam.single_mut();
for ev in ev_scroll.read() {
let forward = cam.forward();