add trees
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 817 B |
+15
-8
@@ -204,18 +204,25 @@ pub fn citizen_movement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_standable_tile(tilemap: &TileMap, pos: IVec3) -> bool {
|
fn is_standable_tile(tilemap: &TileMap, pos: IVec3) -> bool {
|
||||||
// Check if the tile at current position is not blocking
|
// Check if current position has a blocking floor tile
|
||||||
if let Some(current_tile) = tilemap.floor_tiles.get(&pos) {
|
if let Some(current_tile) = tilemap.floor_tiles.get(&pos) {
|
||||||
if current_tile.0 != 0 {
|
return current_tile.0 == 0;
|
||||||
return false;
|
}
|
||||||
}
|
// Check if current position has a solid fixture tile (e.g., log, leaf)
|
||||||
|
if let Some(current_tile) = tilemap.fixture_tiles.get(&pos) {
|
||||||
|
return current_tile.0 == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there's solid ground below
|
// Check if there's solid ground below (fixture or floor)
|
||||||
let pos_below = pos - IVec3::new(0, 0, ITILE_SIZE);
|
let pos_below = pos - IVec3::new(0, 0, ITILE_SIZE);
|
||||||
|
|
||||||
if let Some(below_tile) = tilemap.floor_tiles.get(&pos_below) {
|
if let Some(below_tile) = tilemap.floor_tiles.get(&pos_below) {
|
||||||
return below_tile.0 != 0;
|
return below_tile.0 != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(below_tile) = tilemap.fixture_tiles.get(&pos_below) {
|
||||||
|
return below_tile.0 != 0;
|
||||||
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,9 +391,9 @@ pub fn spawn_citizens(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
let mut rng = rand::rng();
|
let mut rng = rand::rng();
|
||||||
|
|
||||||
// Spawn a handful of citizens
|
// Spawn a handful of citizens
|
||||||
for _ in 0..100 {
|
for _ in 0..1000 {
|
||||||
let x: f32 = rng.random_range(-5.0..5.0);
|
let x: f32 = rng.random_range(-35.0..35.0);
|
||||||
let y: f32 = rng.random_range(-5.0..5.0);
|
let y: f32 = rng.random_range(-35.0..35.0);
|
||||||
let mut position = Vec3::new(x.round(), y.round(), 35.0) * TILE_SIZE;
|
let mut position = Vec3::new(x.round(), y.round(), 35.0) * TILE_SIZE;
|
||||||
position.z += 0.1;
|
position.z += 0.1;
|
||||||
|
|
||||||
|
|||||||
+107
-25
@@ -10,12 +10,13 @@ use crate::tiles::{
|
|||||||
use crate::{camera, game};
|
use crate::{camera, game};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_platform::collections::hash_map::HashMap;
|
use bevy_platform::collections::hash_map::HashMap;
|
||||||
|
use bevy_platform::collections::HashSet;
|
||||||
use noise::{NoiseFn, Perlin};
|
use noise::{NoiseFn, Perlin};
|
||||||
|
|
||||||
pub const CHUNK_SIZE: i32 = 8;
|
pub const CHUNK_SIZE: i32 = 8;
|
||||||
|
|
||||||
pub const Z_BELOW: f32 = 10.0;
|
pub const Z_BELOW: f32 = 10.0;
|
||||||
pub const Z_ABOVE: f32 = 8.0;
|
pub const Z_ABOVE: f32 = 15.0;
|
||||||
pub const Z_TOTAL: f32 = Z_ABOVE + Z_BELOW; // MAX 255 DO NOT EXCEED
|
pub const Z_TOTAL: f32 = Z_ABOVE + Z_BELOW; // MAX 255 DO NOT EXCEED
|
||||||
|
|
||||||
pub const SEED: u32 = 420;
|
pub const SEED: u32 = 420;
|
||||||
@@ -390,7 +391,7 @@ fn generate_chunk_forrestry(
|
|||||||
|
|
||||||
events.par_read().for_each(|event| {
|
events.par_read().for_each(|event| {
|
||||||
let floor_positions = &event.floor_tiles;
|
let floor_positions = &event.floor_tiles;
|
||||||
let mut tree_positions: Vec<Vec3> = Vec::new();
|
let tree_positions: Vec<Vec3> = Vec::new();
|
||||||
let min_distance = 7.0 * TILE_SIZE;
|
let min_distance = 7.0 * TILE_SIZE;
|
||||||
|
|
||||||
for (position, floor_type) in floor_positions.iter() {
|
for (position, floor_type) in floor_positions.iter() {
|
||||||
@@ -400,32 +401,113 @@ fn generate_chunk_forrestry(
|
|||||||
match floor_type.as_str() {
|
match floor_type.as_str() {
|
||||||
"grass" => {
|
"grass" => {
|
||||||
commands.command_scope(|mut commands| {
|
commands.command_scope(|mut commands| {
|
||||||
|
// Track log positions to avoid leaf overlap
|
||||||
|
let mut log_positions = HashSet::new();
|
||||||
|
|
||||||
// Check if position is far enough from existing trees
|
// Check if position is far enough from existing trees
|
||||||
let is_far_enough = tree_positions
|
let is_far_enough = tree_positions
|
||||||
.iter()
|
.iter()
|
||||||
.all(|&tree_pos| above_pos.distance(tree_pos) > min_distance);
|
.all(|&tree_pos| above_pos.distance(tree_pos) > min_distance);
|
||||||
|
|
||||||
// 1 in 25 chance if far enough from other trees
|
// 1 in 65 chance if far enough from other trees
|
||||||
if is_far_enough && rand::random::<u32>() % 45 == 0 {
|
if is_far_enough && rand::random::<u32>() % 65 == 0 {
|
||||||
FixtureTilePrefab::log(above_pos).spawn(&mut commands);
|
// Generate trunk
|
||||||
if let Some(texture_id) = texture_ids.refs.get(&500004) {
|
let trunk_height = 3 + rand::random::<u32>() % 4;
|
||||||
if let Some(texture) = textures.handles.get(texture_id) {
|
for i in 0..trunk_height {
|
||||||
let sprite = Sprite {
|
let trunk_pos =
|
||||||
image: texture.clone(),
|
above_pos + Vec3::new(0.0, 0.0, i as f32 * TILE_SIZE);
|
||||||
..Default::default()
|
let trunk_ivec = trunk_pos.as_ivec3();
|
||||||
};
|
|
||||||
let log = commands
|
// Skip if position already has a tile
|
||||||
.spawn((
|
if tilemap.fixture_tiles.get(&trunk_ivec).is_some() {
|
||||||
sprite,
|
continue;
|
||||||
Transform::from_xyz(
|
}
|
||||||
above_pos.x,
|
|
||||||
above_pos.y,
|
FixtureTilePrefab::log(trunk_pos).spawn(&mut commands);
|
||||||
above_pos.z,
|
if let Some(texture_id) = texture_ids.refs.get(&500004) {
|
||||||
),
|
if let Some(texture) = textures.handles.get(texture_id) {
|
||||||
))
|
let sprite = Sprite {
|
||||||
.id();
|
image: texture.clone(),
|
||||||
commands.entity(log).insert(VisibleGameEntity);
|
..Default::default()
|
||||||
tree_positions.push(above_pos);
|
};
|
||||||
|
let log = commands
|
||||||
|
.spawn((
|
||||||
|
sprite,
|
||||||
|
Transform::from_xyz(
|
||||||
|
trunk_pos.x,
|
||||||
|
trunk_pos.y,
|
||||||
|
trunk_pos.z,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.id();
|
||||||
|
commands.entity(log).insert(VisibleGameEntity);
|
||||||
|
collected_tilemap_updates
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.push((trunk_ivec, (1, true, [0; 8])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_positions.insert(trunk_ivec);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate leaves - 3D spherical canopy with random shape
|
||||||
|
let base_leaf_radius = 3.0;
|
||||||
|
let leaf_center =
|
||||||
|
above_pos + Vec3::new(0.0, 0.0, trunk_height as f32 * TILE_SIZE);
|
||||||
|
|
||||||
|
for x in -base_leaf_radius as i32..=base_leaf_radius as i32 {
|
||||||
|
for y in -base_leaf_radius as i32..=base_leaf_radius as i32 {
|
||||||
|
for z in -base_leaf_radius as i32..=base_leaf_radius as i32 {
|
||||||
|
let pos = Vec3::new(
|
||||||
|
x as f32 * TILE_SIZE,
|
||||||
|
y as f32 * TILE_SIZE,
|
||||||
|
z as f32 * TILE_SIZE,
|
||||||
|
) + leaf_center;
|
||||||
|
let ivec = pos.as_ivec3();
|
||||||
|
|
||||||
|
// Skip if position already has a tile or is a log
|
||||||
|
if tilemap.fixture_tiles.get(&ivec).is_some()
|
||||||
|
|| log_positions.contains(&ivec)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply random radius variation for natural shape
|
||||||
|
let x_f = x as f32;
|
||||||
|
let y_f = y as f32;
|
||||||
|
let z_f = z as f32;
|
||||||
|
let radius = base_leaf_radius
|
||||||
|
* (1.0 + (rand::random::<f32>() * 0.2 - 0.1));
|
||||||
|
|
||||||
|
if x_f * x_f + y_f * y_f + z_f * z_f <= radius * radius {
|
||||||
|
FixtureTilePrefab::leaves(pos).spawn(&mut commands);
|
||||||
|
if let Some(texture_id) = texture_ids.refs.get(&500005)
|
||||||
|
{
|
||||||
|
if let Some(texture) =
|
||||||
|
textures.handles.get(texture_id)
|
||||||
|
{
|
||||||
|
let sprite = Sprite {
|
||||||
|
image: texture.clone(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let leaf = commands
|
||||||
|
.spawn((
|
||||||
|
sprite,
|
||||||
|
Transform::from_xyz(
|
||||||
|
pos.x, pos.y, pos.z,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.id();
|
||||||
|
commands.entity(leaf).insert(VisibleGameEntity);
|
||||||
|
collected_tilemap_updates
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.push((ivec, (5, true, [1; 8])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -471,8 +553,8 @@ fn generate_chunk_fauna(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn setup_initial_chunks(mut event_writer: EventWriter<GenerateChunkEvent>) {
|
fn setup_initial_chunks(mut event_writer: EventWriter<GenerateChunkEvent>) {
|
||||||
for x in -8..=8 {
|
for x in -10..=10 {
|
||||||
for y in -5..=5 {
|
for y in -10..=10 {
|
||||||
event_writer.write(GenerateChunkEvent {
|
event_writer.write(GenerateChunkEvent {
|
||||||
chunk_position: IVec2::new(x, y),
|
chunk_position: IVec2::new(x, y),
|
||||||
});
|
});
|
||||||
|
|||||||
+15
-1
@@ -30,6 +30,7 @@ const DIRT_WALL_PATH: &str = "dirt_wall.png";
|
|||||||
const ROCK_WALL_PATH: &str = "rock_wall.png";
|
const ROCK_WALL_PATH: &str = "rock_wall.png";
|
||||||
const BEDROCK_WALL_PATH: &str = "bedrock_wall.png";
|
const BEDROCK_WALL_PATH: &str = "bedrock_wall.png";
|
||||||
const LOG_PATH: &str = "log.png";
|
const LOG_PATH: &str = "log.png";
|
||||||
|
const LEAVES_PATH: &str = "leaves.png";
|
||||||
|
|
||||||
pub fn initialize_textures(mut commands: Commands, asset_server: Res<AssetServer>) {
|
pub fn initialize_textures(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
let mut textures: HashMap<String, Handle<Image>> = HashMap::new();
|
let mut textures: HashMap<String, Handle<Image>> = HashMap::new();
|
||||||
@@ -76,6 +77,8 @@ pub fn initialize_textures(mut commands: Commands, asset_server: Res<AssetServer
|
|||||||
);
|
);
|
||||||
texture_ids.insert(FIXTURE_ID_OFFSET + 4, LOG_PATH.to_string());
|
texture_ids.insert(FIXTURE_ID_OFFSET + 4, LOG_PATH.to_string());
|
||||||
textures.insert(LOG_PATH.to_string(), asset_server.load(LOG_PATH));
|
textures.insert(LOG_PATH.to_string(), asset_server.load(LOG_PATH));
|
||||||
|
texture_ids.insert(FIXTURE_ID_OFFSET + 5, LEAVES_PATH.to_string());
|
||||||
|
textures.insert(LEAVES_PATH.to_string(), asset_server.load(LEAVES_PATH));
|
||||||
|
|
||||||
commands.insert_resource(Textures { handles: textures });
|
commands.insert_resource(Textures { handles: textures });
|
||||||
commands.insert_resource(TextureIDs { refs: texture_ids });
|
commands.insert_resource(TextureIDs { refs: texture_ids });
|
||||||
@@ -527,7 +530,18 @@ impl FixtureTilePrefab {
|
|||||||
FixtureTilePrefab {
|
FixtureTilePrefab {
|
||||||
transform: Transform::from_translation(position),
|
transform: Transform::from_translation(position),
|
||||||
tile: FixtureTile {
|
tile: FixtureTile {
|
||||||
id: FIXTURE_ID_OFFSET + 3,
|
id: FIXTURE_ID_OFFSET + 4,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
visibility: Visibility::Hidden,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn leaves(position: Vec3) -> Self {
|
||||||
|
FixtureTilePrefab {
|
||||||
|
transform: Transform::from_translation(position),
|
||||||
|
tile: FixtureTile {
|
||||||
|
id: FIXTURE_ID_OFFSET + 5,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
visibility: Visibility::Hidden,
|
visibility: Visibility::Hidden,
|
||||||
|
|||||||
Reference in New Issue
Block a user