mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Improved water pathfinding
This commit is contained in:
parent
71b7e1ef90
commit
de685b00b2
@ -139,6 +139,7 @@ void main() {
|
|||||||
// f_pos = v_pos + (model_offs - focus_off.xyz);
|
// f_pos = v_pos + (model_offs - focus_off.xyz);
|
||||||
|
|
||||||
f_pos = (inst_mat * vec4(v_pos_, 1.0)).xyz * SCALE + inst_offs;
|
f_pos = (inst_mat * vec4(v_pos_, 1.0)).xyz * SCALE + inst_offs;
|
||||||
|
f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0));
|
||||||
// f_pos = (inst_mat * v_pos_) * SCALE + sprite_pos;
|
// f_pos = (inst_mat * v_pos_) * SCALE + sprite_pos;
|
||||||
|
|
||||||
// f_pos = (inst_mat * vec4(v_pos * SCALE, 1)).xyz + (model_offs - focus_off.xyz);
|
// f_pos = (inst_mat * vec4(v_pos * SCALE, 1)).xyz + (model_offs - focus_off.xyz);
|
||||||
|
@ -131,17 +131,18 @@ impl Route {
|
|||||||
// Determine whether we're close enough to the next to to consider it completed
|
// Determine whether we're close enough to the next to to consider it completed
|
||||||
let dist_sqrd = pos.xy().distance_squared(closest_tgt.xy());
|
let dist_sqrd = pos.xy().distance_squared(closest_tgt.xy());
|
||||||
if dist_sqrd < traversal_cfg.node_tolerance.powf(2.0) * if be_precise { 0.25 } else { 1.0 }
|
if dist_sqrd < traversal_cfg.node_tolerance.powf(2.0) * if be_precise { 0.25 } else { 1.0 }
|
||||||
&& (pos.z - closest_tgt.z > 1.2 || (pos.z - closest_tgt.z > -0.2 && (traversal_cfg.on_ground || traversal_cfg.in_liquid)))
|
&& (((pos.z - closest_tgt.z > 1.2 || (pos.z - closest_tgt.z > -0.2 && traversal_cfg.on_ground))
|
||||||
&& (pos.z - closest_tgt.z < 1.2 || (pos.z - closest_tgt.z < 2.9 && vel.z < -0.05))
|
&& (pos.z - closest_tgt.z < 1.2 || (pos.z - closest_tgt.z < 2.9 && vel.z < -0.05))
|
||||||
&& vel.z <= 0.0
|
&& vel.z <= 0.0
|
||||||
// Only consider the node reached if there's nothing solid between us and it
|
// Only consider the node reached if there's nothing solid between us and it
|
||||||
&& (vol
|
&& (vol
|
||||||
.ray(pos + Vec3::unit_z() * 1.5, closest_tgt + Vec3::unit_z() * 1.5)
|
.ray(pos + Vec3::unit_z() * 1.5, closest_tgt + Vec3::unit_z() * 1.5)
|
||||||
.until(Block::is_solid)
|
.until(Block::is_solid)
|
||||||
.cast()
|
.cast()
|
||||||
.0
|
.0
|
||||||
> pos.distance(closest_tgt) * 0.9 || dist_sqrd < 0.5)
|
> pos.distance(closest_tgt) * 0.9 || dist_sqrd < 0.5)
|
||||||
&& self.next_idx < self.path.len()
|
&& self.next_idx < self.path.len())
|
||||||
|
|| (traversal_cfg.in_liquid && pos.z < closest_tgt.z + 0.8 && pos.z > closest_tgt.z))
|
||||||
{
|
{
|
||||||
// Node completed, move on to the next one
|
// Node completed, move on to the next one
|
||||||
self.next_idx += 1;
|
self.next_idx += 1;
|
||||||
@ -419,7 +420,7 @@ impl Chaser {
|
|||||||
vol.get(
|
vol.get(
|
||||||
(pos + Vec3::<f32>::from(tgt_dir) * 2.5).map(|e| e as i32) + Vec3::unit_z() * z,
|
(pos + Vec3::<f32>::from(tgt_dir) * 2.5).map(|e| e as i32) + Vec3::unit_z() * z,
|
||||||
)
|
)
|
||||||
.map(|b| !b.is_solid())
|
.map(|b| b.is_air())
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -437,17 +438,22 @@ fn walkable<V>(vol: &V, pos: Vec3<i32>) -> bool
|
|||||||
where
|
where
|
||||||
V: BaseVol<Vox = Block> + ReadVol,
|
V: BaseVol<Vox = Block> + ReadVol,
|
||||||
{
|
{
|
||||||
vol.get(pos - Vec3::new(0, 0, 1))
|
let below = vol.get(pos - Vec3::unit_z())
|
||||||
.map(|b| b.is_filled())
|
.ok()
|
||||||
.unwrap_or(false)
|
.copied()
|
||||||
&& vol
|
.unwrap_or_else(Block::empty);
|
||||||
.get(pos + Vec3::new(0, 0, 0))
|
let a = vol.get(pos)
|
||||||
.map(|b| !b.is_filled())
|
.ok()
|
||||||
.unwrap_or(true)
|
.copied()
|
||||||
&& vol
|
.unwrap_or_else(Block::empty);
|
||||||
.get(pos + Vec3::new(0, 0, 1))
|
let b = vol.get(pos + Vec3::unit_z())
|
||||||
.map(|b| !b.is_filled())
|
.ok()
|
||||||
.unwrap_or(true)
|
.copied()
|
||||||
|
.unwrap_or_else(Block::empty);
|
||||||
|
|
||||||
|
let on_ground = below.is_filled();
|
||||||
|
let in_liquid = a.is_liquid();
|
||||||
|
(on_ground || in_liquid) && !a.is_solid() && !b.is_solid()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempt to search for a path to a target, returning the path (if one was
|
/// Attempt to search for a path to a target, returning the path (if one was
|
||||||
@ -546,17 +552,17 @@ where
|
|||||||
&& ((dir.z < 1
|
&& ((dir.z < 1
|
||||||
|| vol
|
|| vol
|
||||||
.get(pos + Vec3::unit_z() * 2)
|
.get(pos + Vec3::unit_z() * 2)
|
||||||
.map(|b| !b.is_filled())
|
.map(|b| !b.is_solid())
|
||||||
.unwrap_or(true))
|
.unwrap_or(true))
|
||||||
&& (dir.z < 2
|
&& (dir.z < 2
|
||||||
|| vol
|
|| vol
|
||||||
.get(pos + Vec3::unit_z() * 3)
|
.get(pos + Vec3::unit_z() * 3)
|
||||||
.map(|b| !b.is_filled())
|
.map(|b| !b.is_solid())
|
||||||
.unwrap_or(true))
|
.unwrap_or(true))
|
||||||
&& (dir.z >= 0
|
&& (dir.z >= 0
|
||||||
|| vol
|
|| vol
|
||||||
.get(pos + *dir + Vec3::unit_z() * 2)
|
.get(pos + *dir + Vec3::unit_z() * 2)
|
||||||
.map(|b| !b.is_filled())
|
.map(|b| !b.is_solid())
|
||||||
.unwrap_or(true)))
|
.unwrap_or(true)))
|
||||||
})
|
})
|
||||||
.map(move |(pos, dir)| pos + dir)
|
.map(move |(pos, dir)| pos + dir)
|
||||||
|
@ -239,9 +239,9 @@ impl<'a> System<'a> for Sys {
|
|||||||
.unwrap_or(Vec2::zero())
|
.unwrap_or(Vec2::zero())
|
||||||
* speed.min(agent.rtsim_controller.speed_factor);
|
* speed.min(agent.rtsim_controller.speed_factor);
|
||||||
inputs.jump.set_state(bearing.z > 1.5);
|
inputs.jump.set_state(bearing.z > 1.5);
|
||||||
inputs.climb = Some(comp::Climb::Up)
|
inputs.climb = Some(comp::Climb::Up);
|
||||||
.filter(|_| bearing.z > 1.5 || physics_state.in_liquid.is_some());
|
//.filter(|_| bearing.z > 0.1 || physics_state.in_liquid.is_some());
|
||||||
inputs.move_z = bearing.z;
|
inputs.move_z = bearing.z + 0.05;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*bearing += Vec2::new(
|
*bearing += Vec2::new(
|
||||||
|
@ -116,11 +116,15 @@ impl TerrainGrid {
|
|||||||
let mut z_diff = 0;
|
let mut z_diff = 0;
|
||||||
for _ in 0..128 {
|
for _ in 0..128 {
|
||||||
let test_pos = pos + Vec3::unit_z() * z_diff;
|
let test_pos = pos + Vec3::unit_z() * z_diff;
|
||||||
if (0..2)
|
if self
|
||||||
.all(|z| self
|
.get(test_pos - Vec3::unit_z())
|
||||||
.get(test_pos + Vec3::unit_z() * z)
|
.map(|b| b.is_filled())
|
||||||
.map(|b| !b.is_solid())
|
.unwrap_or(false)
|
||||||
.unwrap_or(true))
|
&& (0..2)
|
||||||
|
.all(|z| self
|
||||||
|
.get(test_pos + Vec3::unit_z() * z)
|
||||||
|
.map(|b| !b.is_solid())
|
||||||
|
.unwrap_or(true))
|
||||||
{
|
{
|
||||||
return test_pos;
|
return test_pos;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ impl Entity {
|
|||||||
|
|
||||||
let travel_to = self.pos.xy() + Vec3::from((wpos.map(|e| e as f32 + 0.5) - self.pos.xy())
|
let travel_to = self.pos.xy() + Vec3::from((wpos.map(|e| e as f32 + 0.5) - self.pos.xy())
|
||||||
.try_normalized()
|
.try_normalized()
|
||||||
.unwrap_or_else(Vec2::zero)) * 32.0;
|
.unwrap_or_else(Vec2::zero)) * 64.0;
|
||||||
let travel_to_alt = world.sim().get_alt_approx(travel_to.map(|e| e as i32)).unwrap_or(0.0) as i32;
|
let travel_to_alt = world.sim().get_alt_approx(travel_to.map(|e| e as i32)).unwrap_or(0.0) as i32;
|
||||||
let travel_to = terrain.find_space(Vec3::new(travel_to.x as i32, travel_to.y as i32, travel_to_alt)).map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0);
|
let travel_to = terrain.find_space(Vec3::new(travel_to.x as i32, travel_to.y as i32, travel_to_alt)).map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0);
|
||||||
self.controller.travel_to = Some(travel_to);
|
self.controller.travel_to = Some(travel_to);
|
||||||
|
@ -87,7 +87,7 @@ pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) {
|
|||||||
pub fn init(state: &mut State, world: &world::World) {
|
pub fn init(state: &mut State, world: &world::World) {
|
||||||
let mut rtsim = RtSim::new(world.sim().get_size());
|
let mut rtsim = RtSim::new(world.sim().get_size());
|
||||||
|
|
||||||
for _ in 0..10000 {
|
for _ in 0..2500 {
|
||||||
let pos = rtsim.chunks.size().map2(
|
let pos = rtsim.chunks.size().map2(
|
||||||
TerrainChunk::RECT_SIZE,
|
TerrainChunk::RECT_SIZE,
|
||||||
|sz, chunk_sz| thread_rng().gen_range(0, sz * chunk_sz) as i32,
|
|sz, chunk_sz| thread_rng().gen_range(0, sz * chunk_sz) as i32,
|
||||||
|
@ -24,6 +24,7 @@ pub mod sim;
|
|||||||
pub mod sim2;
|
pub mod sim2;
|
||||||
pub mod site;
|
pub mod site;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
pub mod pathfinding;
|
||||||
|
|
||||||
// Reexports
|
// Reexports
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
|
35
world/src/pathfinding.rs
Normal file
35
world/src/pathfinding.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use crate::sim::WorldSim;
|
||||||
|
use common::{
|
||||||
|
astar::Astar,
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
use hashbrown::hash_map::DefaultHashBuilder;
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
|
pub struct SearchCfg {
|
||||||
|
// 0.0 = no discount, 1.0 = free travel
|
||||||
|
path_discount: f32,
|
||||||
|
// Cost per metre altitude change per metre horizontal
|
||||||
|
// 0.0 = no cost, 1.0 = same cost vertical as horizontal
|
||||||
|
gradient_aversion: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Searcher<'a> {
|
||||||
|
land: &'a WorldSim,
|
||||||
|
pub cfg: SearchCfg,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Searcher<'a> {
|
||||||
|
/// Attempt to find a path between two chunks on the map.
|
||||||
|
pub fn search(self, a: Vec2<i32>, b: Vec2<i32>) -> Option<Path<i32>> {
|
||||||
|
let heuristic = |pos: &Vec2<i32>| (pos - b).map(|e| e as f32).magnitude();
|
||||||
|
// Astar::new(
|
||||||
|
// 100_000,
|
||||||
|
// a,
|
||||||
|
// heuristc,
|
||||||
|
// DefaultHashBuilder::default(),
|
||||||
|
// );
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user