refactoring hex coords
This commit is contained in:
@@ -18,6 +18,7 @@ bevy_asset_loader = { version = "0.25.0", features = [
|
||||
"standard_dynamic_assets",
|
||||
"3d",
|
||||
] }
|
||||
hex = { path = "../../engine/hex" }
|
||||
|
||||
[features]
|
||||
tracing = []
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
|
||||
use bevy::prelude::Resource;
|
||||
use hex::prelude::*;
|
||||
use shared::building::BuildingIdentifier;
|
||||
use world_generation::hex_utils::HexCoord;
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct BuildQueue {
|
||||
pub struct BuildQueue
|
||||
{
|
||||
pub queue: Vec<QueueEntry>,
|
||||
}
|
||||
|
||||
impl Default for BuildQueue {
|
||||
fn default() -> Self {
|
||||
impl Default for BuildQueue
|
||||
{
|
||||
fn default() -> Self
|
||||
{
|
||||
Self {
|
||||
queue: Default::default(),
|
||||
}
|
||||
@@ -17,7 +19,8 @@ impl Default for BuildQueue {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct QueueEntry {
|
||||
pub struct QueueEntry
|
||||
{
|
||||
pub building: BuildingIdentifier,
|
||||
pub pos: HexCoord,
|
||||
}
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
use bevy::prelude::*;
|
||||
use world_generation::{hex_utils::HexCoord, prelude::Chunk};
|
||||
use hex::prelude::*;
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct BuildingMap {
|
||||
pub struct BuildingMap
|
||||
{
|
||||
pub chunks: Vec<BuildingChunk>,
|
||||
pub size: UVec2,
|
||||
}
|
||||
|
||||
impl BuildingMap {
|
||||
pub fn new(size: UVec2) -> Self {
|
||||
impl BuildingMap
|
||||
{
|
||||
pub fn new(size: UVec2) -> Self
|
||||
{
|
||||
let mut db = BuildingMap {
|
||||
size,
|
||||
chunks: Vec::with_capacity(size.length_squared() as usize),
|
||||
};
|
||||
|
||||
for y in 0..size.y as i32 {
|
||||
for x in 0..size.x as i32 {
|
||||
for y in 0..size.y as i32
|
||||
{
|
||||
for x in 0..size.x as i32
|
||||
{
|
||||
let offset = IVec2::new(x, y);
|
||||
let index = (x + y * size.x as i32) as usize;
|
||||
db.chunks.push(BuildingChunk::new(offset, index));
|
||||
@@ -25,7 +30,8 @@ impl BuildingMap {
|
||||
return db;
|
||||
}
|
||||
|
||||
pub fn get_buildings_in_range(&self, coord: &HexCoord, radius: usize) -> Vec<&BuildingEntry> {
|
||||
pub fn get_buildings_in_range(&self, coord: &HexCoord, radius: usize) -> Vec<&BuildingEntry>
|
||||
{
|
||||
assert!(radius != 0, "Radius cannot be zero");
|
||||
|
||||
let w = self.size.x as usize * Chunk::SIZE;
|
||||
@@ -34,10 +40,13 @@ impl BuildingMap {
|
||||
return self.get_buildings_in_coords(coords);
|
||||
}
|
||||
|
||||
pub fn get_buildings_in_coords(&self, coords: Vec<HexCoord>) -> Vec<&BuildingEntry> {
|
||||
pub fn get_buildings_in_coords(&self, coords: Vec<HexCoord>) -> Vec<&BuildingEntry>
|
||||
{
|
||||
let mut result = Vec::new();
|
||||
for coord in &coords {
|
||||
if let Some(buidling) = self.get_building(coord) {
|
||||
for coord in &coords
|
||||
{
|
||||
if let Some(buidling) = self.get_building(coord)
|
||||
{
|
||||
result.push(buidling);
|
||||
}
|
||||
}
|
||||
@@ -45,25 +54,30 @@ impl BuildingMap {
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry> {
|
||||
pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry>
|
||||
{
|
||||
let chunk = &self.chunks[coord.to_chunk_index(self.size.x as usize)];
|
||||
return chunk.get_building(coord);
|
||||
}
|
||||
|
||||
pub fn add_building(&mut self, entry: BuildingEntry) {
|
||||
pub fn add_building(&mut self, entry: BuildingEntry)
|
||||
{
|
||||
let chunk = &mut self.chunks[entry.coord.to_chunk_index(self.size.x as usize)];
|
||||
chunk.add_building(entry);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BuildingChunk {
|
||||
pub struct BuildingChunk
|
||||
{
|
||||
pub entries: Vec<BuildingEntry>,
|
||||
pub index: usize,
|
||||
pub offset: IVec2,
|
||||
}
|
||||
|
||||
impl BuildingChunk {
|
||||
pub fn new(offset: IVec2, index: usize) -> Self {
|
||||
impl BuildingChunk
|
||||
{
|
||||
pub fn new(offset: IVec2, index: usize) -> Self
|
||||
{
|
||||
return BuildingChunk {
|
||||
entries: Vec::new(),
|
||||
index,
|
||||
@@ -71,16 +85,19 @@ impl BuildingChunk {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry> {
|
||||
pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry>
|
||||
{
|
||||
return self.entries.iter().find(|b| &b.coord == coord);
|
||||
}
|
||||
|
||||
pub fn add_building(&mut self, entry: BuildingEntry) {
|
||||
pub fn add_building(&mut self, entry: BuildingEntry)
|
||||
{
|
||||
self.entries.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BuildingEntry {
|
||||
pub struct BuildingEntry
|
||||
{
|
||||
pub coord: HexCoord,
|
||||
pub entity: Entity,
|
||||
pub is_main: bool,
|
||||
@@ -89,8 +106,10 @@ pub struct BuildingEntry {
|
||||
pub child_entities: Option<Vec<Entity>>,
|
||||
}
|
||||
|
||||
impl BuildingEntry {
|
||||
pub fn new(coord: HexCoord, entity: Entity) -> Self {
|
||||
impl BuildingEntry
|
||||
{
|
||||
pub fn new(coord: HexCoord, entity: Entity) -> Self
|
||||
{
|
||||
return BuildingEntry {
|
||||
coord,
|
||||
entity,
|
||||
@@ -101,7 +120,8 @@ impl BuildingEntry {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn new_with_children(coord: HexCoord, entity: Entity, children: Vec<Entity>) -> BuildingEntry {
|
||||
pub fn new_with_children(coord: HexCoord, entity: Entity, children: Vec<Entity>) -> BuildingEntry
|
||||
{
|
||||
return BuildingEntry {
|
||||
coord,
|
||||
entity,
|
||||
@@ -112,7 +132,8 @@ impl BuildingEntry {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn new_with_parent(coord: HexCoord, entity: Entity, main: Entity) -> BuildingEntry {
|
||||
pub fn new_with_parent(coord: HexCoord, entity: Entity, main: Entity) -> BuildingEntry
|
||||
{
|
||||
return BuildingEntry {
|
||||
coord,
|
||||
entity,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use bevy::math::{IVec2, Vec3Swizzles};
|
||||
use hex::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use shared::coords::CoordsCollection;
|
||||
use world_generation::hex_utils::HexCoord;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct BuildingFootprint
|
||||
@@ -21,7 +21,7 @@ impl BuildingFootprint
|
||||
let n_points: Vec<IVec2> = self
|
||||
.footprint
|
||||
.iter()
|
||||
.flat_map(|p| HexCoord::from_hex(*p).get_neighbors())
|
||||
.flat_map(|p| HexCoord::from_axial(*p).get_neighbors())
|
||||
.map(|c| c.hex.xy())
|
||||
.filter(|p| !self.footprint.contains(p))
|
||||
.collect();
|
||||
|
||||
@@ -27,6 +27,8 @@ bevy_asset_loader = { version = "0.25.0", features = [
|
||||
] }
|
||||
ron = "0.12.0"
|
||||
image = "0.25.9"
|
||||
hex = { path = "../../engine/hex" }
|
||||
|
||||
# bevy_lunex = "0.2.4"
|
||||
|
||||
[features]
|
||||
|
||||
@@ -3,9 +3,9 @@ use bevy::core_pipeline::prepass::DepthPrepass;
|
||||
use bevy::input::mouse::{MouseMotion, MouseScrollUnit, MouseWheel};
|
||||
use bevy::prelude::*;
|
||||
use bevy::window::{CursorGrabMode, CursorOptions, PrimaryWindow};
|
||||
use hex::prelude::*;
|
||||
use shared::sets::GameplaySet;
|
||||
use shared::tags::MainCamera;
|
||||
use world_generation::hex_utils::HexCoord;
|
||||
use world_generation::prelude::Map;
|
||||
use world_generation::states::GeneratorState;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use bevy::prelude::*;
|
||||
use hex::prelude::*;
|
||||
use rayon::str;
|
||||
use world_generation::prelude::Chunk;
|
||||
|
||||
#[derive(Component, Reflect)]
|
||||
#[reflect(Component)]
|
||||
|
||||
@@ -4,13 +4,14 @@ use bevy::{light::NotShadowCaster, pbr::ExtendedMaterial, prelude::*};
|
||||
use bevy_asset_loader::prelude::*;
|
||||
|
||||
use bevy_inspector_egui::quick::ResourceInspectorPlugin;
|
||||
use hex::prelude::*;
|
||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||
use shared::states::{AssetLoadState, GameplayState, MenuState};
|
||||
|
||||
use world_generation::{
|
||||
biome_asset::{BiomeAsset, BiomeAssetPlugin},
|
||||
biome_painter::*,
|
||||
heightmap::generate_heightmap,
|
||||
hex_utils::{offset_to_index, SHORT_DIAGONAL},
|
||||
map::biome_map::BiomeMap,
|
||||
prelude::*,
|
||||
tile_manager::*,
|
||||
|
||||
@@ -7,6 +7,7 @@ use bevy::{
|
||||
mesh::Mesh,
|
||||
};
|
||||
use bevy_rapier3d::geometry::{Collider, TriMeshFlags};
|
||||
use hex::prelude::*;
|
||||
use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator};
|
||||
use world_generation::{
|
||||
biome_painter::BiomePainter,
|
||||
@@ -14,8 +15,7 @@ use world_generation::{
|
||||
chunk_colliders::generate_chunk_collider,
|
||||
mesh_generator::{generate_chunk_mesh, generate_chunk_water_mesh},
|
||||
},
|
||||
hex_utils::offset_to_world,
|
||||
prelude::{Chunk, Map, MeshChunkData},
|
||||
prelude::{Map, MeshChunkData},
|
||||
tile_manager::TileAsset,
|
||||
tile_mapper::TileMapperAsset,
|
||||
};
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use bevy::{prelude::*, window::PrimaryWindow};
|
||||
use bevy_rapier3d::{plugin::ReadRapierContext, prelude::QueryFilter};
|
||||
use hex::prelude::*;
|
||||
use shared::{
|
||||
resources::{TileContact, TileUnderCursor},
|
||||
tags::MainCamera,
|
||||
};
|
||||
use world_generation::{hex_utils::HexCoord, prelude::Map, states::GeneratorState};
|
||||
use world_generation::{prelude::Map, states::GeneratorState};
|
||||
|
||||
pub struct TileSelectionPlugin;
|
||||
|
||||
impl Plugin for TileSelectionPlugin
|
||||
|
||||
@@ -9,6 +9,7 @@ edition = "2021"
|
||||
bevy = "0.18.0"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
world_generation = { path = "../../engine/world_generation" }
|
||||
hex = { path = "../../engine/hex" }
|
||||
|
||||
|
||||
[features]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use bevy::prelude::*;
|
||||
use world_generation::hex_utils::HexCoord;
|
||||
use hex::prelude::*;
|
||||
|
||||
#[derive(Default, Debug, Reflect)]
|
||||
pub struct CoordsCollection
|
||||
@@ -51,11 +51,11 @@ impl CoordsCollection
|
||||
|
||||
pub fn get_coords(&self) -> Vec<HexCoord>
|
||||
{
|
||||
let center = HexCoord::from_hex(self.origin);
|
||||
let center = HexCoord::from_axial(self.origin);
|
||||
return self
|
||||
.points
|
||||
.iter()
|
||||
.map(|p| HexCoord::from_hex(p + self.origin).rotate_around(¢er, self.rotation))
|
||||
.map(|p| HexCoord::from_axial(p + self.origin).rotate_around(¢er, self.rotation))
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
use bevy::prelude::*;
|
||||
use world_generation::hex_utils::*;
|
||||
use hex::prelude::*;
|
||||
|
||||
#[derive(Message)]
|
||||
pub enum TileModifiedEvent {
|
||||
pub enum TileModifiedEvent
|
||||
{
|
||||
HeightChanged(HexCoord, f32),
|
||||
TypeChanged(HexCoord, usize),
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
pub struct ChunkModifiedEvent {
|
||||
pub struct ChunkModifiedEvent
|
||||
{
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
use bevy::prelude::*;
|
||||
use world_generation::hex_utils::HexCoord;
|
||||
use hex::prelude::*;
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct TileUnderCursor(pub Option<TileContact>);
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct TileContact {
|
||||
pub struct TileContact
|
||||
{
|
||||
pub tile: HexCoord,
|
||||
pub point: Vec3,
|
||||
pub surface: Vec3,
|
||||
}
|
||||
|
||||
impl TileContact {
|
||||
pub fn new(tile: HexCoord, contact: Vec3, surface: Vec3) -> Self {
|
||||
impl TileContact
|
||||
{
|
||||
pub fn new(tile: HexCoord, contact: Vec3, surface: Vec3) -> Self
|
||||
{
|
||||
return Self {
|
||||
tile,
|
||||
point: contact,
|
||||
|
||||
@@ -6,6 +6,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
bevy = "0.18.0"
|
||||
world_generation = { path = "../../engine/world_generation" }
|
||||
hex = { path = "../../engine/hex" }
|
||||
shared = { path = "../shared" }
|
||||
bevy_rapier3d = "0.33.0"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use bevy::{ecs::world::CommandQueue, prelude::*, tasks::Task};
|
||||
use hex::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use world_generation::hex_utils::HexCoord;
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct Unit;
|
||||
@@ -13,7 +13,8 @@ pub struct LandUnit;
|
||||
pub struct NavalUnit;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||
pub enum UnitDomain {
|
||||
pub enum UnitDomain
|
||||
{
|
||||
Land,
|
||||
Air,
|
||||
Naval,
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
use bevy::prelude::*;
|
||||
use hex::prelude::*;
|
||||
use ordered_float::OrderedFloat;
|
||||
use world_generation::{hex_utils::HexCoord, prelude::Map};
|
||||
use world_generation::prelude::Map;
|
||||
|
||||
#[derive(Clone, Resource)]
|
||||
pub struct NavData {
|
||||
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>)> {
|
||||
impl NavData
|
||||
{
|
||||
pub fn get_neighbors(&self, coord: &HexCoord) -> Vec<(HexCoord, OrderedFloat<f32>)>
|
||||
{
|
||||
let mut neighbors = Vec::with_capacity(6);
|
||||
let cur_height = self.get_height(coord);
|
||||
for i in 0..6 {
|
||||
for i in 0..6
|
||||
{
|
||||
let n = coord.get_neighbor(i);
|
||||
if !self.is_in_bounds(&n) {
|
||||
if !self.is_in_bounds(&n)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let n_height = self.get_height(&n);
|
||||
@@ -23,26 +29,32 @@ impl NavData {
|
||||
}
|
||||
return neighbors;
|
||||
}
|
||||
pub fn get(&self, coord: &HexCoord) -> &NavTile {
|
||||
pub fn get(&self, coord: &HexCoord) -> &NavTile
|
||||
{
|
||||
return &self.tiles[coord.to_index(self.map_width)];
|
||||
}
|
||||
|
||||
pub fn get_height(&self, coord: &HexCoord) -> f32 {
|
||||
pub fn get_height(&self, coord: &HexCoord) -> f32
|
||||
{
|
||||
return self.tiles[coord.to_index(self.map_width)].height;
|
||||
}
|
||||
|
||||
pub fn is_in_bounds(&self, pos: &HexCoord) -> bool {
|
||||
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 {
|
||||
pub fn build(map: &Map) -> NavData
|
||||
{
|
||||
#[cfg(feature = "tracing")]
|
||||
let _path_span = info_span!("Build Nav Data").entered();
|
||||
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 {
|
||||
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 {
|
||||
@@ -61,13 +73,16 @@ impl NavData {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn update(&mut self, map: &Map) {
|
||||
pub fn update(&mut self, map: &Map)
|
||||
{
|
||||
#[cfg(feature = "tracing")]
|
||||
let _path_span = info_span!("Update Nav Data").entered();
|
||||
let h = map.get_tile_height();
|
||||
let w = map.get_tile_width();
|
||||
for y in 0..h {
|
||||
for x in 0..w {
|
||||
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 {
|
||||
@@ -79,7 +94,8 @@ impl NavData {
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn update_tile(&mut self, coord: &HexCoord, height: f32, move_cost: f32) {
|
||||
pub fn update_tile(&mut self, coord: &HexCoord, height: f32, move_cost: f32)
|
||||
{
|
||||
let tile = &mut self.tiles[coord.to_index(self.map_width)];
|
||||
tile.move_cost = move_cost;
|
||||
tile.height = height;
|
||||
@@ -87,14 +103,17 @@ impl NavData {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NavTile {
|
||||
pub struct NavTile
|
||||
{
|
||||
pub height: f32,
|
||||
pub move_cost: f32,
|
||||
pub coord: HexCoord,
|
||||
}
|
||||
|
||||
impl NavTile {
|
||||
pub fn calculate_heuristic(&self, to: &HexCoord) -> OrderedFloat<f32> {
|
||||
impl NavTile
|
||||
{
|
||||
pub fn calculate_heuristic(&self, to: &HexCoord) -> OrderedFloat<f32>
|
||||
{
|
||||
return (self.coord.distance(to) as f32).into();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,10 @@ use bevy::{
|
||||
prelude::*,
|
||||
tasks::{futures, AsyncComputeTaskPool},
|
||||
};
|
||||
use hex::prelude::*;
|
||||
use pathfinding::prelude::astar;
|
||||
use shared::{events::TileModifiedEvent, resources::TileUnderCursor, sets::GameplaySet};
|
||||
use world_generation::{hex_utils::HexCoord, prelude::Map, states::GeneratorState};
|
||||
use world_generation::{prelude::Map, states::GeneratorState};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
use crate::units_debug_plugin::UnitsDebugPlugin;
|
||||
@@ -20,8 +21,10 @@ use crate::{
|
||||
|
||||
pub struct UnitsPlugin;
|
||||
|
||||
impl Plugin for UnitsPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
impl Plugin for UnitsPlugin
|
||||
{
|
||||
fn build(&self, app: &mut App)
|
||||
{
|
||||
app.init_resource::<PathBatchId>();
|
||||
app.add_plugins(UnitAssetPlugin);
|
||||
|
||||
@@ -40,15 +43,20 @@ impl Plugin for UnitsPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_navdata(mut commands: Commands, map: Res<Map>) {
|
||||
fn build_navdata(mut commands: Commands, map: Res<Map>)
|
||||
{
|
||||
let nav_data = NavData::build(&map);
|
||||
commands.insert_resource(nav_data);
|
||||
}
|
||||
|
||||
fn update_navdata(mut tile_updates: MessageReader<TileModifiedEvent>, mut nav_data: ResMut<NavData>) {
|
||||
for event in tile_updates.read() {
|
||||
match event {
|
||||
TileModifiedEvent::HeightChanged(coord, new_height) => {
|
||||
fn update_navdata(mut tile_updates: MessageReader<TileModifiedEvent>, mut nav_data: ResMut<NavData>)
|
||||
{
|
||||
for event in tile_updates.read()
|
||||
{
|
||||
match event
|
||||
{
|
||||
TileModifiedEvent::HeightChanged(coord, new_height) =>
|
||||
{
|
||||
nav_data.update_tile(coord, *new_height, 1.0);
|
||||
}
|
||||
_ => (),
|
||||
@@ -56,6 +64,7 @@ fn update_navdata(mut tile_updates: MessageReader<TileModifiedEvent>, mut nav_da
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn units_control(tile_under_cursor: Res<TileUnderCursor>) {}
|
||||
|
||||
fn move_unit(
|
||||
@@ -63,22 +72,27 @@ fn move_unit(
|
||||
time: Res<Time>,
|
||||
map: Res<Map>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (mut t, mut path, entity) in units.iter_mut() {
|
||||
if path.1 >= path.0.len() {
|
||||
)
|
||||
{
|
||||
for (mut t, mut path, entity) in units.iter_mut()
|
||||
{
|
||||
if path.1 >= path.0.len()
|
||||
{
|
||||
commands.entity(entity).remove::<Path>();
|
||||
continue;
|
||||
}
|
||||
let p = path.0[path.1];
|
||||
let d = p - t.translation;
|
||||
if d.length() < 0.1 {
|
||||
if d.length() < 0.1
|
||||
{
|
||||
path.1 += 1;
|
||||
continue;
|
||||
}
|
||||
let vel = d.normalize() * 10.0 * time.delta_secs();
|
||||
t.translation += vel;
|
||||
let coord = HexCoord::from_world_pos(t.translation);
|
||||
if map.is_in_bounds(&coord) {
|
||||
if map.is_in_bounds(&coord)
|
||||
{
|
||||
t.translation.y = map.sample_height(&coord);
|
||||
}
|
||||
}
|
||||
@@ -90,22 +104,28 @@ fn dispatch_path_requests(
|
||||
nav_data: Res<NavData>,
|
||||
mut batch_id: ResMut<PathBatchId>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
if units.is_empty() {
|
||||
)
|
||||
{
|
||||
if units.is_empty()
|
||||
{
|
||||
return;
|
||||
}
|
||||
let mut groups: HashMap<HexCoord, Vec<PathRequest>> = HashMap::new();
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
let _group_span = info_span!("Grouping").entered();
|
||||
for (transform, target, entity) in units.iter() {
|
||||
for (transform, target, entity) in units.iter()
|
||||
{
|
||||
let req = PathRequest {
|
||||
entity,
|
||||
from: HexCoord::from_world_pos(transform.translation),
|
||||
};
|
||||
if let Some(group) = groups.get_mut(&target.0) {
|
||||
if let Some(group) = groups.get_mut(&target.0)
|
||||
{
|
||||
group.push(req);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
groups.insert(target.0, vec![req]);
|
||||
}
|
||||
}
|
||||
@@ -113,11 +133,13 @@ fn dispatch_path_requests(
|
||||
drop(_group_span);
|
||||
|
||||
let pool = AsyncComputeTaskPool::get();
|
||||
for (target, units) in groups {
|
||||
for (target, units) in groups
|
||||
{
|
||||
let id = batch_id.0;
|
||||
batch_id.0 += 1;
|
||||
|
||||
for req in &units {
|
||||
for req in &units
|
||||
{
|
||||
commands
|
||||
.entity(req.entity)
|
||||
.insert(PathTaskPending(id))
|
||||
@@ -136,17 +158,21 @@ fn dispatch_path_requests(
|
||||
let batch_task = pool.spawn(async move {
|
||||
let mut i = 0;
|
||||
let mut queue = CommandQueue::default();
|
||||
for entitiy_req in req.entities {
|
||||
for entitiy_req in req.entities
|
||||
{
|
||||
let dst = req.destination[i];
|
||||
i += 1;
|
||||
#[cfg(feature = "tracing")]
|
||||
let _path_span = info_span!("Path Finding").entered();
|
||||
if let Some(path) = calculate_path(&entitiy_req.from, &dst, &local_nav_data) {
|
||||
if let Some(path) = calculate_path(&entitiy_req.from, &dst, &local_nav_data)
|
||||
{
|
||||
queue.push(move |world: &mut World| {
|
||||
let mut unit_e = world.entity_mut(entitiy_req.entity);
|
||||
|
||||
if let Some(pending_task) = unit_e.get::<PathTaskPending>() {
|
||||
if pending_task.0 == id {
|
||||
if let Some(pending_task) = unit_e.get::<PathTaskPending>()
|
||||
{
|
||||
if pending_task.0 == id
|
||||
{
|
||||
unit_e.insert(path);
|
||||
unit_e.remove::<PathTaskPending>();
|
||||
}
|
||||
@@ -154,7 +180,8 @@ fn dispatch_path_requests(
|
||||
});
|
||||
}
|
||||
}
|
||||
if queue.is_empty() {
|
||||
if queue.is_empty()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
return Some(queue);
|
||||
@@ -163,26 +190,36 @@ fn dispatch_path_requests(
|
||||
}
|
||||
}
|
||||
|
||||
fn get_end_points(coord: &HexCoord, count: usize, map: &Map) -> Vec<HexCoord> {
|
||||
fn get_end_points(coord: &HexCoord, count: usize, map: &Map) -> Vec<HexCoord>
|
||||
{
|
||||
let mut result = Vec::with_capacity(count);
|
||||
if count == 1 {
|
||||
if count == 1
|
||||
{
|
||||
return vec![*coord];
|
||||
}
|
||||
result.push(*coord);
|
||||
let mut r = 1;
|
||||
while result.len() < count {
|
||||
while result.len() < count
|
||||
{
|
||||
let tiles = HexCoord::select_ring(coord, r);
|
||||
let needed = count - result.len();
|
||||
if needed >= tiles.len() {
|
||||
for t in tiles {
|
||||
if map.is_in_bounds(&t) {
|
||||
if needed >= tiles.len()
|
||||
{
|
||||
for t in tiles
|
||||
{
|
||||
if map.is_in_bounds(&t)
|
||||
{
|
||||
result.push(t);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i in 0..needed {
|
||||
}
|
||||
else
|
||||
{
|
||||
for i in 0..needed
|
||||
{
|
||||
let t = tiles[i];
|
||||
if map.is_in_bounds(&t) {
|
||||
if map.is_in_bounds(&t)
|
||||
{
|
||||
result.push(t);
|
||||
}
|
||||
}
|
||||
@@ -193,10 +230,14 @@ fn get_end_points(coord: &HexCoord, count: usize, map: &Map) -> Vec<HexCoord> {
|
||||
return result;
|
||||
}
|
||||
|
||||
fn resolve_path_task(mut tasks: Query<(&mut PathTask, Entity)>, mut commands: Commands) {
|
||||
for (mut task, entity) in tasks.iter_mut() {
|
||||
if let Some(c) = futures::check_ready(&mut task.0) {
|
||||
if let Some(mut queue) = c {
|
||||
fn resolve_path_task(mut tasks: Query<(&mut PathTask, Entity)>, mut commands: Commands)
|
||||
{
|
||||
for (mut task, entity) in tasks.iter_mut()
|
||||
{
|
||||
if let Some(c) = futures::check_ready(&mut task.0)
|
||||
{
|
||||
if let Some(mut queue) = c
|
||||
{
|
||||
commands.append(&mut queue);
|
||||
}
|
||||
commands.entity(entity).despawn();
|
||||
@@ -204,32 +245,38 @@ fn resolve_path_task(mut tasks: Query<(&mut PathTask, Entity)>, mut commands: Co
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_path(from: &HexCoord, to: &HexCoord, nav: &NavData) -> Option<Path> {
|
||||
fn calculate_path(from: &HexCoord, to: &HexCoord, nav: &NavData) -> Option<Path>
|
||||
{
|
||||
let path = astar(
|
||||
from,
|
||||
|n| nav.get_neighbors(n),
|
||||
|n| nav.get(n).calculate_heuristic(to),
|
||||
|n| n == to,
|
||||
);
|
||||
if let Some((nodes, _cost)) = path {
|
||||
if let Some((nodes, _cost)) = path
|
||||
{
|
||||
let result: Vec<_> = nodes.iter().map(|f| f.to_world(nav.get_height(f))).collect();
|
||||
return Some(Path(result, 1));
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
struct PathRequest {
|
||||
struct PathRequest
|
||||
{
|
||||
pub entity: Entity,
|
||||
pub from: HexCoord,
|
||||
}
|
||||
|
||||
struct BatchPathRequest {
|
||||
struct BatchPathRequest
|
||||
{
|
||||
pub entities: Vec<PathRequest>,
|
||||
pub destination: Vec<HexCoord>,
|
||||
}
|
||||
|
||||
impl BatchPathRequest {
|
||||
pub fn new(entities: Vec<PathRequest>, dst: Vec<HexCoord>) -> Self {
|
||||
impl BatchPathRequest
|
||||
{
|
||||
pub fn new(entities: Vec<PathRequest>, dst: Vec<HexCoord>) -> Self
|
||||
{
|
||||
return Self {
|
||||
destination: dst,
|
||||
entities,
|
||||
|
||||
Reference in New Issue
Block a user