pathfinding wip
This commit is contained in:
@@ -6,7 +6,7 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bevy = "0.14.0"
|
||||
bevy = "0.14.2"
|
||||
world_generation = { path = "../../engine/world_generation" }
|
||||
shared = { path = "../shared" }
|
||||
bevy_rapier3d = "0.27.0"
|
||||
|
||||
@@ -7,7 +7,7 @@ build = "build.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bevy = { version = "0.14.0", features = ["file_watcher"] }
|
||||
bevy = { version = "0.14.2", features = ["file_watcher"] }
|
||||
bevy-inspector-egui = "0.25.0"
|
||||
iyes_perf_ui = "0.3.0"
|
||||
noise = "0.8.2"
|
||||
|
||||
@@ -6,7 +6,7 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bevy = "0.14.0"
|
||||
bevy = "0.14.2"
|
||||
serde = { version = "1.0.204", features = ["derive"] }
|
||||
world_generation = { path = "../../engine/world_generation" }
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bevy = "0.14.0"
|
||||
bevy = "0.14.2"
|
||||
world_generation = { path = "../../engine/world_generation" }
|
||||
shared = { path = "../shared" }
|
||||
bevy_rapier3d = "0.27.0"
|
||||
@@ -17,6 +17,8 @@ bevy_asset_loader = { version = "0.21.0", features = [
|
||||
"3d",
|
||||
] }
|
||||
quadtree_rs = "0.1.3"
|
||||
pathfinding = "4.11.0"
|
||||
ordered-float = "4.3.0"
|
||||
|
||||
[features]
|
||||
tracing = []
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use bevy::{ecs::world::CommandQueue, prelude::*, tasks::Task};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use world_generation::hex_utils::HexCoord;
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct Unit;
|
||||
@@ -19,7 +20,7 @@ pub enum UnitDomain {
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct Target(pub Vec3);
|
||||
pub struct Target(pub HexCoord);
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct Path(pub Vec<Vec3>, pub usize);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
|
||||
pub mod assets;
|
||||
pub mod components;
|
||||
pub mod nav_data;
|
||||
pub mod resources;
|
||||
#[cfg(debug_assertions)]
|
||||
pub mod units_debug_plugin;
|
||||
pub mod units_plugin;
|
||||
|
||||
70
game/units/src/nav_data.rs
Normal file
70
game/units/src/nav_data.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
use ordered_float::OrderedFloat;
|
||||
use world_generation::{
|
||||
hex_utils::HexCoord,
|
||||
prelude::{Chunk, Map},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NavData {
|
||||
pub tiles: Vec<NavTile>,
|
||||
pub map_height: usize,
|
||||
pub map_width: usize,
|
||||
}
|
||||
|
||||
impl NavData {
|
||||
pub fn get_neighbors(&self, coord: &HexCoord) -> Vec<(HexCoord, OrderedFloat<f32>)> {
|
||||
let mut neighbors = Vec::with_capacity(6);
|
||||
for i in 0..6 {
|
||||
let n = coord.get_neighbor(i);
|
||||
if !self.is_in_bounds(&n) {
|
||||
continue;
|
||||
}
|
||||
neighbors.push((n, OrderedFloat(1.0)));
|
||||
}
|
||||
return neighbors;
|
||||
}
|
||||
pub fn get(&self, coord: &HexCoord) -> &NavTile {
|
||||
return &self.tiles[coord.to_index(self.map_width)];
|
||||
}
|
||||
|
||||
pub fn is_in_bounds(&self, pos: &HexCoord) -> bool {
|
||||
return pos.is_in_bounds(self.map_height, self.map_width);
|
||||
}
|
||||
|
||||
pub fn build(map: &Map) -> NavData {
|
||||
let mut tiles = Vec::with_capacity(map.get_tile_count());
|
||||
let h = map.get_tile_height();
|
||||
let w = map.get_tile_width();
|
||||
for y in 0..h {
|
||||
for x in 0..w {
|
||||
let coord = HexCoord::from_grid_pos(x, y);
|
||||
let height = map.sample_height(&coord);
|
||||
let tile = NavTile {
|
||||
coord,
|
||||
height,
|
||||
move_cost: 1.0,
|
||||
};
|
||||
tiles.push(tile);
|
||||
}
|
||||
}
|
||||
|
||||
return NavData {
|
||||
tiles,
|
||||
map_width: w,
|
||||
map_height: h,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NavTile {
|
||||
pub height: f32,
|
||||
pub move_cost: f32,
|
||||
pub coord: HexCoord,
|
||||
}
|
||||
|
||||
impl NavTile {
|
||||
pub fn calculate_heuristic(&self, to: &HexCoord) -> OrderedFloat<f32> {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
1
game/units/src/resources.rs
Normal file
1
game/units/src/resources.rs
Normal file
@@ -0,0 +1 @@
|
||||
use bevy::prelude::*;
|
||||
@@ -60,7 +60,7 @@ fn set_unit_target(
|
||||
for e in units.iter() {
|
||||
info!("Setting Target");
|
||||
let mut e = commands.entity(e);
|
||||
e.insert(Target(contact.surface));
|
||||
e.insert(Target(contact.tile));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
use bevy::{
|
||||
ecs::world::CommandQueue, prelude::*, tasks::AsyncComputeTaskPool, transform::commands, utils::futures,
|
||||
window::PrimaryWindow,
|
||||
};
|
||||
use bevy_asset_loader::loading_state::{
|
||||
config::{ConfigureLoadingState, LoadingStateConfig},
|
||||
LoadingStateAppExt,
|
||||
};
|
||||
use shared::{resources::TileUnderCursor, sets::GameplaySet, states::AssetLoadState};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use bevy::{ecs::world::CommandQueue, prelude::*, tasks::AsyncComputeTaskPool, utils::futures};
|
||||
use pathfinding::prelude::astar;
|
||||
use shared::{resources::TileUnderCursor, sets::GameplaySet};
|
||||
use world_generation::{hex_utils::HexCoord, prelude::Map};
|
||||
|
||||
use crate::{
|
||||
assets::{unit_asset::UnitAssetPlugin, unit_database::UnitDatabase},
|
||||
assets::unit_asset::UnitAssetPlugin,
|
||||
components::{Path, PathTask, Target, Unit},
|
||||
nav_data::{self, NavData},
|
||||
units_debug_plugin::UnitsDebugPlugin,
|
||||
};
|
||||
|
||||
@@ -28,7 +25,10 @@ impl Plugin for UnitsPlugin {
|
||||
|
||||
app.add_systems(Update, units_control.in_set(GameplaySet));
|
||||
app.add_systems(Update, move_unit.in_set(GameplaySet));
|
||||
app.add_systems(FixedPreUpdate, (calculate_path, resolve_path_task).in_set(GameplaySet));
|
||||
app.add_systems(
|
||||
FixedPreUpdate,
|
||||
(dispatch_path_requests, resolve_path_task).in_set(GameplaySet),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,27 +60,41 @@ fn move_unit(
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_path(
|
||||
fn dispatch_path_requests(
|
||||
units: Query<(&Transform, &Target, Entity), (With<Unit>, Without<PathTask>)>,
|
||||
map: Res<Map>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
let pool = AsyncComputeTaskPool::get();
|
||||
let mut groups: HashMap<HexCoord, Vec<PathRequest>> = HashMap::new();
|
||||
|
||||
for (transform, target, entity) in units.iter() {
|
||||
let from = transform.translation;
|
||||
let to = target.0;
|
||||
let req = PathRequest {
|
||||
entity,
|
||||
to: HexCoord::from_world_pos(transform.translation),
|
||||
};
|
||||
if let Some(group) = groups.get_mut(&target.0) {
|
||||
group.push(req);
|
||||
} else {
|
||||
groups.insert(target.0, vec![req]);
|
||||
}
|
||||
}
|
||||
|
||||
let task = pool.spawn(async move {
|
||||
let mut queue = CommandQueue::default();
|
||||
let nav_data = NavData::build(&map);
|
||||
|
||||
queue.push(move |world: &mut World| {
|
||||
//todo: calculate path
|
||||
world.entity_mut(entity).insert(Path(vec![from, to], 0));
|
||||
let pool = AsyncComputeTaskPool::get();
|
||||
for (from, units) in groups {
|
||||
for req in units {
|
||||
let d = nav_data.clone();
|
||||
let task = pool.spawn(async move {
|
||||
let path = calculate_path(&from, &req.to, d);
|
||||
let mut queue = CommandQueue::default();
|
||||
queue.push(move |world: &mut World| {
|
||||
world.entity_mut(req.entity).insert(path);
|
||||
});
|
||||
return queue;
|
||||
});
|
||||
return queue;
|
||||
});
|
||||
|
||||
commands.entity(entity).insert(PathTask(task)).remove::<Target>();
|
||||
commands.entity(req.entity).insert(PathTask(task)).remove::<Target>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,3 +106,18 @@ fn resolve_path_task(mut tasks: Query<(&mut PathTask, Entity), With<Unit>>, mut
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_path(from: &HexCoord, to: &HexCoord, nav: NavData) -> Path {
|
||||
let path = astar(
|
||||
from,
|
||||
|n| nav.get_neighbors(n),
|
||||
|n| nav.get(n).calculate_heuristic(to),
|
||||
|n| n == to,
|
||||
);
|
||||
todo!("Convert path");
|
||||
}
|
||||
|
||||
struct PathRequest {
|
||||
pub entity: Entity,
|
||||
pub to: HexCoord,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user