Add the Inside version to the Collision enum (#2489)
# Objective I think the 'collide' function inside the 'bevy/crates/bevy_sprite/src/collide_aabb.rs' file should return 'Some' if the two rectangles are fully overlapping or one is inside the other. This can happen on low-end machines when a lot of time passes between two frames because of a stutter, so a bullet for example gets inside its target. I can also think of situations where this is a valid use case even without stutters. ## Solution I added an 'Inside' version to the Collision enum declared in the file. And I use it, when the two rectangles are overlapping, but we can't say from which direction it happened. I gave a 'penetration depth' of minus Infinity to these cases, so that this variant only appears, when the two rectangles overlap from each side fully. I am not sure if this is the right thing to do. Fixes #1980 Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
parent
4134577e64
commit
c285a69f76
@ -8,6 +8,7 @@ pub enum Collision {
|
||||
Right,
|
||||
Top,
|
||||
Bottom,
|
||||
Inside,
|
||||
}
|
||||
|
||||
// TODO: ideally we can remove this once bevy gets a physics system
|
||||
@ -27,35 +28,28 @@ pub fn collide(a_pos: Vec3, a_size: Vec2, b_pos: Vec3, b_size: Vec2) -> Option<C
|
||||
// check to see if we hit on the left or right side
|
||||
let (x_collision, x_depth) = if a_min.x < b_min.x && a_max.x > b_min.x && a_max.x < b_max.x
|
||||
{
|
||||
(Some(Collision::Left), b_min.x - a_max.x)
|
||||
(Collision::Left, b_min.x - a_max.x)
|
||||
} else if a_min.x > b_min.x && a_min.x < b_max.x && a_max.x > b_max.x {
|
||||
(Some(Collision::Right), a_min.x - b_max.x)
|
||||
(Collision::Right, a_min.x - b_max.x)
|
||||
} else {
|
||||
(None, 0.0)
|
||||
(Collision::Inside, -f32::INFINITY)
|
||||
};
|
||||
|
||||
// check to see if we hit on the top or bottom side
|
||||
let (y_collision, y_depth) = if a_min.y < b_min.y && a_max.y > b_min.y && a_max.y < b_max.y
|
||||
{
|
||||
(Some(Collision::Bottom), b_min.y - a_max.y)
|
||||
(Collision::Bottom, b_min.y - a_max.y)
|
||||
} else if a_min.y > b_min.y && a_min.y < b_max.y && a_max.y > b_max.y {
|
||||
(Some(Collision::Top), a_min.y - b_max.y)
|
||||
(Collision::Top, a_min.y - b_max.y)
|
||||
} else {
|
||||
(None, 0.0)
|
||||
(Collision::Inside, -f32::INFINITY)
|
||||
};
|
||||
|
||||
// if we had an "x" and a "y" collision, pick the "primary" side using penetration depth
|
||||
match (x_collision, y_collision) {
|
||||
(Some(x_collision), Some(y_collision)) => {
|
||||
if y_depth.abs() < x_depth.abs() {
|
||||
Some(y_collision)
|
||||
} else {
|
||||
Some(x_collision)
|
||||
}
|
||||
}
|
||||
(Some(x_collision), None) => Some(x_collision),
|
||||
(None, Some(y_collision)) => Some(y_collision),
|
||||
(None, None) => None,
|
||||
if y_depth.abs() < x_depth.abs() {
|
||||
Some(y_collision)
|
||||
} else {
|
||||
Some(x_collision)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
|
||||
@ -288,6 +288,7 @@ fn ball_collision_system(
|
||||
Collision::Right => reflect_x = velocity.x < 0.0,
|
||||
Collision::Top => reflect_y = velocity.y < 0.0,
|
||||
Collision::Bottom => reflect_y = velocity.y > 0.0,
|
||||
Collision::Inside => { /* do nothing */ }
|
||||
}
|
||||
|
||||
// reflect velocity on the x-axis if we hit something on the x-axis
|
||||
|
||||
Loading…
Reference in New Issue
Block a user