Using Rectangle Intersect and Normalized direction

I have two Rectangles. Lets call them playerRect and enemyRect.
When the playerRect center intersect with enemyRect center at high speed it starts do vibrate.

I have a theory that when playerRect center are close to enemyRect center it adds the normalize number and passes the center, and when it changes it normalize value it goes beyond the center again… and so it continue back and forth.

Could this be a correct theory?

Are there any other way I can have two rectangles intersect when they hit eachother in the middel, and NOT vibrate?
As i said, it works whe they collide at low speed, but not at higher speed.

This is my code:

public void NormalizePlayerToEnemyPosition()
        {
            if (playerPosition != enemyPosition)
            {
                playerToEnemyDifference = enemyPosition - playerPosition;
                playerToEnemyDifference.Normalize();
            }
            if (PlayerCenter().Intersects(EnemyCenter()))
            {
                playerToEnemyDifference = new Vector2(0, 0);
            }
            
        }

        public Rectangle PlayerCenter()
        {
            return new Rectangle((int)playerRectangle.Center.X, (int)playerRectangle.Center.Y, playerTexture.Width / 8, playerTexture.Height / 8);
        }

        public Rectangle EnemyCenter()
        {

            return new Rectangle((int)enemyRectangle.Center.X, (int)enemyRectangle.Center.Y, enemyTexture.Width / 8, enemyTexture.Height / 8);
        }

I’m not sure what you are trying to do here. If the rectangles don’t intersect, you are calculating the normalized vector (vector with a length of one) between the player and the enemy, but if the rectangles do intersect, you are setting the vector to 0, 0 (vector with a length of zero).

What are you doing with the playerToEnemyDifference vector after calling this method? If it is rotating an object to face the direction, it will most likely not work well with a zero length direction vector because it has no direction or infinite directions, depending on how you think about it.

What i want to do is following:

  1. I want the intersection between them not to be around the rectangle sides, but in the middel of both rectangle.
  2. When the two rectangles meets in the middel i want them to intersect and stay there, the problem i have now is if they intersects at high speed, they starts vibrating.

playerRectangle follows playerRectangle. I can myself control playerRectangle with my keyboard.

We just don’t have enough information to determine what might be wrong. We can’t see how you’re moving the rectangle. We can’t see how the playerToEnemyDifference vector is used in that position calculation.

The vibrating around the centre of the other rectangle is most likely due to the movement during one frame being bigger than the distance between the centres of the two rectangles. You move the rectangle by the amount for that frame, which overshoots the centre of the other rectangle. I’m assuming you are moving the rectangle towards the centre of the other rectangle. Because it overshot during the last frame, it suddenly has to turn 180 degrees, but since the speed is the same it overshoots again in the other direction. This continues until the player stops moving. What you should do in this case is check the movement distance for that frame to the distance between the rectangle centres. If the distance between the centres is less than the movement distance, use the distance between centres as the movement distance. This means it won’t overshoot.

Hmmm ill give it a try.

But how is the possible to make the intersection in the middle of the rectangle and not on the sides?

Noone knows how I can get the center of rectangle as intersect bounds?

Your movement step is bigger than your rectangle size. You could use Ray.Intersects(BoundingBox), where the ray is from the previous frame’s position to the current frame’s position, and assume zero for the Z of the ray and -1 to 1 for the min and max Z of the bounding box.

var playerMoveDirection = currentPlayerPosition - previousPlayerPosition;
var playerMoveDistance = playerMoveDirection.Length();
playerMoveDirection.Normalize();
var ray = new Ray(new Vector3(previousPlayerPosition.X, previousPlayerPosition.Y, 0.0f, new Vector3(playerMoveDirection.X, playerMoveDirection.Y, 0.0f));
var enemyCenter = EnemyCenter();
var result = ray.Intersects(new BoundingBox(new Vector3(enemyCenter.Left, enemyCenter.Top, -1.0f), new Vector3(enemyCenter.Right, enemyCenter.Bottom, 1.0f)));
if (result.HasValue && result.Value < playerMoveDistance)
{
    // It collided somewhere along the line between the previous frame and this frame
}

Hey, your code works great. BUT if the enemy attacks from a direction not vertical or horizontal, but sidelong it starts to vibrate.

So when the enemy move vertical or horizontal the “enemyToPlayerMoveDirection” X/Y is either 0 or 1. Then it works great. But as soon as X/Y turns 0.XXX the " var enemyToPlayerRayDistanceResult = enemyToPlayerRay.Intersects(player.TextureBoundingBox);" starts returning “null”

What can I do to fix this?

enemyToPlayerMoveDirection = enemyCurrentPosition - enemyPreviousPosition;

            Ray enemyToPlayerRay = new Ray(new Vector3(enemy.TextureBoundingBox.Min.X, enemy.TextureBoundingBox.Min.Y, 0.0F), new Vector3(enemyToPlayerMoveDirection.X, enemyToPlayerMoveDirection.Y, 0.0F));

            var enemyToPlayerRayDistanceResult = enemyToPlayerRay.Intersects(player.TextureBoundingBox);

            //Enemy previous position
            enemyPreviousPosition = enemy.position;

            enemy.position += enemyToPlayerNormalized;

            if(enemyToPlayerRayDistanceResult.HasValue && enemyToPlayerRayDistanceResult.Value < 1)
            {
                enemy.position = player.position;
                enemyPreviousPosition = enemy.position;
            }

You probably need to normalize the direction so it has a length of one before creating the ray.

enemyToPlayerMoveDirection = enemyCurrentPosition - enemyPreviousPosition;
enemyToPlayerMoveDirection.Normalize();

Yes ive done that, but when going sideways the "enemyToPlayerMoveDirection " X is 0.82424 and Y is -0.5632. These numbers vary after the direction ofc. But it seems that it wont handle X and Y numbers which is less or more than 0 and 1.

Got a new idea Kota? :slight_smile:

I’m out of ideas at the moment. If it is bouncing either side of the target, then it means you are still overshooting the target in one frame.

Well, not exactly. It works when it goes horizontal and vertical, then the “enemyToPlayerRayDistanceResult” gives me a result. But if the enemy goes sideways, it returns null. So as I said, when it X or Y is 0 or 1 its ok, but as soon as it goes to decimal example 0.5235 it stops working. It just wont return anything.

Fixed it, my ray was firing at and from the corners of the boxes, so the ray missed it. Works great now :smiley: