Created
October 25, 2012 21:44
-
-
Save jpbyrne/3955627 to your computer and use it in GitHub Desktop.
A simple Breakout clone created using JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Ball(x, y, radius, color) { | |
this.x = x; | |
this.y = y; | |
this.dx = 10; | |
this.dy = 10; | |
this.dxRange = this.dx * 2; | |
this.radius = radius; | |
this.color = color; | |
this.draw = function(context) { | |
context.save(); | |
context.translate(this.x, this.y); | |
context.fillStyle = this.color; | |
context.beginPath(); | |
context.arc(0, 0, this.radius, 0, (Math.PI * 2), true); | |
context.closePath(); | |
context.fill(); | |
context.restore(); | |
} | |
// prevents the ball from leaving the stage | |
// (except via the bottom of the screen) | |
this.bound = function(canvas) { | |
if(this.x - (this.radius / 2) <= 0 || | |
this.x + (this.radius / 2) >= canvas.width) { | |
this.dx = - this.dx; | |
} | |
if(this.y - (this.radius / 2) <= 0) { | |
this.dy = - this.dy; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Brick(x, y, width, height, color) { | |
this.x = x; | |
this.y = y; | |
this.height = height; | |
this.width = width; | |
this.color = color; | |
this.state = true; | |
this.draw = function(context) { | |
context.save(); | |
context.translate(this.x, this.y); | |
context.fillStyle = this.color; | |
context.fillRect (0,0,this.width,this.height); | |
context.restore(); | |
} | |
// detects collision between the brick and ball | |
this.collide = function(ball) { | |
if(this.state == true && | |
ball.x - ball.radius <= this.x + this.width && | |
ball.x + ball.radius >= this.x && | |
ball.y - ball.radius <= this.y + this.height && | |
ball.y + ball.radius >= this.y) { | |
this.state = false; | |
ball.dy = - ball.dy; | |
return true; | |
} | |
else { | |
return false; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html xmlns="http://www.w3.org/1999/xhtml"> | |
<head> | |
<style> | |
#canvas { | |
background-color: #000000; | |
} | |
</style> | |
<script type="text/javascript" src="raf.js"></script> | |
<script type="text/javascript" src="paddle.js"></script> | |
<script type="text/javascript" src="ball.js"></script> | |
<script type="text/javascript" src="brick.js"></script> | |
<script type="text/javascript"> | |
var canvas; | |
var ctx; | |
var paddle; | |
var PADDLE_WIDTH; | |
var PADDLE_HEIGHT; | |
var MARGIN; | |
var ball; | |
var BALL_WIDTH; | |
var BALL_HEIGHT; | |
var bricks; | |
var NROWS; | |
var NCOLS; | |
var BRICK_WIDTH; | |
var BRICK_HEIGHT; | |
var PADDING; | |
var rightDown = false; | |
var leftDown = false; | |
var releaseDown = false; | |
var resetDown = false; | |
var lives; | |
var score; | |
var livesEle; | |
var scoreEle; | |
function init() { | |
canvas = document.getElementById('canvas'); | |
ctx = canvas.getContext('2d'); | |
PADDLE_WIDTH = 120; | |
PADDLE_HEIGHT = 20; | |
MARGIN = 15; | |
paddle = new Paddle(canvas.width / 2 - (PADDLE_WIDTH / 2), | |
canvas.height - PADDLE_HEIGHT - MARGIN, | |
PADDLE_WIDTH, | |
PADDLE_HEIGHT, | |
'#FFFFFF'); | |
BALL_WIDTH = 20; | |
BALL_HEIGHT = 20; | |
ball = new Ball(canvas.width / 2, canvas.height/ 2, BALL_WIDTH, '#FFFFFF'); | |
NROWS = 5; | |
NCOLS = 9; | |
BRICK_WIDTH = (canvas.width/NCOLS) - 1; | |
BRICK_HEIGHT = 20; | |
PADDING = 1; | |
//initialises a 2D array of bricks | |
bricks = new Array(NROWS); | |
for (var i = 0; i < NROWS; i++) { | |
bricks[i] = new Array(NCOLS); | |
for (var j = 0; j < NCOLS; j++) { | |
bricks[i][j] = new Brick((BRICK_WIDTH + PADDING) * j, | |
((BRICK_HEIGHT + PADDING) * i) + MARGIN, | |
BRICK_WIDTH, | |
BRICK_HEIGHT, | |
'#FFFFFF'); | |
} | |
} | |
ball.dx = 0; | |
lives = 3; | |
livesEle = document.getElementById('lives'); | |
livesEle.innerHTML = lives; | |
score = 0; | |
scoreEle = document.getElementById('score'); | |
scoreEle.innerHTML = score; | |
loop(); | |
} | |
function loop() { | |
ctx.clearRect(0, 0, canvas.width, canvas.height); | |
requestAnimationFrame(loop); | |
if(lives >= 0) { | |
livesEle.innerHTML = lives; | |
scoreEle.innerHTML = score; | |
// prevents the ball from leaving the stage | |
ball.bound(canvas); | |
// resets the ball and decrements lives if | |
// it passes off the bottom of the screen | |
if(ball.y - (ball.radius * 2) >= canvas.height) { | |
paddle.x = canvas.width / 2 - (PADDLE_WIDTH / 2); | |
ball.x = canvas.width / 2; | |
ball.y = canvas.height/ 2; | |
ball.dx = 0; | |
lives--; | |
} | |
// ball/paddle collision detection | |
paddle.collide(ball); | |
// ball/brick collision detection | |
for (var i = 0; i < NROWS; i++) { | |
for (var j = 0; j < NCOLS; j++) { | |
if(bricks[i][j].collide(ball) == true) { | |
score++; | |
} | |
} | |
} | |
// update ball coords | |
ball.x += ball.dx; | |
ball.y += ball.dy; | |
// update paddle coords based on user input | |
if(leftDown == true && paddle.x >= 0) { | |
paddle.x -= paddle.dx; | |
} | |
if(rightDown == true && paddle.x + paddle.width <= canvas.width) { | |
paddle.x += paddle.dx; | |
} | |
//draw | |
ball.draw(ctx); | |
paddle.draw(ctx); | |
for (i=0; i < NROWS; i++) { | |
for (j=0; j < NCOLS; j++) { | |
if(bricks[i][j].state == true) { | |
bricks[i][j].draw(ctx); | |
} | |
} | |
} | |
} | |
else { | |
// draw game over text and restart instructions | |
ctx.fillStyle = '#FFFFFF'; | |
ctx.font = '64px Arial'; | |
ctx.fillText('You lose', 400, 300); | |
ctx.font = '18px Arial'; | |
ctx.fillText('Press [r] to start again', 400, 380); | |
// reset all game elements | |
if(resetDown == true) { | |
lives = 2; | |
score = 0; | |
for (i=0; i < NROWS; i++) { | |
for (j=0; j < NCOLS; j++) { | |
bricks[i][j].state = true; | |
} | |
} | |
} | |
} | |
} | |
function onKeyDown(evt) { | |
if (evt.keyCode == 39) rightDown = true; | |
else if (evt.keyCode == 37) leftDown = true; | |
else if (evt.keyCode == 38) leftDown = true; | |
else if (evt.keyCode == 82) resetDown = true; | |
} | |
function onKeyUp(evt) { | |
if (evt.keyCode == 39) rightDown = false; | |
else if (evt.keyCode == 37) leftDown = false; | |
else if (evt.keyCode == 38) leftDown = false; | |
else if (evt.keyCode == 82) resetDown = false; | |
} | |
window.onresize = function() { | |
console.log('resize'); | |
} | |
</script> | |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |
<title>Breakout</title> | |
</head> | |
<body onload="init()" onkeydown="onKeyDown(event)" onkeyup="onKeyUp(event)"> | |
<h2>Breakout</h2> | |
<canvas id="canvas" width="800" height="600"> | |
Canvas is not supported | |
</canvas> | |
<table> | |
<tr> | |
<td>Lives: </td> | |
<td id="lives"></td> | |
</tr> | |
<tr> | |
<td>Score: </td> | |
<td id="score"></td> | |
</tr> | |
</table> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Paddle(x, y, width, height, color) { | |
this.x = x; | |
this.y = y; | |
this.width = width; | |
this.height = height; | |
this.color = color; | |
this.dx = 10; | |
this.draw = function(context) { | |
context.save(); | |
context.translate(this.x, this.y); | |
context.fillStyle = this.color; | |
context.fillRect (0, 0, this.width, this.height); | |
context.restore(); | |
} | |
// detects collison between the ball and paddle | |
this.collide = function(ball) { | |
if(ball.x + ball.radius >= this.x && | |
ball.x - ball.radius <= this.x + this.width && | |
ball.y + (ball.radius / 2) >= this.y) { | |
// detects where on the paddle the ball has collided | |
// and deflects the ball in the appropriate direction | |
var percentage = (ball.x - this.x) / this.width; | |
ball.dx = (percentage * ball.dxRange) - (ball.dxRange / 2); | |
ball.dy = - ball.dy; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment