mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Basic town house generation
This commit is contained in:
parent
fd3ffdf28b
commit
8499143f77
@ -14,8 +14,12 @@ use common::{
|
||||
store::{Id, Store},
|
||||
path::Path,
|
||||
astar::Astar,
|
||||
spiral::Spiral2d,
|
||||
};
|
||||
use crate::{
|
||||
sim::{WorldSim, SimChunk},
|
||||
site::{Site as WorldSite, Settlement},
|
||||
};
|
||||
use crate::sim::{WorldSim, SimChunk};
|
||||
|
||||
const CARDINALS: [Vec2<i32>; 4] = [
|
||||
Vec2::new(1, 0),
|
||||
@ -79,10 +83,22 @@ impl Civs {
|
||||
// Temporary!
|
||||
for track in this.tracks.iter() {
|
||||
for loc in track.path.iter() {
|
||||
sim.get_mut(*loc).unwrap().place = Some(this.civs.iter().next().unwrap().homeland);
|
||||
ctx.sim.get_mut(*loc).unwrap().place = Some(this.civs.iter().next().unwrap().homeland);
|
||||
}
|
||||
}
|
||||
|
||||
// Place sites in world
|
||||
for site in this.sites.iter() {
|
||||
let wpos = site.center * Vec2::from(TerrainChunkSize::RECT_SIZE).map(|e: u32| e as i32);
|
||||
let settlement = WorldSite::from(Settlement::generate(wpos, Some(ctx.sim), ctx.rng));
|
||||
for pos in Spiral2d::new().map(|offs| site.center + offs).take(32usize.pow(2)) {
|
||||
ctx.sim
|
||||
.get_mut(pos)
|
||||
.map(|chunk| chunk.sites.push(settlement.clone()));
|
||||
}
|
||||
println!("Placed site at {:?}", site.center);
|
||||
}
|
||||
|
||||
this.display_info();
|
||||
|
||||
this
|
||||
|
@ -1451,6 +1451,7 @@ impl WorldSim {
|
||||
*/
|
||||
|
||||
// Stage 2 - towns!
|
||||
/*
|
||||
let chunk_idx_center = |e: Vec2<i32>| {
|
||||
e.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| {
|
||||
e * sz as i32 + sz as i32 / 2
|
||||
@ -1464,12 +1465,9 @@ impl WorldSim {
|
||||
chunk_idx_center(WORLD_SIZE.map(|e| e as i32)),
|
||||
)
|
||||
.map_init(
|
||||
|| Box::new(BlockGen::new(ColumnGen::new(self))),
|
||||
|mut block_gen, (pos, seed)| {
|
||||
|| (),
|
||||
|_, (pos, seed)| {
|
||||
let mut rng = ChaChaRng::from_seed(seed_expan::rng_state(seed));
|
||||
// println!("Town: {:?}", town);
|
||||
//TownState::generate(pos, &mut block_gen, &mut rng).map(|t| (pos,
|
||||
// Arc::new(t)))
|
||||
(
|
||||
pos,
|
||||
Site::from(Settlement::generate(pos, Some(self), &mut rng)),
|
||||
@ -1496,6 +1494,7 @@ impl WorldSim {
|
||||
chunk.sites.push(site.clone());
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
// Create waypoints
|
||||
const WAYPOINT_EVERY: usize = 16;
|
||||
|
@ -52,7 +52,7 @@ impl Archetype for House {
|
||||
let empty = Some(Some(Block::empty()));
|
||||
|
||||
let ceil_height = 6;
|
||||
let width = 3 + branch.locus + if profile.y >= ceil_height { 1 } else { 0 };
|
||||
let width = -3 + branch.locus + if profile.y >= ceil_height { 1 } else { 0 };
|
||||
let foundation_height = 0 - (dist - width - 1).max(0);
|
||||
let roof_height = 8 + width;
|
||||
|
||||
@ -115,7 +115,7 @@ impl Archetype for House {
|
||||
};
|
||||
|
||||
// Window
|
||||
if (frame_bounds.size() + 1).reduce_min() > 2 {
|
||||
if (frame_bounds.size() + 1).reduce_min() > 2 { // Window frame is large enough for a window
|
||||
let surface_pos = Vec2::new(bound_offset.x, profile.y);
|
||||
if window_bounds.contains_point(surface_pos) {
|
||||
return empty;
|
||||
|
@ -30,12 +30,12 @@ impl<A: Archetype> Building<A> {
|
||||
root: Branch {
|
||||
len,
|
||||
attr: A::Attr::default(),
|
||||
locus: 2 + rng.gen_range(0, 5),
|
||||
locus: 8 + rng.gen_range(0, 5),
|
||||
children: (0..rng.gen_range(0, 4))
|
||||
.map(|_| (rng.gen_range(0, len + 1), Branch {
|
||||
.map(|_| (rng.gen_range(-5, len + 5).clamped(0, len.max(1) - 1), Branch {
|
||||
len: rng.gen_range(5, 12) * if rng.gen() { 1 } else { -1 },
|
||||
attr: A::Attr::default(),
|
||||
locus: 1 + rng.gen_range(0, 3),
|
||||
locus: 8 + rng.gen_range(0, 3),
|
||||
children: Vec::new(),
|
||||
}))
|
||||
.collect(),
|
||||
@ -49,8 +49,8 @@ impl<A: Archetype> Building<A> {
|
||||
pub fn bounds_2d(&self) -> Aabr<i32> {
|
||||
let b = self.skel.bounds();
|
||||
Aabr {
|
||||
min: Vec2::from(self.origin) + b.min - 14,
|
||||
max: Vec2::from(self.origin) + b.max + 14,
|
||||
min: Vec2::from(self.origin) + b.min,
|
||||
max: Vec2::from(self.origin) + b.max,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,8 +52,12 @@ impl<T> Skeleton<T> {
|
||||
pub fn bounds(&self) -> Aabr<i32> {
|
||||
let mut bounds = Aabr::new_empty(self.ori.dir() * self.offset);
|
||||
self.for_each(|node, ori, branch| {
|
||||
bounds.expand_to_contain(Aabr::new_empty(node - ori.flip().dir() * branch.locus)
|
||||
.expanded_to_contain_point(node + ori.dir() * branch.len + ori.flip().dir() * branch.locus));
|
||||
let node2 = node + ori.dir() * branch.len;
|
||||
|
||||
let a = node.map2(node2, |a, b| a.min(b)) - branch.locus;
|
||||
let b = node.map2(node2, |a, b| a.max(b)) + branch.locus;
|
||||
bounds.expand_to_contain_point(a);
|
||||
bounds.expand_to_contain_point(b);
|
||||
});
|
||||
bounds
|
||||
}
|
||||
|
@ -89,6 +89,14 @@ pub struct Structure {
|
||||
kind: StructureKind,
|
||||
}
|
||||
|
||||
impl Structure {
|
||||
pub fn bounds_2d(&self) -> Aabr<i32> {
|
||||
match &self.kind {
|
||||
StructureKind::House(house) => house.bounds_2d(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Settlement {
|
||||
origin: Vec2<i32>,
|
||||
land: Land,
|
||||
@ -128,7 +136,7 @@ impl Settlement {
|
||||
//this.place_river(rng);
|
||||
|
||||
this.place_farms(&mut ctx);
|
||||
this.place_town(ctx.rng);
|
||||
this.place_town(&mut ctx);
|
||||
this.place_paths(ctx.rng);
|
||||
|
||||
this
|
||||
@ -229,10 +237,10 @@ impl Settlement {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn place_town(&mut self, rng: &mut impl Rng) {
|
||||
pub fn place_town(&mut self, ctx: &mut GenCtx<impl Rng>) {
|
||||
const PLOT_COUNT: usize = 2;
|
||||
|
||||
let mut origin = Vec2::new(rng.gen_range(-2, 3), rng.gen_range(-2, 3));
|
||||
let mut origin = Vec2::new(ctx.rng.gen_range(-2, 3), ctx.rng.gen_range(-2, 3));
|
||||
|
||||
for i in 0..PLOT_COUNT {
|
||||
if let Some(base_tile) = self.land.find_tile_near(origin, |plot| match plot {
|
||||
@ -244,6 +252,43 @@ impl Settlement {
|
||||
.plot_at_mut(base_tile)
|
||||
.map(|plot| *plot = Plot::Town);
|
||||
|
||||
for _ in 0..ctx.rng.gen_range(10, 30) {
|
||||
for _ in 0..10 {
|
||||
let house_pos = base_tile.map(|e| e * AREA_SIZE as i32 + AREA_SIZE as i32 / 2)
|
||||
+ Vec2::<i32>::zero().map(|_| ctx.rng.gen_range(-(AREA_SIZE as i32) * 3, AREA_SIZE as i32 * 3));
|
||||
|
||||
if let Some(Plot::Town) = self.land
|
||||
.plot_at(house_pos.map(|e| e.div_euclid(AREA_SIZE as i32)))
|
||||
{} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
let structure = Structure {
|
||||
kind: StructureKind::House(HouseBuilding::generate(ctx.rng, Vec3::new(
|
||||
house_pos.x,
|
||||
house_pos.y,
|
||||
ctx.sim
|
||||
.and_then(|sim| sim.get_alt_approx(self.origin + house_pos))
|
||||
.unwrap_or(0.0)
|
||||
.ceil() as i32,
|
||||
))),
|
||||
};
|
||||
|
||||
let bounds = structure.bounds_2d();
|
||||
|
||||
// Check for collision with other structures
|
||||
if self.structures
|
||||
.iter()
|
||||
.any(|s| s.bounds_2d().collides_with_aabr(bounds))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
self.structures.push(structure);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
/*
|
||||
for dir in CARDINALS.iter() {
|
||||
@ -315,21 +360,21 @@ impl Settlement {
|
||||
self.land.set(base_tile, farmhouse);
|
||||
|
||||
// Farmhouses
|
||||
for _ in 0..ctx.rng.gen_range(1, 3) {
|
||||
let house_pos = base_tile.map(|e| e * AREA_SIZE as i32 + AREA_SIZE as i32 / 2)
|
||||
+ Vec2::new(ctx.rng.gen_range(-16, 16), ctx.rng.gen_range(-16, 16));
|
||||
// for _ in 0..ctx.rng.gen_range(1, 3) {
|
||||
// let house_pos = base_tile.map(|e| e * AREA_SIZE as i32 + AREA_SIZE as i32 / 2)
|
||||
// + Vec2::new(ctx.rng.gen_range(-16, 16), ctx.rng.gen_range(-16, 16));
|
||||
|
||||
self.structures.push(Structure {
|
||||
kind: StructureKind::House(HouseBuilding::generate(ctx.rng, Vec3::new(
|
||||
house_pos.x,
|
||||
house_pos.y,
|
||||
ctx.sim
|
||||
.and_then(|sim| sim.get_alt_approx(self.origin + house_pos))
|
||||
.unwrap_or(0.0)
|
||||
.ceil() as i32,
|
||||
))),
|
||||
});
|
||||
}
|
||||
// self.structures.push(Structure {
|
||||
// kind: StructureKind::House(HouseBuilding::generate(ctx.rng, Vec3::new(
|
||||
// house_pos.x,
|
||||
// house_pos.y,
|
||||
// ctx.sim
|
||||
// .and_then(|sim| sim.get_alt_approx(self.origin + house_pos))
|
||||
// .unwrap_or(0.0)
|
||||
// .ceil() as i32,
|
||||
// ))),
|
||||
// });
|
||||
// }
|
||||
|
||||
// Fields
|
||||
let farmland = self.farms.insert(Farm { base_tile });
|
||||
@ -463,13 +508,24 @@ impl Settlement {
|
||||
|
||||
// Apply structures
|
||||
for structure in &self.structures {
|
||||
let bounds = structure.bounds_2d();
|
||||
|
||||
// Skip this structure if it's not near this chunk
|
||||
if !bounds.collides_with_aabr(Aabr {
|
||||
min: wpos2d - self.origin,
|
||||
max: wpos2d - self.origin + vol.size_xy().map(|e| e as i32),
|
||||
}) {
|
||||
continue;
|
||||
}
|
||||
|
||||
match &structure.kind {
|
||||
StructureKind::House(b) => {
|
||||
let centre = b.bounds_2d().center();
|
||||
let bounds = b.bounds();
|
||||
for x in bounds.min.x..bounds.max.x {
|
||||
for y in bounds.min.y..bounds.max.y {
|
||||
for z in bounds.min.z..bounds.max.z {
|
||||
|
||||
for x in bounds.min.x..bounds.max.x + 1 {
|
||||
for y in bounds.min.y..bounds.max.y + 1 {
|
||||
for z in bounds.min.z..bounds.max.z + 1 {
|
||||
let rpos = Vec3::new(x, y, z);
|
||||
let wpos = Vec3::from(self.origin) + rpos;
|
||||
let coffs = wpos - Vec3::from(wpos2d);
|
||||
|
Loading…
Reference in New Issue
Block a user