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,
|
Right,
|
||||||
Top,
|
Top,
|
||||||
Bottom,
|
Bottom,
|
||||||
|
Inside,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: ideally we can remove this once bevy gets a physics system
|
// 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
|
// 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
|
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 {
|
} 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 {
|
} else {
|
||||||
(None, 0.0)
|
(Collision::Inside, -f32::INFINITY)
|
||||||
};
|
};
|
||||||
|
|
||||||
// check to see if we hit on the top or bottom side
|
// 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
|
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 {
|
} 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 {
|
} else {
|
||||||
(None, 0.0)
|
(Collision::Inside, -f32::INFINITY)
|
||||||
};
|
};
|
||||||
|
|
||||||
// if we had an "x" and a "y" collision, pick the "primary" side using penetration depth
|
// if we had an "x" and a "y" collision, pick the "primary" side using penetration depth
|
||||||
match (x_collision, y_collision) {
|
if y_depth.abs() < x_depth.abs() {
|
||||||
(Some(x_collision), Some(y_collision)) => {
|
Some(y_collision)
|
||||||
if y_depth.abs() < x_depth.abs() {
|
} else {
|
||||||
Some(y_collision)
|
Some(x_collision)
|
||||||
} else {
|
|
||||||
Some(x_collision)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(Some(x_collision), None) => Some(x_collision),
|
|
||||||
(None, Some(y_collision)) => Some(y_collision),
|
|
||||||
(None, None) => None,
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|||||||
@ -288,6 +288,7 @@ fn ball_collision_system(
|
|||||||
Collision::Right => reflect_x = velocity.x < 0.0,
|
Collision::Right => reflect_x = velocity.x < 0.0,
|
||||||
Collision::Top => reflect_y = velocity.y < 0.0,
|
Collision::Top => reflect_y = velocity.y < 0.0,
|
||||||
Collision::Bottom => 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
|
// reflect velocity on the x-axis if we hit something on the x-axis
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user