mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Initial test site generation
This commit is contained in:
parent
bed114900f
commit
29705b0a1f
@ -3,14 +3,17 @@ mod tile;
|
|||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
plot::{Plot, PlotKind},
|
plot::{Plot, PlotKind},
|
||||||
tile::TileGrid,
|
tile::{TileGrid, Tile, TileKind, TILE_SIZE},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
site::SpawnRules,
|
site::SpawnRules,
|
||||||
util::Grid,
|
util::Grid,
|
||||||
Canvas,
|
Canvas,
|
||||||
};
|
};
|
||||||
use common::store::{Id, Store};
|
use common::{
|
||||||
|
terrain::{Block, BlockKind, SpriteKind},
|
||||||
|
store::{Id, Store},
|
||||||
|
};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
@ -52,24 +55,62 @@ impl Site {
|
|||||||
pub fn generate(rng: &mut impl Rng) -> Self {
|
pub fn generate(rng: &mut impl Rng) -> Self {
|
||||||
let mut site = Site::default();
|
let mut site = Site::default();
|
||||||
|
|
||||||
for i in 0..10 {
|
for i in 0..100 {
|
||||||
let dir = Vec2::<f32>::zero()
|
let dir = Vec2::<f32>::zero()
|
||||||
.map(|_| rng.gen_range(-1.0..1.0))
|
.map(|_| rng.gen_range(-1.0..1.0))
|
||||||
.normalized();
|
.normalized();
|
||||||
let search_pos = (dir * 32.0).map(|e| e as i32);
|
let search_pos = (dir * rng.gen_range(0.0f32..1.0).powf(2.0) * 24.0).map(|e| e as i32);
|
||||||
|
|
||||||
site.tiles
|
site.tiles
|
||||||
.find_near(search_pos, |tile| tile.is_empty())
|
.find_near(search_pos, |_, tile| tile.is_empty())
|
||||||
.map(|center| {
|
.and_then(|center| site.tiles.grow_aabr(center, 6..16, Extent2::new(2, 2)).ok())
|
||||||
// TODO
|
.map(|aabr| {
|
||||||
|
let tile = match i % 2 {
|
||||||
|
0 => TileKind::Farmland { seed: i },
|
||||||
|
_ => TileKind::Building { levels: 1 + i % 3 },
|
||||||
|
};
|
||||||
|
|
||||||
|
for x in 0..aabr.size().w {
|
||||||
|
for y in 0..aabr.size().h {
|
||||||
|
let pos = aabr.min + Vec2::new(x, y);
|
||||||
|
site.tiles.set(pos, Tile::free(tile.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
site
|
site
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn wpos_tile(&self, wpos2d: Vec2<i32>) -> &Tile {
|
||||||
|
self.tiles.get((wpos2d - self.origin).map(|e| e.div_euclid(TILE_SIZE as i32)))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render(&self, canvas: &mut Canvas, dynamic_rng: &mut impl Rng) {
|
pub fn render(&self, canvas: &mut Canvas, dynamic_rng: &mut impl Rng) {
|
||||||
// TODO
|
canvas.foreach_col(|canvas, wpos2d, col| {
|
||||||
|
match self.wpos_tile(wpos2d).kind {
|
||||||
|
TileKind::Farmland { seed } => (-4..5).for_each(|z| canvas.map(
|
||||||
|
Vec3::new(wpos2d.x, wpos2d.y, col.alt as i32 + z),
|
||||||
|
|b| if [
|
||||||
|
BlockKind::Grass,
|
||||||
|
BlockKind::Earth,
|
||||||
|
BlockKind::Sand,
|
||||||
|
BlockKind::Snow,
|
||||||
|
BlockKind::Rock,
|
||||||
|
]
|
||||||
|
.contains(&b.kind()) {
|
||||||
|
Block::new(BlockKind::Earth, Rgb::new(40, 5 + (seed % 32) as u8, 0))
|
||||||
|
} else {
|
||||||
|
b.with_sprite(SpriteKind::Empty)
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
TileKind::Building { levels } => (-4..7 * levels as i32).for_each(|z| canvas.set(
|
||||||
|
Vec3::new(wpos2d.x, wpos2d.y, col.alt as i32 + z),
|
||||||
|
Block::new(BlockKind::Wood, Rgb::new(180, 150, 120))
|
||||||
|
)),
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use common::spiral::Spiral2d;
|
use common::spiral::Spiral2d;
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
pub const TILE_SIZE: u32 = 7;
|
pub const TILE_SIZE: u32 = 7;
|
||||||
pub const ZONE_SIZE: u32 = 16;
|
pub const ZONE_SIZE: u32 = 16;
|
||||||
@ -25,7 +26,7 @@ impl TileGrid {
|
|||||||
|
|
||||||
let tpos = tpos + TILE_RADIUS as i32;
|
let tpos = tpos + TILE_RADIUS as i32;
|
||||||
self.zones
|
self.zones
|
||||||
.get(tpos)
|
.get(tpos.map(|e| e.div_euclid(ZONE_SIZE as i32)))
|
||||||
.and_then(|zone| {
|
.and_then(|zone| {
|
||||||
zone.as_ref()?
|
zone.as_ref()?
|
||||||
.get(tpos.map(|e| e.rem_euclid(ZONE_SIZE as i32)))
|
.get(tpos.map(|e| e.rem_euclid(ZONE_SIZE as i32)))
|
||||||
@ -36,9 +37,9 @@ impl TileGrid {
|
|||||||
|
|
||||||
pub fn get_mut(&mut self, tpos: Vec2<i32>) -> Option<&mut Tile> {
|
pub fn get_mut(&mut self, tpos: Vec2<i32>) -> Option<&mut Tile> {
|
||||||
let tpos = tpos + TILE_RADIUS as i32;
|
let tpos = tpos + TILE_RADIUS as i32;
|
||||||
self.zones.get_mut(tpos).and_then(|zone| {
|
self.zones.get_mut(tpos.map(|e| e.div_euclid(ZONE_SIZE as i32))).and_then(|zone| {
|
||||||
zone.get_or_insert_with(|| {
|
zone.get_or_insert_with(|| {
|
||||||
Grid::populate_from(Vec2::broadcast(ZONE_RADIUS as i32 * 2 + 1), |_| None)
|
Grid::populate_from(Vec2::broadcast(ZONE_SIZE as i32), |_| None)
|
||||||
})
|
})
|
||||||
.get_mut(tpos.map(|e| e.rem_euclid(ZONE_SIZE as i32)))
|
.get_mut(tpos.map(|e| e.rem_euclid(ZONE_SIZE as i32)))
|
||||||
.map(|tile| tile.get_or_insert_with(|| Tile::empty()))
|
.map(|tile| tile.get_or_insert_with(|| Tile::empty()))
|
||||||
@ -49,23 +50,66 @@ impl TileGrid {
|
|||||||
self.get_mut(tpos).map(|t| std::mem::replace(t, tile))
|
self.get_mut(tpos).map(|t| std::mem::replace(t, tile))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_near(&self, tpos: Vec2<i32>, f: impl Fn(&Tile) -> bool) -> Option<Vec2<i32>> {
|
pub fn find_near(&self, tpos: Vec2<i32>, f: impl Fn(Vec2<i32>, &Tile) -> bool) -> Option<Vec2<i32>> {
|
||||||
const MAX_SEARCH_RADIUS_BLOCKS: u32 = 256;
|
const MAX_SEARCH_RADIUS_BLOCKS: u32 = 256;
|
||||||
const MAX_SEARCH_CELLS: u32 = ((MAX_SEARCH_RADIUS_BLOCKS / TILE_SIZE) * 2).pow(2);
|
const MAX_SEARCH_CELLS: u32 = ((MAX_SEARCH_RADIUS_BLOCKS / TILE_SIZE) * 2 + 1).pow(2);
|
||||||
Spiral2d::new().take(MAX_SEARCH_CELLS as usize).map(|r| tpos + r).find(|tpos| (&f)(self.get(*tpos)))
|
Spiral2d::new().take(MAX_SEARCH_CELLS as usize).map(|r| tpos + r).find(|tpos| (&f)(*tpos, self.get(*tpos)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn grow_aabr(&self, center: Vec2<i32>, area_range: Range<u32>, min_dims: Extent2<u32>) -> Result<Aabr<i32>, Aabr<i32>> {
|
||||||
|
let mut aabr = Aabr::new_empty(center);
|
||||||
|
|
||||||
|
let mut last_growth = 0;
|
||||||
|
for i in 0.. {
|
||||||
|
if i - last_growth >= 4 {
|
||||||
|
break;
|
||||||
|
} else if aabr.size().product() + if i % 2 == 0 { aabr.size().h } else { aabr.size().w } > area_range.end as i32 {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
match i % 4 {
|
||||||
|
0 if (aabr.min.y..aabr.max.y).all(|y| self.get(Vec2::new(aabr.max.x + 1, y)).is_empty()) => {
|
||||||
|
aabr.max.x += 1;
|
||||||
|
last_growth = i;
|
||||||
|
},
|
||||||
|
1 if (aabr.min.x..aabr.max.x).all(|x| self.get(Vec2::new(x, aabr.max.y + 1)).is_empty()) => {
|
||||||
|
aabr.max.y += 1;
|
||||||
|
last_growth = i;
|
||||||
|
},
|
||||||
|
2 if (aabr.min.y..aabr.max.y).all(|y| self.get(Vec2::new(aabr.min.x - 1, y)).is_empty()) => {
|
||||||
|
aabr.min.x -= 1;
|
||||||
|
last_growth = i;
|
||||||
|
},
|
||||||
|
3 if (aabr.min.x..aabr.max.x).all(|x| self.get(Vec2::new(x, aabr.min.y - 1)).is_empty()) => {
|
||||||
|
aabr.min.y -= 1;
|
||||||
|
last_growth = i;
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if aabr.size().product() as u32 >= area_range.start
|
||||||
|
&& aabr.size().w as u32 >= min_dims.w
|
||||||
|
&& aabr.size().h as u32 >= min_dims.h
|
||||||
|
{
|
||||||
|
Ok(aabr)
|
||||||
|
} else {
|
||||||
|
Err(aabr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub enum TileKind {
|
pub enum TileKind {
|
||||||
Empty,
|
Empty,
|
||||||
Farmland,
|
Farmland { seed: u32 },
|
||||||
Building { levels: u32 },
|
Building { levels: u32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Tile {
|
pub struct Tile {
|
||||||
kind: TileKind,
|
pub(crate) kind: TileKind,
|
||||||
plot: Option<Id<Plot>>,
|
pub(crate) plot: Option<Id<Plot>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tile {
|
impl Tile {
|
||||||
@ -76,5 +120,13 @@ impl Tile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a tile that is not associated with any plot.
|
||||||
|
pub const fn free(kind: TileKind) -> Self {
|
||||||
|
Self {
|
||||||
|
kind,
|
||||||
|
plot: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool { self.kind == TileKind::Empty }
|
pub fn is_empty(&self) -> bool { self.kind == TileKind::Empty }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user