Search code examples
javascriptcollision-detectiongame-physics

Find the closest brick to the ball in a bricks breaking game


I am building a JavaScript bricks breaking game from scratch for fun. A demo can be played here. However, you will see that all collisions are not handled.

In an attempt to handle collisions by direct computation (rather than iterate over the whole array of bricks), I need to find the closest brick to my ball at each tick, so I can compare its bounds and those of my ball and find if there was a collision.

I have a 2D bricksArray and I am doing this to find the closest brick:

var col = Math.floor((_ballX + _ballDirX * Breakoid.BALL_SIZE) / (_brickWidth + Breakoid.EMPTY_SPACE))
var row = Math.floor((_ballY + _ballDirY * Breakoid.BALL_SIZE) / (Breakoid.BRICK_HEIGHT + Breakoid.EMPTY_SPACE))

I suggest you to see the code in its context to understand clearly what I am trying to do. (I committed my trials and debug stuff for you to see and maybe understand better than me my problem. The mess is happening between lines 208 and 246).

Actually, those two Math.floor are very strange (because I am not using them right). It usually find values 1 up or 1 down than the actual closest brick, and this is resulting in things like bricksArray[1][-1] wich of course doesn't exists and throw an error. Or bricksArray[1][2] when the closest brick is actually [1][1], and that's not very nice of them because I get mad.

So, how can I find the closest brick to my ball? (hoping it's the best way to do)

Also: my ball is currently moving in only 4 directions since _ballDirX and _ballDirY can only take 1 or -1. I am aware of the trigonometrical circle stuff but then I am wondering if collisions will still be "that simple"...


Solution

  • You need to check the values of row and col for each direction of ball. This way you can determine in what brick the ball will collide based on its direction.

    // Bricks collision stuff
    if (topBall <= Breakoid.NBROWS * (Breakoid.BRICK_HEIGHT + Breakoid.EMPTY_SPACE) {               
    
        // find the closest brick based on direction of ball
        if(_ballDirX==1 && _ballDirY==1) {
            var col = Math.floor((rightBall + _brickWidth) / (_brickWidth + Breakoid.EMPTY_SPACE))-1
            var row = Math.floor((bottomBall) / (Breakoid.BRICK_HEIGHT + Breakoid.EMPTY_SPACE))
        }
        else if(_ballDirX==1 && _ballDirY==-1) {
            var col = Math.floor((rightBall + _brickWidth) / (_brickWidth + Breakoid.EMPTY_SPACE)) -1
            var row = Math.floor((topBall + Breakoid.BRICK_HEIGHT) / (Breakoid.BRICK_HEIGHT + Breakoid.EMPTY_SPACE)) - 1
        }
        else if(_ballDirX==-1 && _ballDirY==1) {
            var col = Math.floor((leftBall + _brickWidth) / (_brickWidth + Breakoid.EMPTY_SPACE))-1 
            var row = Math.floor((bottomBall) / (Breakoid.BRICK_HEIGHT + Breakoid.EMPTY_SPACE))
        }
        else if(_ballDirX==-1 && _ballDirY==-1) {
            var col = Math.floor((leftBall + _brickWidth) / (_brickWidth + Breakoid.EMPTY_SPACE))-1
            var row = Math.floor((topBall + Breakoid.BRICK_HEIGHT) / (Breakoid.BRICK_HEIGHT + Breakoid.EMPTY_SPACE)) - 1
        }
    
        // avoid wrong values of row and col
        // when the player is over the game borders.    
        try{
            var brick = _bricksArray[row][col]
    
            // check for collision
            if (_bricksArray[row][col].present) {
                if (topBall == brick.bottomBorder) {
                    console.log("top hit")
                    _ballDirY = 1
                    _bricksArray[row][col].present = false
                } else if (rightBall == brick.leftBorder) {
                    console.log("right hit")
                    _ballDirX = -1
                    _bricksArray[row][col].present = false
                } else if (bottomBall == brick.topBorder) {
                    console.log("bottom hit")
                    _ballDirY = -1
                    _bricksArray[row][col].present = false
                } else if (leftBall == brick.rightBorder) {
                    console.log("left hit")
                    _ballDirX = 1
                    _bricksArray[row][col].present = false
                }
            }
    
        }catch(e){
            // console.log("row: " + row + " col: " + col)
        }   
    }
    

    Maybe you will find some issues in this code because it was not fully tested. Nevertheless hope you get the idea.

    I highly recommend this "breakout" tutorial from Jake Gordon:
    http://codeincomplete.com/posts/2011/6/11/javascript_breakout/

    It covers the full implementation of a "breakout" game using html5 canvas.

    He treats collisions as well as its issues in this especific article: http://codeincomplete.com/posts/2011/6/12/collision_detection_in_breakout/

    The articles cited above might not suit your needs but you can have good insights about how to implement several features in your game.