Search code examples
c#xnacollision-detection

XNA - Ball Detect collision wrong after first collision


In my pong game I basically have two paddles, a ball that is set to bounce off all walls / paddles, it used to work fine, but now after the first hit with the paddle, it starts to detect the collision wrong, could you please take a look on this code to see what's wrong:

Ball.cs:

public class Ball
{
    GreenPaddle gPaddle;
    BluePaddle bPaddle;
    public Texture2D ballTexture;
    public Vector2 ballPosition;
    public Rectangle ballRect;
    public float speed = 1f;
    bool movingUp, movingLeft;

    public Ball(GreenPaddle paddle, BluePaddle paddleb)
    {
        this.gPaddle = paddle;
        this.bPaddle = paddleb;
        movingLeft = true;
        movingUp = true;
    }

    public void LoadContent(ContentManager Content)
    {

        ballTexture = Content.Load<Texture2D>("ball");
        ballPosition = new Vector2(380, 225);
        ballRect = new Rectangle((int)ballPosition.X, (int)ballPosition.Y,
            20, 20);

    }

    public void Update(GameTime gameTime)
    {
        BallMovement();
        CollideWithPaddles();
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(ballTexture, ballRect, Color.White);
    }

    public void BallMovement()
    {
        if (movingUp) { ballPosition.Y -= speed; ballRect.Y -= (int)speed; }
        if (!movingUp) { ballPosition.Y += speed; ballRect.Y += (int)speed; }
        if (movingLeft) { ballPosition.X -= speed; ballRect.X -= (int)speed; }
        if (!movingLeft) { ballPosition.X += speed; ballRect.X += (int)speed; }

        if (ballPosition.Y < 83)
        {
            movingUp = false;
        }
        if (ballPosition.Y >= 500)
        {
            movingUp = true;
        }

    }


    public void CollideWithPaddles()
        {

            if (ballRect.Intersects(gPaddle.gpRect))
                movingLeft = false;     
            if (ballRect.Intersects(bPaddle.bpRect))
                movingLeft = true;

        }
    }

And in my Game1.cs i have this part which i might think is causing some problem:

public bool BallHitEffect()
    {
        //Plays an effect/animation when ball hits the paddle
        if (gPaddle.gpRect.Intersects(ball.ballRect) || bPaddle.bpRect.Intersects(ball.ballRect))
        {
            ball.speed += 0.5f;//Makes the ball go faster every paddle-hit.
            return true;
        }
        else { return false; }
    }

And in my Game1.cs Update method i have this for the animation:

//If it is not already playing and there is collision, start playing
        if (!IsPlaying && BallHitEffect())
            IsPlaying = true;
        //Increment the frameTimePlayed by the time (in milliseconds) since the last frame
        if (IsPlaying)
            frameTimePlayed += gameTime.ElapsedGameTime.TotalMilliseconds;
        //If playing and we have not exceeded the time limit
        if (IsPlaying && frameTimePlayed < animationTime)
        {
            animatedSprite.Update(gameTime);
            // And increment your frames (Using division to figure out how many frames per second)
        }
        //If exceeded time, reset variables and stop playing
        else if (IsPlaying && frameTimePlayed >= animationTime)
        {
            frameTimePlayed = 0;
            IsPlaying = false;
            // TODO: Possibly custom animation.Stop(), depending on your animation class
        }

The animation is a 800x400, each image/tile is 200x200.


Solution

  • The problem here is that when the ball collides, you increase the speed by 0.5. However, when you move the hitbox, you round the speed. This means that the hitbox moves by 1 each frame, but the ball by 0.5