mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Better town walls, made settlements avoid rivers
This commit is contained in:
parent
5d5e8e3238
commit
9dc46c490e
@ -9,7 +9,7 @@ fn main() {
|
|||||||
let mut win =
|
let mut win =
|
||||||
minifb::Window::new("Settlement Viewer", W, H, minifb::WindowOptions::default()).unwrap();
|
minifb::Window::new("Settlement Viewer", W, H, minifb::WindowOptions::default()).unwrap();
|
||||||
|
|
||||||
let settlement = Settlement::generate(Vec2::zero(), &mut thread_rng());
|
let settlement = Settlement::generate(Vec2::zero(), None, &mut thread_rng());
|
||||||
|
|
||||||
let mut focus = Vec2::<f32>::zero();
|
let mut focus = Vec2::<f32>::zero();
|
||||||
let mut zoom = 1.0;
|
let mut zoom = 1.0;
|
||||||
|
@ -25,6 +25,12 @@ pub enum Site {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Site {
|
impl Site {
|
||||||
|
pub fn radius(&self) -> f32 {
|
||||||
|
match self {
|
||||||
|
Site::Settlement(settlement) => settlement.radius(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_surface(&self, wpos: Vec2<i32>) -> Option<Block> {
|
pub fn get_surface(&self, wpos: Vec2<i32>) -> Option<Block> {
|
||||||
match self {
|
match self {
|
||||||
Site::Settlement(settlement) => settlement.get_surface(wpos),
|
Site::Settlement(settlement) => settlement.get_surface(wpos),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
block::ZCache,
|
block::ZCache,
|
||||||
util::{Grid, Sampler, StructureGen2d},
|
sim::{SimChunk, WorldSim},
|
||||||
|
util::{Grid, RandomField, Sampler, StructureGen2d},
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
astar::Astar,
|
astar::Astar,
|
||||||
@ -65,7 +66,13 @@ pub fn center_of(p: [Vec2<f32>; 3]) -> Vec2<f32> {
|
|||||||
Vec2::new(x, y)
|
Vec2::new(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
const AREA_SIZE: u32 = 64;
|
impl SimChunk {
|
||||||
|
fn can_host_settlement(&self) -> bool {
|
||||||
|
!self.near_cliffs && !self.river.is_river() && !self.river.is_lake()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const AREA_SIZE: u32 = 32;
|
||||||
|
|
||||||
fn to_tile(e: i32) -> i32 { ((e as f32).div_euclid(AREA_SIZE as f32)).floor() as i32 }
|
fn to_tile(e: i32) -> i32 { ((e as f32).div_euclid(AREA_SIZE as f32)).floor() as i32 }
|
||||||
|
|
||||||
@ -95,7 +102,7 @@ pub struct Farm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Settlement {
|
impl Settlement {
|
||||||
pub fn generate(wpos: Vec2<i32>, rng: &mut impl Rng) -> Self {
|
pub fn generate(wpos: Vec2<i32>, sim: Option<&WorldSim>, rng: &mut impl Rng) -> Self {
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
origin: wpos,
|
origin: wpos,
|
||||||
land: Land::new(rng),
|
land: Land::new(rng),
|
||||||
@ -104,6 +111,10 @@ impl Settlement {
|
|||||||
town: None,
|
town: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Some(sim) = sim {
|
||||||
|
this.designate_from_world(sim, rng);
|
||||||
|
}
|
||||||
|
|
||||||
//this.place_river(rng);
|
//this.place_river(rng);
|
||||||
|
|
||||||
this.place_farms(rng);
|
this.place_farms(rng);
|
||||||
@ -113,6 +124,28 @@ impl Settlement {
|
|||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn designate_from_world(&mut self, sim: &WorldSim, rng: &mut impl Rng) {
|
||||||
|
let tile_radius = self.radius() as i32 / AREA_SIZE as i32;
|
||||||
|
let hazard = self.land.new_plot(Plot::Hazard);
|
||||||
|
Spiral2d::new()
|
||||||
|
.take_while(|tile| tile.map(|e| e.abs()).reduce_max() < tile_radius)
|
||||||
|
.for_each(|tile| {
|
||||||
|
let wpos = self.origin + tile * AREA_SIZE as i32;
|
||||||
|
|
||||||
|
if (0..4)
|
||||||
|
.map(|x| (0..4).map(move |y| Vec2::new(x, y)))
|
||||||
|
.flatten()
|
||||||
|
.any(|offs| {
|
||||||
|
sim.get_wpos(wpos + offs * AREA_SIZE as i32 / 2)
|
||||||
|
.map(|chunk| !chunk.can_host_settlement())
|
||||||
|
.unwrap_or(true)
|
||||||
|
})
|
||||||
|
{
|
||||||
|
self.land.set(tile, hazard);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn place_river(&mut self, rng: &mut impl Rng) {
|
pub fn place_river(&mut self, rng: &mut impl Rng) {
|
||||||
let river_dir = Vec2::new(rng.gen::<f32>() - 0.5, rng.gen::<f32>() - 0.5).normalized();
|
let river_dir = Vec2::new(rng.gen::<f32>() - 0.5, rng.gen::<f32>() - 0.5).normalized();
|
||||||
let radius = 500.0 + rng.gen::<f32>().powf(2.0) * 1000.0;
|
let radius = 500.0 + rng.gen::<f32>().powf(2.0) * 1000.0;
|
||||||
@ -145,12 +178,14 @@ impl Settlement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn place_paths(&mut self, rng: &mut impl Rng) {
|
pub fn place_paths(&mut self, rng: &mut impl Rng) {
|
||||||
|
const PATH_COUNT: usize = 6;
|
||||||
|
|
||||||
let mut dir = Vec2::zero();
|
let mut dir = Vec2::zero();
|
||||||
for _ in 0..6 {
|
for _ in 0..PATH_COUNT {
|
||||||
dir = (Vec2::new(rng.gen::<f32>() - 0.5, rng.gen::<f32>() - 0.5) * 2.0 - dir)
|
dir = (Vec2::new(rng.gen::<f32>() - 0.5, rng.gen::<f32>() - 0.5) * 2.0 - dir)
|
||||||
.try_normalized()
|
.try_normalized()
|
||||||
.unwrap_or(Vec2::zero());
|
.unwrap_or(Vec2::zero());
|
||||||
let origin = dir.map(|e| (e * 20.0) as i32);
|
let origin = dir.map(|e| (e * 100.0) as i32);
|
||||||
let origin = self
|
let origin = self
|
||||||
.land
|
.land
|
||||||
.find_tile_near(origin, |plot| match plot {
|
.find_tile_near(origin, |plot| match plot {
|
||||||
@ -164,6 +199,7 @@ impl Settlement {
|
|||||||
.find_path(origin, town.base_tile, |from, to| match (from, to) {
|
.find_path(origin, town.base_tile, |from, to| match (from, to) {
|
||||||
(_, Some(b)) if self.land.plot(b.plot) == &Plot::Dirt => 0.0,
|
(_, Some(b)) if self.land.plot(b.plot) == &Plot::Dirt => 0.0,
|
||||||
(_, Some(b)) if self.land.plot(b.plot) == &Plot::Water => 20.0,
|
(_, Some(b)) if self.land.plot(b.plot) == &Plot::Water => 20.0,
|
||||||
|
(_, Some(b)) if self.land.plot(b.plot) == &Plot::Hazard => 50.0,
|
||||||
(Some(a), Some(b)) if a.contains(WayKind::Wall) => {
|
(Some(a), Some(b)) if a.contains(WayKind::Wall) => {
|
||||||
if b.contains(WayKind::Wall) {
|
if b.contains(WayKind::Wall) {
|
||||||
1000.0
|
1000.0
|
||||||
@ -176,22 +212,25 @@ impl Settlement {
|
|||||||
})
|
})
|
||||||
}) {
|
}) {
|
||||||
let path = path.iter().copied().collect::<Vec<_>>();
|
let path = path.iter().copied().collect::<Vec<_>>();
|
||||||
self.land.write_path(&path, WayKind::Path, |_| true, true);
|
self.land.write_path(&path, WayKind::Path, |_| true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn place_town(&mut self, rng: &mut impl Rng) {
|
pub fn place_town(&mut self, rng: &mut 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(rng.gen_range(-2, 3), rng.gen_range(-2, 3));
|
||||||
|
|
||||||
let town = self.land.new_plot(Plot::Town);
|
for i in 0..PLOT_COUNT {
|
||||||
for i in 0..6 {
|
|
||||||
if let Some(base_tile) = self.land.find_tile_near(origin, |plot| match plot {
|
if let Some(base_tile) = self.land.find_tile_near(origin, |plot| match plot {
|
||||||
Some(Plot::Field { .. }) => true,
|
Some(Plot::Field { .. }) => true,
|
||||||
Some(Plot::Dirt) => true,
|
Some(Plot::Dirt) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}) {
|
}) {
|
||||||
self.land.set(base_tile, town);
|
self.land
|
||||||
|
.plot_at_mut(base_tile)
|
||||||
|
.map(|plot| *plot = Plot::Town);
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
/*
|
/*
|
||||||
@ -222,6 +261,7 @@ impl Settlement {
|
|||||||
.find_path(spokes[i], spokes[(i + 1) % spokes.len()], |_, to| match to
|
.find_path(spokes[i], spokes[(i + 1) % spokes.len()], |_, to| match to
|
||||||
.map(|to| self.land.plot(to.plot))
|
.map(|to| self.land.plot(to.plot))
|
||||||
{
|
{
|
||||||
|
Some(Plot::Hazard) => 10000.0,
|
||||||
Some(Plot::Town) => 1000.0,
|
Some(Plot::Town) => 1000.0,
|
||||||
_ => 1.0,
|
_ => 1.0,
|
||||||
})
|
})
|
||||||
@ -248,7 +288,10 @@ impl Settlement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn place_farms(&mut self, rng: &mut impl Rng) {
|
pub fn place_farms(&mut self, rng: &mut impl Rng) {
|
||||||
for _ in 0..6 {
|
const FARM_COUNT: usize = 4;
|
||||||
|
const FIELDS_PER_FARM: usize = 5;
|
||||||
|
|
||||||
|
for _ in 0..FARM_COUNT {
|
||||||
if let Some(base_tile) = self
|
if let Some(base_tile) = self
|
||||||
.land
|
.land
|
||||||
.find_tile_near(Vec2::zero(), |plot| plot.is_none())
|
.find_tile_near(Vec2::zero(), |plot| plot.is_none())
|
||||||
@ -258,7 +301,7 @@ impl Settlement {
|
|||||||
self.land.set(base_tile, farmhouse);
|
self.land.set(base_tile, farmhouse);
|
||||||
|
|
||||||
// Farmhouses
|
// Farmhouses
|
||||||
for _ in 0..rng.gen_range(1, 4) {
|
for _ in 0..rng.gen_range(1, 3) {
|
||||||
let house_pos = base_tile.map(|e| e * AREA_SIZE as i32 + AREA_SIZE as i32 / 2)
|
let house_pos = base_tile.map(|e| e * AREA_SIZE as i32 + AREA_SIZE as i32 / 2)
|
||||||
+ Vec2::new(rng.gen_range(-16, 16), rng.gen_range(-16, 16));
|
+ Vec2::new(rng.gen_range(-16, 16), rng.gen_range(-16, 16));
|
||||||
|
|
||||||
@ -273,7 +316,7 @@ impl Settlement {
|
|||||||
|
|
||||||
// Fields
|
// Fields
|
||||||
let farmland = self.farms.insert(Farm { base_tile });
|
let farmland = self.farms.insert(Farm { base_tile });
|
||||||
for _ in 0..5 {
|
for _ in 0..FIELDS_PER_FARM {
|
||||||
self.place_field(farmland, base_tile, rng);
|
self.place_field(farmland, base_tile, rng);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,16 +329,16 @@ impl Settlement {
|
|||||||
origin: Vec2<i32>,
|
origin: Vec2<i32>,
|
||||||
rng: &mut impl Rng,
|
rng: &mut impl Rng,
|
||||||
) -> Option<Id<Plot>> {
|
) -> Option<Id<Plot>> {
|
||||||
let max_size = 7;
|
const MAX_FIELD_SIZE: usize = 24;
|
||||||
|
|
||||||
if let Some(center) = self.land.find_tile_near(origin, |plot| plot.is_none()) {
|
if let Some(center) = self.land.find_tile_near(origin, |plot| plot.is_none()) {
|
||||||
let field = self.land.new_plot(Plot::Field {
|
let field = self.land.new_plot(Plot::Field {
|
||||||
farm,
|
farm,
|
||||||
seed: rng.gen(),
|
seed: rng.gen(),
|
||||||
});
|
});
|
||||||
let tiles = self
|
let tiles =
|
||||||
.land
|
self.land
|
||||||
.grow_from(center, rng.gen_range(1, max_size), rng, |plot| {
|
.grow_from(center, rng.gen_range(5, MAX_FIELD_SIZE), rng, |plot| {
|
||||||
plot.is_none()
|
plot.is_none()
|
||||||
});
|
});
|
||||||
for pos in tiles.into_iter() {
|
for pos in tiles.into_iter() {
|
||||||
@ -307,12 +350,16 @@ impl Settlement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn radius(&self) -> f32 { 1200.0 }
|
||||||
|
|
||||||
pub fn apply_to(
|
pub fn apply_to(
|
||||||
&self,
|
&self,
|
||||||
wpos2d: Vec2<i32>,
|
wpos2d: Vec2<i32>,
|
||||||
zcaches: &Grid<Option<ZCache>>,
|
zcaches: &Grid<Option<ZCache>>,
|
||||||
vol: &mut (impl BaseVol<Vox = Block> + WriteVol),
|
vol: &mut (impl BaseVol<Vox = Block> + WriteVol),
|
||||||
) {
|
) {
|
||||||
|
let rand_field = RandomField::new(0);
|
||||||
|
|
||||||
for y in 0..zcaches.size().y {
|
for y in 0..zcaches.size().y {
|
||||||
for x in 0..zcaches.size().x {
|
for x in 0..zcaches.size().x {
|
||||||
let offs = Vec2::new(x, y);
|
let offs = Vec2::new(x, y);
|
||||||
@ -326,15 +373,25 @@ impl Settlement {
|
|||||||
let wpos2d = wpos2d + offs;
|
let wpos2d = wpos2d + offs;
|
||||||
|
|
||||||
match self.land.get_at_block(wpos2d - self.origin) {
|
match self.land.get_at_block(wpos2d - self.origin) {
|
||||||
Sample::Way(WayKind::Wall) => {
|
Sample::Way(WayKind::Wall, dist) => {
|
||||||
|
let color = Lerp::lerp(
|
||||||
|
Rgb::new(130i32, 100, 0),
|
||||||
|
Rgb::new(90, 70, 50),
|
||||||
|
(rand_field.get(wpos2d.into()) % 256) as f32 / 256.0,
|
||||||
|
)
|
||||||
|
.map(|e| (e % 256) as u8);
|
||||||
for z in 0..12 {
|
for z in 0..12 {
|
||||||
|
if dist / WayKind::Wall.width()
|
||||||
|
< ((1.0 - z as f32 / 12.0) * 2.0).min(1.0)
|
||||||
|
{
|
||||||
vol.set(
|
vol.set(
|
||||||
Vec3::new(offs.x, offs.y, zcache.sample.alt.floor() as i32 + z),
|
Vec3::new(offs.x, offs.y, zcache.sample.alt.floor() as i32 + z),
|
||||||
Block::new(BlockKind::Normal, Rgb::new(60, 60, 60)),
|
Block::new(BlockKind::Normal, color),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Sample::Tower(Tower::Wall) => {
|
Sample::Tower(Tower::Wall, _pos) => {
|
||||||
for z in 0..16 {
|
for z in 0..16 {
|
||||||
vol.set(
|
vol.set(
|
||||||
Vec3::new(offs.x, offs.y, zcache.sample.alt.floor() as i32 + z),
|
Vec3::new(offs.x, offs.y, zcache.sample.alt.floor() as i32 + z),
|
||||||
@ -366,11 +423,12 @@ impl Settlement {
|
|||||||
|
|
||||||
Some(match self.land.get_at_block(pos) {
|
Some(match self.land.get_at_block(pos) {
|
||||||
Sample::Wilderness => return None,
|
Sample::Wilderness => return None,
|
||||||
Sample::Way(WayKind::Path) => Rgb::new(130, 100, 0),
|
Sample::Plot(Plot::Hazard) => return None,
|
||||||
Sample::Way(WayKind::Hedge) => Rgb::new(0, 150, 0),
|
Sample::Way(WayKind::Path, _) => Rgb::new(90, 70, 50),
|
||||||
Sample::Way(WayKind::Wall) => Rgb::new(60, 60, 60),
|
Sample::Way(WayKind::Hedge, _) => Rgb::new(0, 150, 0),
|
||||||
Sample::Tower(Tower::Wall) => Rgb::new(50, 50, 50),
|
Sample::Way(WayKind::Wall, _) => Rgb::new(60, 60, 60),
|
||||||
Sample::Plot(Plot::Dirt) => Rgb::new(130, 100, 0),
|
Sample::Tower(Tower::Wall, _) => Rgb::new(50, 50, 50),
|
||||||
|
Sample::Plot(Plot::Dirt) => Rgb::new(90, 70, 50),
|
||||||
Sample::Plot(Plot::Grass) => Rgb::new(100, 200, 0),
|
Sample::Plot(Plot::Grass) => Rgb::new(100, 200, 0),
|
||||||
Sample::Plot(Plot::Water) => Rgb::new(100, 150, 250),
|
Sample::Plot(Plot::Water) => Rgb::new(100, 150, 250),
|
||||||
Sample::Plot(Plot::Town) => {
|
Sample::Plot(Plot::Town) => {
|
||||||
@ -405,6 +463,7 @@ impl Settlement {
|
|||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum Plot {
|
pub enum Plot {
|
||||||
|
Hazard,
|
||||||
Dirt,
|
Dirt,
|
||||||
Grass,
|
Grass,
|
||||||
Water,
|
Water,
|
||||||
@ -431,7 +490,7 @@ impl WayKind {
|
|||||||
match self {
|
match self {
|
||||||
WayKind::Path => 4.0,
|
WayKind::Path => 4.0,
|
||||||
WayKind::Hedge => 1.5,
|
WayKind::Hedge => 1.5,
|
||||||
WayKind::Wall => 3.5,
|
WayKind::Wall => 2.5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -444,7 +503,7 @@ pub enum Tower {
|
|||||||
impl Tower {
|
impl Tower {
|
||||||
pub fn radius(&self) -> f32 {
|
pub fn radius(&self) -> f32 {
|
||||||
match self {
|
match self {
|
||||||
Tower::Wall => 8.0,
|
Tower::Wall => 6.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -462,8 +521,8 @@ impl Tile {
|
|||||||
pub enum Sample<'a> {
|
pub enum Sample<'a> {
|
||||||
Wilderness,
|
Wilderness,
|
||||||
Plot(&'a Plot),
|
Plot(&'a Plot),
|
||||||
Way(&'a WayKind),
|
Way(&'a WayKind, f32),
|
||||||
Tower(&'a Tower),
|
Tower(&'a Tower, Vec2<i32>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Land {
|
pub struct Land {
|
||||||
@ -493,7 +552,7 @@ impl Land {
|
|||||||
|
|
||||||
if let Some(tower) = center_tile.and_then(|tile| tile.tower.as_ref()) {
|
if let Some(tower) = center_tile.and_then(|tile| tile.tower.as_ref()) {
|
||||||
if (neighbors[4].0.distance_squared(pos) as f32) < tower.radius().powf(2.0) {
|
if (neighbors[4].0.distance_squared(pos) as f32) < tower.radius().powf(2.0) {
|
||||||
return Sample::Tower(tower);
|
return Sample::Tower(tower, neighbors[4].0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,8 +563,9 @@ impl Land {
|
|||||||
neighbors[map[i]].0.map(|e| e as f32),
|
neighbors[map[i]].0.map(|e| e as f32),
|
||||||
];
|
];
|
||||||
if let Some(way) = center_tile.and_then(|tile| tile.ways[i].as_ref()) {
|
if let Some(way) = center_tile.and_then(|tile| tile.ways[i].as_ref()) {
|
||||||
if dist_to_line(line, pos.map(|e| e as f32)) < way.width() {
|
let dist = dist_to_line(line, pos.map(|e| e as f32));
|
||||||
return Sample::Way(way);
|
if dist < way.width() {
|
||||||
|
return Sample::Way(way, dist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,6 +200,8 @@ impl RiverData {
|
|||||||
.map(RiverKind::is_lake)
|
.map(RiverKind::is_lake)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn near_river(&self) -> bool { self.is_river() || self.neighbor_rivers.len() > 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw rivers and assign them heights, widths, and velocities. Take some
|
/// Draw rivers and assign them heights, widths, and velocities. Take some
|
||||||
|
@ -1463,7 +1463,10 @@ impl WorldSim {
|
|||||||
// println!("Town: {:?}", town);
|
// println!("Town: {:?}", town);
|
||||||
//TownState::generate(pos, &mut block_gen, &mut rng).map(|t| (pos,
|
//TownState::generate(pos, &mut block_gen, &mut rng).map(|t| (pos,
|
||||||
// Arc::new(t)))
|
// Arc::new(t)))
|
||||||
(pos, Site::from(Settlement::generate(pos, &mut rng)))
|
(
|
||||||
|
pos,
|
||||||
|
Site::from(Settlement::generate(pos, Some(self), &mut rng)),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@ -1478,10 +1481,8 @@ impl WorldSim {
|
|||||||
|
|
||||||
if let Some((pos, site)) = sites
|
if let Some((pos, site)) = sites
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(pos, _)| {
|
.filter(|(pos, site)| {
|
||||||
pos.map(|e| e as i64)
|
pos.map(|e| e as f32).distance(wpos.map(|e| e as f32)) < site.radius()
|
||||||
.distance_squared(wpos.map(|e| e as i64))
|
|
||||||
< 1200i64.pow(2)
|
|
||||||
})
|
})
|
||||||
.min_by_key(|(pos, _)| wpos.distance_squared(*pos))
|
.min_by_key(|(pos, _)| wpos.distance_squared(*pos))
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user