Search code examples
c#visual-studiovisual-studio-2013collision-detectionbreakout

Breakout Brick Collision


I really need some help with getting collision detection to work with my bricks in my breakout clone. I've spent hours reading answers all over different websites but most seem to be in other coding languages I'm not that familiar with and not sure how to translate them over.

I've got collision working on the walls, paddle, and ball, I just can't get it to work with the bricks.I'm not sure if you'll need to see all the code from the different classes but here's the bricks, ball, and main form classes. Hopefully I format this right haha. Any help or advice would be appreciated.

Brick Class:

    class BrickTest2
    {
      public int x {get; set;}
      public int y {get; set;}
      public int brWidth { get; set; }
      public int brHeight { get; set; }
      public static int rows = 4;
      public static int columns = 10;

      public Image brickTest2Img;

      List<Rectangle> brick = new List<Rectangle>();

      public Rectangle brickRect2;

      public Rectangle BrickRect2
      {
        get { return brickRect2; }
      }

      public BrickTest2()
      {
        x = 0;
        y = 0;
        brWidth = 32;
        brHeight = 12;

        brickTest2Img = Breakout.Properties.Resources.brickRed;
        brickRect2 = new Rectangle(x, y, brWidth, brHeight);

      }

      public void drawBrickTest2(Graphics paper)
      {

        for (int c = 0; c < columns; c++)
            for (int r = 0; r < rows; r++)
            {
               Rectangle brickRect2 = new Rectangle(x + c * brWidth, y + r * brHeight, brWidth, brHeight);
                brick.Add(brickRect2);

                paper.DrawImage(brickTest2Img, brickRect2);

               switch(r)
                {
                    case 0:
                        brickTest2Img = Breakout.Properties.Resources.brickRed;
                        break;
                    case 1:
                        brickTest2Img = Breakout.Properties.Resources.BrickYellow;
                        break;
                    case 2:
                        brickTest2Img = Breakout.Properties.Resources.BrickGreen;
                        break;
                    case 3:
                        brickTest2Img = Breakout.Properties.Resources.BrickBlue;
                        break;
                   default:
                        break;
                }
            }
     }
   }
 }

Ball Class:

    public class Ball
    {
      public int x, y, width, height;
      public int xSpeed, ySpeed;
      private Random randSpeed;

      private Image ballImage;
      private Rectangle ballRec;

      public Rectangle BallRec
      {
        get { return ballRec; }
      }

      public Ball()
      {
        randSpeed = new Random();
        x = 130;
        y = 130;
        width = 8;
        height = 8;

        xSpeed = randSpeed.Next(5, 7);
        ySpeed = randSpeed.Next(5, 7);

        ballImage = Breakout.Properties.Resources.ball2;

        ballRec = new Rectangle(x, y, width, height);
      }

      public void drawBall(Graphics paper)
      {
        paper.DrawImage(ballImage, ballRec);

      }

      public void moveBall()
      {
        ballRec.X += xSpeed;
        ballRec.Y += ySpeed;
      }

      public void collideWallBall()
      {
        if (ballRec.X < 0 || ballRec.X > 270)
        {
            xSpeed *= -1;
        }

        if (ballRec.Y < 0)
        {
            ySpeed *= -1;
        }

      }

      public void BallDead()
      {
        if (ballRec.Y > 260)
        {
           // ySpeed *= -1; for testing
            Settings.gmOver = true;
        }
      }

      public void collidePaddleBall(Rectangle paddleRec)
      {
        if (paddleRec.IntersectsWith(ballRec))
        {
            ySpeed *= -1;
        }
      }


      public void collideBrickBall(Rectangle brickRec2)
      {
        if (brickRec2.IntersectsWith(ballRec))
        {
            // desperate attempt to get it to work
            if(brickRec2.X == ballRec.X)
            {
                ySpeed *= -1;
            }
        }
      }

   }
 }

Main Form:

public partial class Form1 : Form
{

    // initiallizes class files
    Graphics paper;
    Paddle gmPaddle = new Paddle();
    Ball gmBall = new Ball();
    BrickTest2 gmBrickTest = new BrickTest2();

    public Form1()
    {

        // initializes
        InitializeComponent();
        GameStart();

    }


    private void GameStart()
    {

        // sets up a new game
        new Settings();
        Settings.gmOver = false;
        lblGameOver1.Visible = false;
        lblGameOver2.Visible = false;
        Cursor.Hide();


    }


    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        paper = e.Graphics;

        if (Settings.gmOver == true)
        {
            // once game is over, stops drawing object and brings up game over message
            string gameOver1 = "Game over!";
            string gameOver2 = "Press Enter to try again";
            lblGameOver1.Text = gameOver1;
            lblGameOver2.Text = gameOver2;
            lblGameOver1.Visible = true;
            lblGameOver2.Visible = true;
        }

        if(Settings.gmOver != true)
        {
            // draws objects if game is not over
            gmPaddle.drawPaddle(paper);
            gmBall.drawBall(paper);
            gmBrickTest.drawBrickTest2(paper);

        } 
    }


    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        // calls mouse movement for the paddle
        gmPaddle.movePaddle(e.X);
        this.Invalidate();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        //updates collision
        gmBall.moveBall();
        gmBall.collideWallBall();
        gmBall.collidePaddleBall(gmPaddle.PaddleRec);
        gmBall.BallDead();
        gmBall.collideBrickBall(gmBrickTest.BrickRect2);

        this.Invalidate();
    }



    private void Form1_KeyPress(object sender, KeyPressEventArgs e)
    {
        // restarts game, still needs work
        GameStart();

    }


 }

}

Solution

  • After looking at the code You've posted, I would suggest to verify if You use brickRect2 variable correctly.

    In the class constructor You always assign brickRect2 = new Rectangle(x, y, brWidth, brHeight);, so it's always (0, 0, 32, 12).

    Then, in the drawBrickTest2(Graphics paper) method You don't draw the rectangle directly, but instead, You shift it according to row and column variables: Rectangle brickRect2 = new Rectangle(x + c * brWidth, y + r * brHeight, brWidth, brHeight);, so here You use just a local variable that is named the same as the field in Your class.

    I cannot see the code, where You call collideBrickBall(Rectangle brickRec2) method, but I suppose You may try to use the field from the class, which is always (0, 0, 32, 12).

    If this is the case, tere are several methods You can use to fix this:

    • assign appropriate rectangle coordinates to the brickRect2 field instead of shifting it when drawing
    • don't use IntersectWith(Rectangle rect) method and do the collision comparison manually, considering the coordinates shift