HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Breakout game in JavaScript

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
javascriptgamebreakout

Problem

I decided to make a Breakout game in JavaScript. Is there a way of making it cleaner? For instance, creating objects for the ball and the paddle.






Brick Game


body {
background-color: black;
}
canvas {
border: 1px solid green;
}





var canvas = document.getElementById("game-canvas");
// Get a 2D context for the canvas.
var ctx = canvas.getContext("2d");

var ballR = 10;
var x = canvas.width / 2;
var y = canvas.height - 30;
var dx = 3;
var dy = -3;
var pongH = 15;
var pongW = 80;
var pongX = (canvas.width - pongW) / 2;
var rightKey = false;
var leftKey = false;
var brickRows = 3;
var brickCol = 9;
var brickW = 75;
var brickH = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;

var bricks = [];
for (c = 0; c b.x && x b.y && y canvas.width - ballR || x + dx canvas.height - ballR) {
if (x > pongX && x 0) {
pongX -= 7;
}

x += dx;
y += dy;
}

setInterval(draw, 10);


Solution

First, great job. I loved seeing that the whole game had been created with so little code, and was so easy to understand.

While you could consider making this more object-oriented, I don't think it's necessary, so I did some rewrites in keeping with the simple procedural style of the original.

The biggest place for improvement is in naming your concepts. For example, this:

if (hitSideWall())
    dx = -dx;
if (hitTop() || hitPong())
    dy = -dy;
if (gameOver())
  document.location.reload();


is much clearer than:

if (y + dy  canvas.height - ballR) {
  if (x > pongX && x < pongX + pongW) {
    dy = -dy;
  } else {
    document.location.reload();
  }
}


You can apply this principle over and over, at all levels of your code. See the full rewrite for more examples.

Other notes:

  • Avoid nesting wherever possible, and avoid "if... else" statements.



  • The nested for loop for the bricks only needs to be done once. Use it once to create a flat array of bricks. Afterward, the nested structure is superfluous, since each brick object contains the info you need. Just loop through the flat array with forEach.



  • When initializing multiple variables, just use one var and commas.



Full rewrite:


  
  Brick Game
  
    body { background-color: black; }
    canvas { border: 1px solid green; }
  

  

    
      var canvas = document.getElementById("game-canvas"),
          ctx = canvas.getContext("2d"),
          ballR = 10,
          x = canvas.width / 2,
          y = canvas.height - 30,
          dx = 3,
          dy = -3,
          pongH = 15,
          pongW = 80,
          pongX = (canvas.width - pongW) / 2,
          rightKey = false,
          leftKey = false,
          brickRows = 3,
          brickCol = 9,
          brickW = 75,
          brickH = 20,
          brickPadding = 10,
          brickOffsetTop = 30,
          brickOffsetLeft = 30;

      var bricks = [];
      for (c = 0; c  b.x && x  b.y && y  pongX && x  canvas.height - ballR }
        function gameOver() { return hitBottom() && !ballOverPong() }
        function hitSideWall() { return x + dx > canvas.width - ballR || x + dx  canvas.width - ballR || x + dx 

Code Snippets

if (hitSideWall())
    dx = -dx;
if (hitTop() || hitPong())
    dy = -dy;
if (gameOver())
  document.location.reload();
if (y + dy < ballR) {
  dy = -dy;
} else if (y + dy > canvas.height - ballR) {
  if (x > pongX && x < pongX + pongW) {
    dy = -dy;
  } else {
    document.location.reload();
  }
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Brick Game</title>
  <style type="text/css">
    body { background-color: black; }
    canvas { border: 1px solid green; }
  </style>
</head>

<body>

  <canvas id="game-canvas" height="600px" width="800px" </canvas>

    <script type="text/javascript">
      var canvas = document.getElementById("game-canvas"),
          ctx = canvas.getContext("2d"),
          ballR = 10,
          x = canvas.width / 2,
          y = canvas.height - 30,
          dx = 3,
          dy = -3,
          pongH = 15,
          pongW = 80,
          pongX = (canvas.width - pongW) / 2,
          rightKey = false,
          leftKey = false,
          brickRows = 3,
          brickCol = 9,
          brickW = 75,
          brickH = 20,
          brickPadding = 10,
          brickOffsetTop = 30,
          brickOffsetLeft = 30;

      var bricks = [];
      for (c = 0; c < brickCol; c++) {
        for (r = 0; r < brickRows; r++) {
          bricks.push({
            x: (c * (brickW + brickPadding)) + brickOffsetLeft,
            y: (r * (brickH + brickPadding)) + brickOffsetTop,
            status: 1
          });
        }
      }


       // function to draw the ball 
      function drawBall() {
        ctx.beginPath();
        ctx.arc(x, y, ballR, 0, Math.PI * 2);
        ctx.fillStyle = "red";
        ctx.fill();
        ctx.closePath();
      }

       // function draw the pong
      function drawPong() {
        ctx.beginPath();
        ctx.rect(pongX, canvas.height - pongH, pongW, pongH);
        ctx.fillStyle = "blue";
        ctx.fill();
        ctx.closePath();
      }

       // function draw the bricks
      function drawBricks() {
        bricks.forEach(function(brick) {
          if (!brick.status) return;
          ctx.beginPath();
          ctx.rect(brick.x, brick.y, brickW, brickH);
          ctx.fillStyle = "green";
          ctx.fill();
          ctx.closePath();
        });
      }

      function collisionDetection() {
        bricks.forEach(function(b) {
          if (!b.status) return;

          var inBricksColumn = x > b.x && x < b.x + brickW,
              inBricksRow = y > b.y && y < b.y + brickH;

          if (inBricksColumn && inBricksRow) {
            dy = -dy;
            b.status = 0;
          }
        });
      }

      function draw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        drawBricks();
        drawBall();
        drawPong();
        collisionDetection();

        if (hitSideWall())
            dx = -dx;
        if (hitTop() || hitPong())
            dy = -dy;
        if (gameOver())
          document.location.reload();

        var RIGHT_ARROW = 39,
            LEFT_ARROW= 37;

        function hitPong() { return hitBottom() && ballOverPong() }
        function ballOverPong() { return x > pongX && x < pongX + pongW }
        function hitBottom() { return y + dy > canvas.height - ballR }
        function gameOver() { return hitBottom() && !ball

Context

StackExchange Code Review Q#109771, answer score: 4

Revisions (0)

No revisions yet.