Question

I'm a starter in XNA and I'm trying to make a pong-game.
I've been able to make a pong game, but all the code was in one class. So I wanted to try to add a little bit of OOP and I've made a class for the ball and one for the pad.

The ball moves perfectly, but I don't seem to able to make the ball bounce from the pads.

These are the codes I use:
To move the pads
Game1.cs

#region left
    if (_KBS.IsKeyDown(Keys.W) || _KBS.IsKeyDown(Keys.Z))
        Left.MoveUp();
    else if (_KBS.IsKeyDown(Keys.S))
        Left.MoveDown();
#endregion

#region right
    if (_KBS.IsKeyDown(Keys.Up))
        Right.MoveUp();
    else if (_KBS.IsKeyDown(Keys.Down))
        Right.MoveDown();
#endregion

pad.cs

public void MoveUp() {
    if (!paused)
        RecPad.Offset(0, -speed);

    CheckBorders();
}

public void MoveDown() {
    if (!paused)
        RecPad.Offset(0, speed);

    CheckBorders();
}

private void CheckBorders() {
    MathHelper.Clamp(recPad.Y, borders.Top, borders.Bottom - recPad.Height);
}

To check if the ball bounces
ball.cs

public void CheckBounce() {
    if ((myBounds.Intersects(left) && movement.X < 0) || (myBounds.Intersects(right) && movement.X > 0))
            movement.X *= -1;
}

public void Draw(SpriteBatch sBatch, Texture2D texture, Color color, Rectangle left, Rectangle right) {
    this.left = left;
    this.right = right;

    Move();

    sBatch.Begin();
    sBatch.Draw(texture, myBounds, color);
    sBatch.End();
}

pad.cs

public Rectangle RecPad {
    get { return recPad; }
    private set { recPad = value; }
}

Game1.cs

Ball.Draw(spriteBatch, ball, Color.White, Left.RecPad, Right.RecPad);

I seemed to get the pads back to work
The problem seems to be solved by using the originel recPad instead of the constructor RecPad
Now I only need to get my boundries working, because the MathHelper.Clamp doesn't seem to work
See my code for more info

This code now fixed my border-problem

private void CheckBorders() {
        if (recPad.Top < borders.Top)
            recPad.Location = new Point(recPad.X, borders.Top);
        if (recPad.Bottom > borders.Bottom)
            recPad.Location = new Point(recPad.X, borders.Bottom - recPad.Height);
    }
Was it helpful?

Solution

This immediately stands out to me (from CheckBounce):

    movement.X *= 1;

Could be a copying error, or you forgot to put a '-'.

Also, consider using the Rectangle.Contains/Intersects method(s) to streamline some collision code, and MathHelper.Clamp to keep your paddles in bounds. This is more just for future reference, since your methods work, but it's nice to take advantage of the helpful tools in XNA.

Edit: Concerning those 'helpful tools':

The Rectangle class has the methods Intersect and Contains, which can tell you if that rectangle is intersecting another rectangle or containing a certain point, respectively. You say your ball is just a top left position and a texture, but I see in your collision checking you also check for the radius of the ball. I think you'd have an easier time defining a Rectangle bounding area for your ball and using the Intersects method to check for collision. That simplifies your collision code to:

public void CheckBounce()
{
    if (myBounds.Intersects(LeftPaddle.Bounds) || myBounds.Intersects(RightPaddle.Bounds))
        movement.X *= -1;
}

Fairly simple, but not entirely safe-- if the ball manages to move far enough into a paddle that one frame of movement wouldn't free it from that paddle's bounds, you'd be stuck perpetually inverting the X velocity, producing a 'stuck ball' effect. So we can add just a bit more checking code to avoid that:

public void CheckBounce()
{
    if ((myBounds.Intersects(LeftPaddle.Bounds) && movement.X < 0) ||
     (myBounds.Intersects(RightPaddle.Bounds) && movement.X > 0))
        movement.X *= -1;
}

I apologize if the inline conditionals are a little too dense. What this means is, if the ball is moving left and hits the right paddle, invert the X. Likewise, if it's moving right and hits the left paddle, invert the X. This removes the 'sticking'.

Now, as for MathHelper.Clamp, in your situation I would use it to restrict paddle movement. MathHelper.Clamp simply clamps a value between an upper and lower bound. It's the equivalent of using Math.Min, then Math.Max.

private void CheckBorders()
{
    //clamps a       value  to a   min  and a           max
    MathHelper.Clamp(recPad.Y, borders.Top, borders.Bottom - recPad.Height);
}

This clamps the Y position of your rectangle between the top of your borders, and the bottom of your borders minus the height of the rectangle. That last bit keeps the bottom of your rectangle from clipping the bottom of the borders by taking the height into account.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top