Skip to content

Commit 37243b3

Browse files
committed
Refactor obstacle detection code
1 parent c9e43a5 commit 37243b3

3 files changed

Lines changed: 43 additions & 50 deletions

File tree

src/level.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub struct Level {
1212
pub star_thresholds: Vec<u32>,
1313
}
1414

15-
#[derive(Deserialize, Debug)]
15+
#[derive(Deserialize, Debug, Clone, Component)]
1616
pub enum Obstacle {
1717
Rect(Vec2, Vec2),
1818
}

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,7 @@ fn spawn_obstacle(commands: &mut Commands, obstacle: &Obstacle) {
877877
.build(),
878878
Transform::from_translation(origin.extend(layer::OBSTACLE)),
879879
StateScoped(GameState::Playing),
880+
obstacle.clone(),
880881
))
881882
.with_children(|parent| {
882883
parent.spawn((

src/road_drawing.rs

Lines changed: 41 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use petgraph::{
88
use crate::{
99
collision::{point_segment_collision, segment_collision, PointCollision, SegmentCollision},
1010
layer,
11+
level::Obstacle,
1112
lines::{possible_lines, Axis},
1213
sim::SimulationState,
1314
spawn_road_segment, theme, Collider, ColliderLayer, DrawingInteraction, DrawingMouseMovement,
@@ -344,6 +345,7 @@ fn not_drawing_mouse_movement_system(
344345
selected_tool: Res<SelectedTool>,
345346
mouse_snapped: Res<MouseSnappedPos>,
346347
q_colliders: Query<(&ChildOf, &Collider, &ColliderLayer)>,
348+
q_obstacles: Query<(), With<Obstacle>>,
347349
) {
348350
if !matches!(selected_tool.0, Tool::LineDrawing) {
349351
return;
@@ -359,12 +361,11 @@ fn not_drawing_mouse_movement_system(
359361

360362
let bad = q_colliders
361363
.iter()
362-
.any(|(_parent, collider, layer)| match collider {
364+
.any(|(child_of, collider, _layer)| match collider {
363365
Collider::Segment(segment) => {
364366
match point_segment_collision(mouse_snapped.0, segment.0, segment.1) {
365367
PointCollision::None => false,
366-
// TODO (I think) this is a hack to check if the collider is an obstacle
367-
_ => layer.0 == 0,
368+
_ => q_obstacles.get(child_of.parent()).is_ok(),
368369
}
369370
}
370371
_ => false,
@@ -382,6 +383,7 @@ fn drawing_mouse_movement_system(
382383
sim_state: Res<SimulationState>,
383384
mouse_snapped: Res<MouseSnappedPos>,
384385
q_colliders: Query<(&ChildOf, &Collider, &ColliderLayer)>,
386+
q_obstacles: Query<(), With<Obstacle>>,
385387
) {
386388
if !road_state.drawing {
387389
return;
@@ -448,27 +450,37 @@ fn drawing_mouse_movement_system(
448450
Collider::Segment(s) => {
449451
let collision = segment_collision(s.0, s.1, *a, *b);
450452

453+
// If there's no collision, there's no problem.
454+
if matches!(collision, SegmentCollision::None) {
455+
continue;
456+
};
457+
458+
let parent = child_of.parent();
459+
let is_obstacle = q_obstacles.get(parent).is_ok();
460+
if is_obstacle {
461+
ok = false;
462+
break;
463+
}
464+
451465
match collision {
466+
// This variant is covered above.
467+
SegmentCollision::None => {}
468+
// We are allowed to cross over road segments on other layers,
469+
// but not obstacles.
452470
SegmentCollision::Intersecting => {
453-
if layer.0 == road_state.layer || layer.0 == 0 {
471+
if layer.0 == road_state.layer {
454472
ok = false;
455473
break;
456474
}
457475
}
476+
// Overlapping a road segment is never okay.
458477
SegmentCollision::Overlapping => {
459478
ok = false;
460479
break;
461480
}
481+
// "Touching" collisions are allowed only if they are the
482+
// start or end of the line we are currently drawing.
462483
SegmentCollision::Touching(intersection_point) => {
463-
// "Touching" collisions are allowed only if they are the
464-
// start or end of the line we are currently drawing.
465-
466-
// TODO (I think) this is a hack to check if the collider is an obstacle
467-
if layer.0 == 0 {
468-
ok = false;
469-
break;
470-
}
471-
472484
let start_touching = intersection_point == road_state.start;
473485
let end_touching = intersection_point == road_state.end;
474486

@@ -500,29 +512,18 @@ fn drawing_mouse_movement_system(
500512
}
501513

502514
if start_touching {
503-
connections
504-
.0
505-
.push(SegmentConnection::Split(child_of.parent()));
515+
connections.0.push(SegmentConnection::Split(parent));
506516
split_layers.0.insert(layer.0);
507517
}
508518
if end_touching {
509-
connections
510-
.1
511-
.push(SegmentConnection::Split(child_of.parent()));
519+
connections.1.push(SegmentConnection::Split(parent));
512520
split_layers.1.insert(layer.0);
513521
}
514522
}
523+
// "Connecting" collisions are allowed only if they are the
524+
// start or end of the line we are currently drawing.
515525
SegmentCollision::Connecting(intersection_point)
516526
| SegmentCollision::ConnectingParallel(intersection_point) => {
517-
// "Connecting" collisions are allowed only if they are the
518-
// start or end of the line we are currently drawing.
519-
520-
// TODO (I think) this is a hack to check if the collider is an obstacle
521-
if layer.0 == 0 {
522-
ok = false;
523-
break;
524-
}
525-
526527
let start_touching = intersection_point == road_state.start;
527528
let end_touching = intersection_point == road_state.end;
528529

@@ -537,13 +538,9 @@ fn drawing_mouse_movement_system(
537538
if matches!(collision, SegmentCollision::ConnectingParallel(_))
538539
&& layer.0 == road_state.layer
539540
{
540-
connections
541-
.0
542-
.push(SegmentConnection::TryExtend(child_of.parent()));
541+
connections.0.push(SegmentConnection::TryExtend(parent));
543542
} else {
544-
connections
545-
.0
546-
.push(SegmentConnection::Add(child_of.parent()));
543+
connections.0.push(SegmentConnection::Add(parent));
547544
}
548545
}
549546
if (road_state.start == *b && start_touching)
@@ -552,23 +549,18 @@ fn drawing_mouse_movement_system(
552549
if matches!(collision, SegmentCollision::ConnectingParallel(_))
553550
&& layer.0 == road_state.layer
554551
{
555-
connections
556-
.1
557-
.push(SegmentConnection::TryExtend(child_of.parent()));
552+
connections.1.push(SegmentConnection::TryExtend(parent));
558553
} else {
559-
connections
560-
.1
561-
.push(SegmentConnection::Add(child_of.parent()));
554+
connections.1.push(SegmentConnection::Add(parent));
562555
}
563556
}
564557
}
565-
SegmentCollision::None => {}
566558
}
567559
}
560+
// The only point colliders that exist right now are for termini
568561
Collider::Point(p) => match point_segment_collision(*p, *a, *b) {
562+
// Don't allow the midpoint of the line to connect to a terminus.
569563
PointCollision::Middle => {
570-
// don't allow the midpoint of the line to connect to a
571-
// terminus
572564
ok = false;
573565
break;
574566
}
@@ -578,19 +570,19 @@ fn drawing_mouse_movement_system(
578570
break;
579571
}
580572

573+
// Exit drawing mode if the player is connecting a road to a
574+
// terminus.
581575
if *p == road_state.end {
582576
stop = true;
583577
}
584578

579+
let parent = child_of.parent();
580+
585581
if *a == *p {
586-
connections
587-
.0
588-
.push(SegmentConnection::Add(child_of.parent()));
582+
connections.0.push(SegmentConnection::Add(parent));
589583
}
590584
if *b == *p {
591-
connections
592-
.1
593-
.push(SegmentConnection::Add(child_of.parent()));
585+
connections.1.push(SegmentConnection::Add(parent));
594586
}
595587
}
596588
PointCollision::None => {}

0 commit comments

Comments
 (0)