Skip to content

Instantly share code, notes, and snippets.

@y-lohse
Created January 2, 2013 22:59
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save y-lohse/4439108 to your computer and use it in GitHub Desktop.
Save y-lohse/4439108 to your computer and use it in GitHub Desktop.
HTML5 pool game using the canvas and my Cannon framework : https://github.com/y-lohse/Cannon
Cannon.include('lib/math.js');
Cannon.include('lib/display.js');
Cannon.include('lib/misc.js');
Cannon.include('lib/SAT.js');
var canvas, cue;
var shooting = false, shootStart;
var rails = [], balls = [], pockets = [];
var WALL_SIZE = 10, BALL_SIZE = 10, POCKET_SIZE = BALL_SIZE*1.7;
Cannon.onReady = function(){
Cannon.use('*');
init();
canvas = new Cannon.Canvas('canvas');
var background = new Rectangle(0, 0, canvas.width, canvas.height);
canvas.addChild(background);
background.fillStyle = "#00cc00";
cue = new Ball(canvas.width/2, canvas.height/2, BALL_SIZE);
canvas.addChild(cue);
cue.fillStyle = '#ffffff';
balls.push(cue);
var rail = new Rail(0, 0, WALL_SIZE, canvas.height);
canvas.addChild(rail);
rail.fillStyle = '#cc3333';
rails.push(rail);
var rail = new Rail(canvas.width-WALL_SIZE, 0, WALL_SIZE, canvas.height);
canvas.addChild(rail);
rail.fillStyle = '#cc3333';
rails.push(rail);
var rail = new Rail(0, 0, canvas.width, WALL_SIZE);
canvas.addChild(rail);
rail.fillStyle = '#cc3333';
rails.push(rail);
var rail = new Rail(0, canvas.height-WALL_SIZE, canvas.width, WALL_SIZE);
canvas.addChild(rail);
rail.fillStyle = '#cc3333';
rails.push(rail);
var pocket = new Ball(10, 10, POCKET_SIZE);
canvas.addChild(pocket);
pocket.fillStyle = '#000000';
pockets.push(pocket);
var pocket = new Ball(canvas.width/2, 5, POCKET_SIZE);
canvas.addChild(pocket);
pocket.fillStyle = '#000000';
pockets.push(pocket);
var pocket = new Ball(canvas.width-10, 10, POCKET_SIZE);
canvas.addChild(pocket);
pocket.fillStyle = '#000000';
pockets.push(pocket);
var pocket = new Ball(10, canvas.height-10, POCKET_SIZE);
canvas.addChild(pocket);
pocket.fillStyle = '#000000';
pockets.push(pocket);
var pocket = new Ball(canvas.width/2, canvas.height-5, POCKET_SIZE);
canvas.addChild(pocket);
pocket.fillStyle = '#000000';
pockets.push(pocket);
var pocket = new Ball(canvas.width-10, canvas.height-10, POCKET_SIZE);
canvas.addChild(pocket);
pocket.fillStyle = '#000000';
pockets.push(pocket);
for (var i = 0; i < 10; i++){
var ball = new Ball(Cannon.Utils.randomIn(POCKET_SIZE, canvas.width-POCKET_SIZE), Cannon.Utils.randomIn(POCKET_SIZE, canvas.height-POCKET_SIZE), BALL_SIZE);
canvas.addChild(ball);
ball.fillStyle = '#cc0000';
balls.push(ball);
}
canvas.on('canvas:render', onRender);
cue.on('mousedown', function(event){
shooting = true;
shootStart = new Point2D(canvas.mouseX, canvas.mouseY);
});
canvas.on('canvas:mouseup', function(){
if (shooting){
var end = shootStart.substract(new Point2D(canvas.mouseX, canvas.mouseY));
cue.direction = new Vector2D(Math.max(Math.min(end.x/5, 10), -10), Math.max(Math.min(end.y/5, 10), -10));
}
});
};
function onRender(){
for (var i = 0; i < rails.length; i++){
var rail = rails[i];
for (var j = 0; j < balls.length; j++){
var ball = balls[j];
ball.updateBounding();
var col = CollisionSolver.solveCollsion(ball.boundingCircle, rail.boundingBox);
if (col.colliding){
var parallel = ball.direction.clone();
var perpendicular = ball.direction.clone();
var parAxis = col.collisions[0].clone().normalize();
var perAxis = col.collisions[0].clone().normalize();
var parallelDP = parallel.dotProduct(parAxis);
parallelDP *= -1;
var perpendicularDP = perpendicular.dotProduct(perAxis.rightNormal());
perAxis = perAxis.rightNormal();
parAxis.multiply(parallelDP);
perAxis.multiply(perpendicularDP);
var escapeVector = parAxis.clone().add(perAxis);
ball.direction = escapeVector;
ball.x += col.collisions[0].x;
ball.y += col.collisions[0].y;
}
}
}
var removeMe = [];
for (var i = 0; i < balls.length; i++){
var ball1 = balls[i];
ball1.updateBounding();
for (var j = i+1; j < balls.length; j++){
var ball2 = balls[j];
var col = CollisionSolver.solveCollsion(ball1.boundingCircle, ball2.boundingCircle);
if (col.colliding){
var nx = (ball2.x - ball1.x)/(2*ball1.radius);
var ny = (ball2.y - ball1.y)/(2*ball1.radius);
var gx = -ny;
var gy = nx;
var v1n = nx*ball1.direction.x + ny*ball1.direction.y;
var v1g = gx*ball1.direction.x + gy*ball1.direction.y;
var v2n = nx*ball2.direction.x + ny*ball2.direction.y;
var v2g = gx*ball2.direction.x + gy*ball2.direction.y;
ball1.direction = new Vector2D(nx*v2n + gx*v1g, ny*v2n + gy*v1g);
ball2.direction = new Vector2D(nx*v1n + gx*v2g, ny*v1n + gy*v2g);
//out of collision
ball1.x += col.collisions[0].x;
ball1.y += col.collisions[0].y;
}
}
for (var j = 0; j < pockets.length; j++){
var col = CollisionSolver.solveCollsion(ball1.boundingCircle, pockets[j].boundingCircle);
if (col.colliding && col.collisions[0].length() > 3){
removeMe.push(ball1);
}
}
ball1.direction.multiply(.97);
ball1.x += ball1.direction.x;
ball1.y += ball1.direction.y;
}
for (var i = 0; i < removeMe.length; i++){
if (removeMe[i] === cue){
cue.direction = new Vector2D(0, 0);
cue.x = canvas.width/2;
cue.y = canvas.height/2;
}
else{
canvas.removeChild(removeMe[i]);
balls = Cannon.Utils.arrayWithout(balls, removeMe[i]);
}
}
}
function init(){
Ball = Cannon.Display.Circle.extend({
__construct: function(x, y, radius){
this._super(false);
this.x = (x || 0);
this.y = (y || 0);
this.radius = (radius || 50);
this.direction = new Cannon.Math.Vector2D(0, 0);
this.boundingCircle = new Cannon.SAT.BoundingCircle(this.x, this.y, this.radius);
},
updateBounding: function(){
this.boundingCircle.x = this.x;
this.boundingCircle.y = this.y;
this.boundingCircle.radius = this.radius;
},
});
Rail = Cannon.Display.Rectangle.extend({
__construct: function(x, y, width, height){
this._super(false);
this.x = (x || 0);
this.y = (y || 0);
this.width = (width || 50);
this.height = (height || 50);
this.center = [this.width/2, this.height/2];
this.boundingBox = new Cannon.SAT.BoundingBox(this.x, this.y, this.width, this.height, this.rotation);
},
});
};
<html>
<head>
<title>Pool</title>
<meta name="Description" content="SAT powered pool game"/>
<style>
*{
margin: 0;
padding: 0;
}
</style>
<script type="text/javascript" src="lib/cannon.js"></script>
<script type="text/javascript" src="game.js"></script>
</head>
<body>
<div id="canvas" style="width: 500px; height: 300px; border: 1px solid black;"></div>
</body>
</html>
@saravanakumarv
Copy link

Hello Friend,Thank you for your codes and ideas.

I implemented your codes,but i cant get all balls randomly,i have get only one ball and it is also cue ball.
balance 9 balls i cant able to get.

please help me to solve my issues,and also cue functionality not working,cue pulling and releasing by mouse that is not working.

and your example the above functionality working fine.

i dont know whether i made mistakes or not.please help me to solve this issues

thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment