Compare commits
No commits in common. "f19beaa73aa0c24c30aae3644192097835ba4c3d" and "afca116394f3560d21684f63d05317d66e1367f8" have entirely different histories.
f19beaa73a
...
afca116394
21
Cargo.toml
21
Cargo.toml
|
@ -13,14 +13,25 @@ speech_dispatcher_0_9 = ["bevy_tts/speech_dispatcher_0_9"]
|
||||||
speech_dispatcher_0_10 = ["bevy_tts/speech_dispatcher_0_10"]
|
speech_dispatcher_0_10 = ["bevy_tts/speech_dispatcher_0_10"]
|
||||||
speech_dispatcher_0_11 = ["bevy_tts/speech_dispatcher_0_11"]
|
speech_dispatcher_0_11 = ["bevy_tts/speech_dispatcher_0_11"]
|
||||||
|
|
||||||
|
[dependencies.bevy]
|
||||||
|
version = "0.13"
|
||||||
|
default-features = false
|
||||||
|
features = [
|
||||||
|
"bevy_gilrs",
|
||||||
|
"bevy_winit",
|
||||||
|
"x11",
|
||||||
|
"wayland",
|
||||||
|
"multi-threaded",
|
||||||
|
"serialize",
|
||||||
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = "0.14"
|
bevy_rapier2d = "0.25"
|
||||||
bevy_rapier2d = "0.27"
|
bevy_synthizer = "0.6"
|
||||||
bevy_synthizer = "0.7"
|
bevy_tts = { version = "0.8", default-features = false, features = ["tolk"] }
|
||||||
bevy_tts = { version = "0.9", default-features = false, features = ["tolk"] }
|
|
||||||
coord_2d = "0.3"
|
coord_2d = "0.3"
|
||||||
here_be_dragons = { version = "0.3", features = ["serde"] }
|
here_be_dragons = { version = "0.3", features = ["serde"] }
|
||||||
leafwing-input-manager = "0.14"
|
leafwing-input-manager = "0.13"
|
||||||
maze_generator = "2"
|
maze_generator = "2"
|
||||||
once_cell = "1"
|
once_cell = "1"
|
||||||
pathfinding = "4"
|
pathfinding = "4"
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::{
|
||||||
sync::RwLock,
|
sync::RwLock,
|
||||||
};
|
};
|
||||||
|
|
||||||
use bevy::{app::PluginGroupBuilder, math::FloatOrd, prelude::*};
|
use bevy::{app::PluginGroupBuilder, prelude::*, utils::FloatOrd};
|
||||||
use bevy_rapier2d::{
|
use bevy_rapier2d::{
|
||||||
parry::query::{closest_points, distance, ClosestPoints},
|
parry::query::{closest_points, distance, ClosestPoints},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
|
131
src/map.rs
131
src/map.rs
|
@ -82,7 +82,8 @@ impl ITileType for Tile {
|
||||||
pub struct PortalBundle {
|
pub struct PortalBundle {
|
||||||
pub portal: Portal,
|
pub portal: Portal,
|
||||||
pub mappable: Mappable,
|
pub mappable: Mappable,
|
||||||
pub transform: TransformBundle,
|
pub transform: Transform,
|
||||||
|
pub global_transform: GlobalTransform,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Bundle, Clone, Default)]
|
#[derive(Bundle, Clone, Default)]
|
||||||
|
@ -90,75 +91,8 @@ pub struct MapBundle<D: 'static + Clone + Default + Send + Sync> {
|
||||||
pub map: Map<D>,
|
pub map: Map<D>,
|
||||||
pub spawn_colliders: SpawnColliders,
|
pub spawn_colliders: SpawnColliders,
|
||||||
pub spawn_portals: SpawnPortals,
|
pub spawn_portals: SpawnPortals,
|
||||||
pub transform: TransformBundle,
|
pub transform: Transform,
|
||||||
}
|
pub global_transform: GlobalTransform,
|
||||||
|
|
||||||
#[derive(Bundle, Clone, Debug)]
|
|
||||||
pub struct TileBundle {
|
|
||||||
pub transform: TransformBundle,
|
|
||||||
pub collider: Collider,
|
|
||||||
pub rigid_body: RigidBody,
|
|
||||||
pub active_collision_types: ActiveCollisionTypes,
|
|
||||||
pub map_obstruction: MapObstruction,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for TileBundle {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
transform: default(),
|
|
||||||
collider: Collider::cuboid(0.5, 0.5),
|
|
||||||
rigid_body: RigidBody::Fixed,
|
|
||||||
active_collision_types: ActiveCollisionTypes::default()
|
|
||||||
| ActiveCollisionTypes::KINEMATIC_STATIC
|
|
||||||
| ActiveCollisionTypes::DYNAMIC_STATIC,
|
|
||||||
map_obstruction: MapObstruction,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TileBundle {
|
|
||||||
pub fn new(x: i32, y: i32) -> Self {
|
|
||||||
Self {
|
|
||||||
transform: Transform::from_xyz(x as f32 + 0.5, y as f32 + 0.5, 0.).into(),
|
|
||||||
..default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Bundle, Clone, Debug)]
|
|
||||||
pub struct ZoneBundle {
|
|
||||||
pub collider: Collider,
|
|
||||||
pub transform: TransformBundle,
|
|
||||||
pub area: Area,
|
|
||||||
pub zone: Zone,
|
|
||||||
pub sensor: Sensor,
|
|
||||||
pub active_events: ActiveEvents,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ZoneBundle {
|
|
||||||
fn new(collider: Collider, position: (f32, f32)) -> Self {
|
|
||||||
let point = Isometry2::new(Vector2::new(position.0, position.1), 0.);
|
|
||||||
let aabb = collider.raw.compute_aabb(&point);
|
|
||||||
Self {
|
|
||||||
collider,
|
|
||||||
area: Area(aabb),
|
|
||||||
transform: Transform::from_translation(Vec3::new(position.0, position.1, 0.)).into(),
|
|
||||||
zone: default(),
|
|
||||||
sensor: default(),
|
|
||||||
active_events: ActiveEvents::COLLISION_EVENTS,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&MRect> for ZoneBundle {
|
|
||||||
fn from(rect: &MRect) -> Self {
|
|
||||||
let collider = Collider::cuboid(
|
|
||||||
rect.width() as f32 / 2. + 0.5,
|
|
||||||
rect.height() as f32 / 2. + 0.5,
|
|
||||||
);
|
|
||||||
let position = (rect.center().x(), rect.center().y());
|
|
||||||
Self::new(collider, position)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GridBuilder {
|
pub struct GridBuilder {
|
||||||
|
@ -191,13 +125,14 @@ impl<D: Clone + Default> MapFilter<D> for GridBuilder {
|
||||||
if let Ok(maze) =
|
if let Ok(maze) =
|
||||||
generator.generate(self.width_in_rooms as i32, self.height_in_rooms as i32)
|
generator.generate(self.width_in_rooms as i32, self.height_in_rooms as i32)
|
||||||
{
|
{
|
||||||
let total_height = self.room_height * self.height_in_rooms + self.height_in_rooms + 1;
|
let total_height = (self.room_height + 1) * self.height_in_rooms + 1;
|
||||||
let half_width = self.room_width / 2;
|
let half_width = self.room_width / 2;
|
||||||
let half_height = self.room_height / 2;
|
let half_height = self.room_height / 2;
|
||||||
for y in 0..self.height_in_rooms {
|
for y in 0..self.height_in_rooms {
|
||||||
for x in 0..self.width_in_rooms {
|
for x in 0..self.width_in_rooms {
|
||||||
let x_offset = x * (self.room_width + 1);
|
let x_offset = x * (self.room_width + 1);
|
||||||
let y_offset = total_height - (y + 1) * (self.room_height + 1) - 1;
|
let y_offset =
|
||||||
|
total_height - (y * (self.room_height + 1)) - self.room_height - 2;
|
||||||
let room = MRect::new_i32(
|
let room = MRect::new_i32(
|
||||||
x_offset as i32 + 1,
|
x_offset as i32 + 1,
|
||||||
y_offset as i32 + 1,
|
y_offset as i32 + 1,
|
||||||
|
@ -255,7 +190,21 @@ fn spawn_colliders<D: 'static + Clone + Default + Send + Sync>(
|
||||||
for x in 0..map.width {
|
for x in 0..map.width {
|
||||||
if let Some(tile) = map.at(x, y) {
|
if let Some(tile) = map.at(x, y) {
|
||||||
if tile.blocks_motion() {
|
if tile.blocks_motion() {
|
||||||
let id = commands.spawn(TileBundle::new(x as i32, y as i32)).id();
|
let id = commands
|
||||||
|
.spawn((
|
||||||
|
RigidBody::Fixed,
|
||||||
|
TransformBundle::from_transform(Transform::from_xyz(
|
||||||
|
x as f32 + 0.5,
|
||||||
|
y as f32 + 0.5,
|
||||||
|
0.,
|
||||||
|
)),
|
||||||
|
Collider::cuboid(0.5, 0.5),
|
||||||
|
ActiveCollisionTypes::default()
|
||||||
|
| ActiveCollisionTypes::KINEMATIC_STATIC
|
||||||
|
| ActiveCollisionTypes::DYNAMIC_STATIC,
|
||||||
|
MapObstruction,
|
||||||
|
))
|
||||||
|
.id();
|
||||||
if tile.blocks_visibility() {
|
if tile.blocks_visibility() {
|
||||||
commands.entity(id).insert(Visible::opaque());
|
commands.entity(id).insert(Visible::opaque());
|
||||||
}
|
}
|
||||||
|
@ -265,8 +214,26 @@ fn spawn_colliders<D: 'static + Clone + Default + Send + Sync>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for room in &map.rooms {
|
for room in &map.rooms {
|
||||||
|
let shape = Collider::cuboid(
|
||||||
|
(room.width() / 2) as f32 + 0.5,
|
||||||
|
(room.height() / 2) as f32 + 0.5,
|
||||||
|
);
|
||||||
|
let position =
|
||||||
|
Isometry2::new(Vector2::new(room.center().x(), room.center().y()), 0.);
|
||||||
|
let aabb = shape.raw.compute_aabb(&position);
|
||||||
commands.entity(map_entity).with_children(|parent| {
|
commands.entity(map_entity).with_children(|parent| {
|
||||||
parent.spawn(ZoneBundle::from(room));
|
parent.spawn((
|
||||||
|
TransformBundle::from_transform(Transform::from_xyz(
|
||||||
|
position.translation.x,
|
||||||
|
position.translation.y,
|
||||||
|
0.,
|
||||||
|
)),
|
||||||
|
shape,
|
||||||
|
Sensor,
|
||||||
|
ActiveEvents::COLLISION_EVENTS,
|
||||||
|
Area(aabb),
|
||||||
|
Zone,
|
||||||
|
));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,19 +248,21 @@ fn spawn_portals<D: 'static + Clone + Default + Send + Sync>(
|
||||||
if **spawn_portals {
|
if **spawn_portals {
|
||||||
commands.entity(map_entity).remove::<SpawnPortals>();
|
commands.entity(map_entity).remove::<SpawnPortals>();
|
||||||
let mut portals: Vec<(f32, f32)> = vec![];
|
let mut portals: Vec<(f32, f32)> = vec![];
|
||||||
for x in 0..map.width {
|
for x in 1..map.width {
|
||||||
for y in 0..map.height {
|
for y in 1..map.height {
|
||||||
let idx = (x, y).to_index(map.width);
|
|
||||||
let mut spawn_portal = false;
|
let mut spawn_portal = false;
|
||||||
if map.get_available_exits(x, y).len() > 2 && map.tiles[idx].is_walkable() {
|
if map.get_available_exits(x, y).len() > 2 {
|
||||||
if (x > 1 && map.tiles[idx - 1].is_walkable())
|
let idx = (x, y).to_index(map.width);
|
||||||
|
if map.tiles[idx].is_walkable()
|
||||||
|
&& (x > 1 && map.tiles[idx - 1].is_walkable())
|
||||||
&& (x < map.width - 2 && map.tiles[idx + 1].is_walkable())
|
&& (x < map.width - 2 && map.tiles[idx + 1].is_walkable())
|
||||||
&& (y > 1 && map.tiles[idx - map.width].is_blocked())
|
&& (y > 1 && map.tiles[idx - map.width].is_blocked())
|
||||||
&& (y < map.height - 2 && map.tiles[idx + map.width].is_blocked())
|
&& (y < map.height - 2 && map.tiles[idx + map.width].is_blocked())
|
||||||
{
|
{
|
||||||
spawn_portal = true;
|
spawn_portal = true;
|
||||||
}
|
}
|
||||||
if (x > 1 && map.tiles[idx - 1].is_blocked())
|
if map.tiles[idx].is_walkable()
|
||||||
|
&& (x > 1 && map.tiles[idx - 1].is_blocked())
|
||||||
&& (x < map.width - 2 && map.tiles[idx + 1].is_blocked())
|
&& (x < map.width - 2 && map.tiles[idx + 1].is_blocked())
|
||||||
&& (y > 1 && map.tiles[idx - map.width].is_walkable())
|
&& (y > 1 && map.tiles[idx - map.width].is_walkable())
|
||||||
&& (y < map.height - 2 && map.tiles[idx + map.width].is_walkable())
|
&& (y < map.height - 2 && map.tiles[idx + map.width].is_walkable())
|
||||||
|
@ -313,7 +282,7 @@ fn spawn_portals<D: 'static + Clone + Default + Send + Sync>(
|
||||||
for (x, y) in portals {
|
for (x, y) in portals {
|
||||||
commands.entity(map_entity).with_children(|parent| {
|
commands.entity(map_entity).with_children(|parent| {
|
||||||
parent.spawn(PortalBundle {
|
parent.spawn(PortalBundle {
|
||||||
transform: Transform::from_translation(Vec3::new(x, y, 0.)).into(),
|
transform: Transform::from_translation(Vec3::new(x, y, 0.)),
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -237,10 +237,8 @@ fn controls(
|
||||||
transform.yaw().radians(),
|
transform.yaw().radians(),
|
||||||
vel,
|
vel,
|
||||||
collider,
|
collider,
|
||||||
ShapeCastOptions {
|
1.,
|
||||||
max_time_of_impact: 1.,
|
true,
|
||||||
..default()
|
|
||||||
},
|
|
||||||
QueryFilter::new()
|
QueryFilter::new()
|
||||||
.exclude_sensors()
|
.exclude_sensors()
|
||||||
.exclude_collider(entity),
|
.exclude_collider(entity),
|
||||||
|
|
|
@ -312,10 +312,8 @@ fn negotiate_path(
|
||||||
transform.yaw().radians(),
|
transform.yaw().radians(),
|
||||||
direction,
|
direction,
|
||||||
collider,
|
collider,
|
||||||
ShapeCastOptions {
|
1.,
|
||||||
max_time_of_impact: 1.,
|
true,
|
||||||
..default()
|
|
||||||
},
|
|
||||||
QueryFilter::new()
|
QueryFilter::new()
|
||||||
.exclude_sensors()
|
.exclude_sensors()
|
||||||
.exclude_collider(entity),
|
.exclude_collider(entity),
|
||||||
|
@ -406,7 +404,7 @@ impl Plugin for PathfindingPlugin {
|
||||||
.register_type::<Path>()
|
.register_type::<Path>()
|
||||||
.register_type::<CostMap>()
|
.register_type::<CostMap>()
|
||||||
.add_systems(
|
.add_systems(
|
||||||
FixedPreUpdate,
|
PreUpdate,
|
||||||
(poll_tasks, apply_deferred, negotiate_path).chain(),
|
(poll_tasks, apply_deferred, negotiate_path).chain(),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
|
@ -415,6 +413,6 @@ impl Plugin for PathfindingPlugin {
|
||||||
.chain()
|
.chain()
|
||||||
.after(InputManagerSystem::Tick),
|
.after(InputManagerSystem::Tick),
|
||||||
)
|
)
|
||||||
.add_systems(FixedPostUpdate, remove_destination);
|
.add_systems(PostUpdate, remove_destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ fn tag_behind(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let v = transform.translation() - listener_transform.translation();
|
let v = transform.translation() - listener_transform.translation();
|
||||||
let dot = v.dot(*listener_forward);
|
let dot = v.dot(listener_forward);
|
||||||
let is_behind = dot <= 0.;
|
let is_behind = dot <= 0.;
|
||||||
if is_behind {
|
if is_behind {
|
||||||
commands.entity(entity).insert(Behind);
|
commands.entity(entity).insert(Behind);
|
||||||
|
|
|
@ -430,13 +430,13 @@ impl<MapData: 'static + Clone + Default + Send + Sync> Plugin for VisibilityPlug
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_event::<VisibilityChanged>()
|
app.add_event::<VisibilityChanged>()
|
||||||
.add_systems(
|
.add_systems(
|
||||||
FixedPreUpdate,
|
PreUpdate,
|
||||||
(
|
(
|
||||||
add_visibility_indices::<MapData>,
|
add_visibility_indices::<MapData>,
|
||||||
update_viewshed,
|
update_viewshed,
|
||||||
update_revealed_tiles::<MapData>,
|
update_revealed_tiles::<MapData>,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_systems(FixedPostUpdate, (log_visible, viewshed_removed, remove_visible));
|
.add_systems(PostUpdate, (log_visible, viewshed_removed, remove_visible));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user