path finding task setup
spacial set wip
This commit is contained in:
@@ -2,7 +2,7 @@ use bevy::prelude::*;
|
||||
#[derive(Component)]
|
||||
pub struct MainCamera;
|
||||
|
||||
#[derive(Component)]
|
||||
#[derive(Component, Clone, Copy)]
|
||||
pub enum Faction {
|
||||
Player,
|
||||
Phos,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy::{ecs::world::CommandQueue, prelude::*, tasks::Task};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
@@ -20,3 +20,9 @@ pub enum UnitDomain {
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct Target(pub Vec3);
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct Path(pub Vec<Vec3>, pub usize);
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct PathTask(pub Task<CommandQueue>);
|
||||
|
||||
@@ -4,3 +4,8 @@ pub mod components;
|
||||
pub mod units_debug_plugin;
|
||||
pub mod units_plugin;
|
||||
pub mod units_spacial_set;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum UnitType {
|
||||
Basic,
|
||||
}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
use bevy::{prelude::*, window::PrimaryWindow};
|
||||
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::{sets::GameplaySet, states::AssetLoadState};
|
||||
use shared::{resources::TileUnderCursor, sets::GameplaySet, states::AssetLoadState};
|
||||
use world_generation::{hex_utils::HexCoord, prelude::Map};
|
||||
|
||||
use crate::{
|
||||
assets::{unit_asset::UnitAssetPlugin, unit_database::UnitDatabase},
|
||||
components::{Target, Unit},
|
||||
components::{Path, PathTask, Target, Unit},
|
||||
units_debug_plugin::UnitsDebugPlugin,
|
||||
};
|
||||
|
||||
@@ -25,20 +28,30 @@ 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));
|
||||
}
|
||||
}
|
||||
|
||||
fn units_control(input: Res<ButtonInput<KeyCode>>, window: Query<&Window, With<PrimaryWindow>>) {
|
||||
let win = window.single();
|
||||
fn units_control(tile_under_cursor: Res<TileUnderCursor>) {}
|
||||
|
||||
let Some(cursor_pos) = win.cursor_position() else {
|
||||
return;
|
||||
};
|
||||
fn move_unit(
|
||||
mut units: Query<(&mut Transform, &mut Path, Entity), With<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() {
|
||||
commands.entity(entity).remove::<Path>();
|
||||
continue;
|
||||
}
|
||||
|
||||
fn move_unit(mut units: Query<(&mut Transform, &Target), With<Unit>>, time: Res<Time>, map: Res<Map>) {
|
||||
for (mut t, target) in units.iter_mut() {
|
||||
let vel = (target.0 - t.translation).normalize() * 10.0 * time.delta_seconds();
|
||||
let p = path.0[path.1];
|
||||
let d = p - t.translation;
|
||||
if d.length() < 0.1 {
|
||||
path.1 += 1;
|
||||
continue;
|
||||
}
|
||||
let vel = d.normalize() * 10.0 * time.delta_seconds();
|
||||
t.translation += vel;
|
||||
let coord = HexCoord::from_world_pos(t.translation);
|
||||
if map.is_in_bounds(&coord) {
|
||||
@@ -46,3 +59,36 @@ fn move_unit(mut units: Query<(&mut Transform, &Target), With<Unit>>, time: Res<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_path(
|
||||
units: Query<(&Transform, &Target, Entity), (With<Unit>, Without<PathTask>)>,
|
||||
map: Res<Map>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
let pool = AsyncComputeTaskPool::get();
|
||||
for (transform, target, entity) in units.iter() {
|
||||
let from = transform.translation;
|
||||
let to = target.0;
|
||||
|
||||
let task = pool.spawn(async move {
|
||||
let mut queue = CommandQueue::default();
|
||||
|
||||
queue.push(move |world: &mut World| {
|
||||
//todo: calculate path
|
||||
world.entity_mut(entity).insert(Path(vec![from, to], 0));
|
||||
});
|
||||
return queue;
|
||||
});
|
||||
|
||||
commands.entity(entity).insert(PathTask(task)).remove::<Target>();
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_path_task(mut tasks: Query<(&mut PathTask, Entity), With<Unit>>, mut commands: Commands) {
|
||||
for (mut task, entity) in tasks.iter_mut() {
|
||||
if let Some(mut c) = futures::check_ready(&mut task.0) {
|
||||
commands.append(&mut c);
|
||||
commands.entity(entity).remove::<PathTask>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
use bevy::prelude::*;
|
||||
use quadtree_rs::{point::Point, Quadtree};
|
||||
use quadtree_rs::{area::AreaBuilder, point::Point, Quadtree};
|
||||
use shared::tags::Faction;
|
||||
use world_generation::hex_utils::HexCoord;
|
||||
|
||||
use crate::components::UnitDomain;
|
||||
use crate::{components::UnitDomain, UnitType};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct UnitEntity {
|
||||
pub entity: Entity,
|
||||
pub domain: UnitDomain,
|
||||
pub unitType: (),
|
||||
pub unit_type: UnitType,
|
||||
pub faction: Faction,
|
||||
pub position: Vec3,
|
||||
}
|
||||
|
||||
pub struct UnitSpacialSet {
|
||||
@@ -25,17 +26,57 @@ impl UnitSpacialSet {
|
||||
}
|
||||
|
||||
pub fn add_unit(&mut self, unit: UnitEntity, pos: Vec3) -> Option<u64> {
|
||||
let p = pos.xz().as_uvec2();
|
||||
return self.tree.insert_pt(
|
||||
Point {
|
||||
x: p.x as usize,
|
||||
y: p.y as usize,
|
||||
},
|
||||
unit,
|
||||
);
|
||||
return self.tree.insert_pt(convert_to_point(pos.xz()), unit);
|
||||
}
|
||||
|
||||
pub fn move_unit(&mut self, handle: u64) {
|
||||
todo!();
|
||||
pub fn move_unit(&mut self, handle: u64, pos: Vec3) -> Option<u64> {
|
||||
if let Some(existing) = self.tree.get(handle) {
|
||||
if existing.anchor() == convert_to_point(pos.xz()) {
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(entry) = self.tree.delete_by_handle(handle) {
|
||||
let p = convert_to_point(pos.xz());
|
||||
let mut entry = *entry.value_ref();
|
||||
entry.position = pos;
|
||||
return self.tree.insert_pt(p, entry);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
pub fn get_units_in_circle(self, center: Vec3, radius: f32) -> Vec<Entity> {
|
||||
let anchor = center.xz() - Vec2::new(radius, radius);
|
||||
let d = (radius * 2.0) as usize;
|
||||
let area = AreaBuilder::default()
|
||||
.anchor(convert_to_point(anchor))
|
||||
.dimensions((d, d))
|
||||
.build()
|
||||
.unwrap();
|
||||
let query = self.tree.query(area);
|
||||
return query
|
||||
.filter(|e| e.value_ref().position.distance(center) <= radius)
|
||||
.map(|e| e.value_ref().entity)
|
||||
.collect();
|
||||
}
|
||||
|
||||
pub fn get_units_in_rect(self, anchor: Vec2, size: Vec2) -> Vec<Entity> {
|
||||
let area = AreaBuilder::default()
|
||||
.anchor(convert_to_point(anchor))
|
||||
.dimensions((size.x as usize, size.y as usize))
|
||||
.build()
|
||||
.unwrap();
|
||||
let query = self.tree.query(area);
|
||||
return query.map(|e| e.value_ref().entity).collect();
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_to_point(pos: Vec2) -> Point<usize> {
|
||||
let p = pos.as_uvec2();
|
||||
return Point {
|
||||
x: p.x as usize,
|
||||
y: p.y as usize,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user