Boucing ball with collision in HTML5 Here\'s my code two two ball bouncing aroun
ID: 3809355 • Letter: B
Question
Boucing ball with collision in HTML5
Here's my code two two ball bouncing around inside a rectangle.
I couldn't figure out how to make make a collision when teo ball collide.
Please help me with the collision here.
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HTML5 Bouncing Ball with collison</title>
<style type="text/css">
<!--
body { background-color:#ededed;
font:normal 12px/18px Arial, Helvetica, sans-serif;
position: center;
}
h1 { display:block;
width:600px;
margin:20px auto;
padding-bottom:20px;
font:normal 24px/30px Georgia, "Times New Roman", Times, serif;
color:#333;
text-shadow: 1px 2px 3px #ccc;
border-bottom:1px solid #cbcbcb;
}
#container {
width:600px;
margin:0 auto;
}
#myCanvas {
background:#fff;
border:1px solid #cbcbcb;
}
-->
</style>
<script>
var context;
var dx= 4;
var dy=4;
var y=150;
var x=10;
var dx2= 3;
var dy2=3;
var y2=200;
var x2=20;
function draw(){
context= myCanvas.getContext('2d');
//clear the previous circle before creating a new one
context.clearRect(0,0,600,600);
context.beginPath();
context.fillStyle="#0000ff";
context.arc(x,y,20,0,Math.PI*2,true);
context.arc(x2,y2,20,0,Math.PI*2,true);
context.closePath();
context.fill();
boundaryLogic();
}
function init(){
context= myCanvas.getContext('2d');
setInterval(draw,10);
}
function boundaryLogic()
{
if( x<0 || x>600)
dx=-dx;
if( y<0 || y>600)
dy=-dy;
x+=dx;
y+=dy;
if( x2<0 || x2>600)
dx2=-dx2;
if( y<0 || y>600)
dy2=-dy2;
x2+=dx2;
y2+=dy2;
}
</script>
</head>
<body>
<h1>Two bouncing balls with collision</h1>
<div id="container">
<canvas id="myCanvas" width="600" height="600"></canvas>
</div>
<p class="home"><a href="https://thimbleprojects.org/dmai/213296"> <strong>Home>></strong></a></p>
</body></html>
Explanation / Answer
<html>
<head>
<title>Balls!</title>
<script type="text/javascript">
function ready() {
var Quadtree = function (lvl, coords) {
this.MAX_OBJECTS = 2;
this.MAX_LEVELS = 2;
this.level = lvl;
this.objects = [];
this.bounds = coords;
this.nodes = [];
this.clear = function () {
this.objects.length = 0;
for (var i = 0; i < this.nodes.length; i++) {
if (this.nodes[i] != null) {
this.nodes[i].clear();
this.nodes[i] = null;
}
}
}
this.split = function () {
var subWidth = Math.round(this.bounds.width / 2);
var subHeight = Math.round(this.bounds.height / 2);
var x = this.bounds.x;
var y = this.bounds.y;
this.nodes[0] = new Quadtree(this.level + 1, {
x: x + subWidth,
y: y,
width: subWidth,
height: subHeight
});
this.nodes[1] = new Quadtree(this.level + 1, {
x: x,
y: y,
width: subWidth,
height: subHeight
});
this.nodes[2] = new Quadtree(this.level + 1, {
x: x,
y: y + subHeight,
width: subWidth,
height: subHeight
});
this.nodes[3] = new Quadtree(this.level + 1, {
x: x + subWidth,
y: y + subHeight,
width: subWidth,
height: subHeight
});
}
this.getIndex = function (coord) {
var index = -1;
var horizontalMidpoint = this.bounds.x + (this.bounds.width / 2);
var verticalMidpoint = this.bounds.y + (this.bounds.height / 2);
var topQuadrant = (coord.y + coord.radius < verticalMidpoint);
var bottomQuadrant = (coord.y - coord.radius > verticalMidpoint);
if (coord.x + coord.radius < horizontalMidpoint) {
if (topQuadrant) {
index = 1;
} else if (bottomQuadrant) {
index = 2;
}
}
else if (coord.x - coord.radius > horizontalMidpoint) {
if (topQuadrant) {
index = 0;
} else if (bottomQuadrant) {
index = 3;
}
}
return index;
}
this.insert = function (coord) {
if (this.nodes[0] != null) {
var index = this.getIndex(coord);
if (index != -1) {
this.nodes[index].insert(coord);
return;
}
}
this.objects.push(coord);
if (this.objects.length > this.MAX_OBJECTS && this.level < this.MAX_LEVELS) {
if (this.nodes[0] == null) {
this.split();
}
var i = 0;
while (i < this.objects.length) {
var index = this.getIndex(this.objects[i]);
if (index != -1) {
this.nodes[index].insert(this.objects[i]);
this.objects.splice(i, 1);
} else {
i++;
}
}
}
}
this.retrieve = function (coord) {
var index = this.getIndex(coord);
var returnObjects = [];
if (index != -1 && this.nodes[0] != null) {
returnObjects = returnObjects.concat(this.nodes[index].retrieve(coord));
}
returnObjects = returnObjects.concat(this.objects);
return returnObjects;
}
this.stringify = function () {
return JSON.stringify(this, undefined, 0);
}
this.draw = function (ctx) {
var hmp = this.bounds.x + (this.bounds.width / 2);
var vmp = this.bounds.y + (this.bounds.height / 2);
context.beginPath();
context.moveTo(this.bounds.x, vmp);
context.lineTo(this.bounds.x + this.bounds.width, vmp);
context.stroke();
context.beginPath();
context.moveTo(hmp, this.bounds.y);
context.lineTo(hmp, this.bounds.y + this.bounds.height);
context.stroke();
for (var i = 0; i < 4; i++) {
if ((this.nodes[i] != null) && (this.nodes[i].objects.length != 0)) this.nodes[i].draw();
}
}
}
window.requestAnimFrame = (function () {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
function random_int(start, end) {
return Math.floor(Math.random() * (end - start + 1) + start);
}
var balls = function balls(context) {
this.context = context,
this.all_balls = [];
this.quad = new Quadtree(0, {
x: 0,
y: 0,
width: this.context.canvas.width,
height: this.context.canvas.height
});
this.add = function () {
var x = new ball(this.context);
this.all_balls.push(x);
return x;
}
this.start = function () {
(function animloop() {
requestAnimFrame(animloop);
var x = new Date().getTime() - (this.time || new Date().getTime());
this.time = new Date().getTime();
Balls.update(x);
Balls.collision(x);
Balls.frames();
Balls.redraw();
})();
}
this.frames = function () {
var time = new Date().getTime();
if (!this.last_fps_time) this.last_fps_time = time;
if (!this.frames_since_last) this.frames_since_last = 0;
this.frames_since_last++;
if (time - this.last_fps_time >= 1000) {
this.frame_text = this.frames_since_last + " FPS";
this.frames_since_last = 0;
this.last_fps_time = time;
}
}
this.redraw = function () {
this.context.save();
this.context.setTransform(1, 0, 0, 1, 0, 0);
this.context.clearRect(0, 0, canvas.width, canvas.height);
this.context.restore();
this.each(function () {
this.draw();
});
var quadtree = false;
if (quadtree) {
this.quad.draw(this.context);
}
this.context.fillStyle = '#000000';
this.context.font = "12px 'Open Sans'";
this.context.fillText(this.frame_text || this.frames_since_last + " FPS", 5, 17);
}
this.each = function (fn) {
for (var i = 0; i < this.all_balls.length; i++) {
fn.apply(this.all_balls[i]);
}
}
this.collision = function (t) {
var returnObjects = [];
var quad = this.quad;
this.each(function () {
var A = {}, B = {};
A = this;
returnObjects = quad.retrieve(A);
for (var x = 0; x < returnObjects.length; x++) {
B = returnObjects[x];
if (A != B) {
if (((a = Math.pow(A.x - B.x, 2)) + (b = Math.pow(A.y - B.y, 2))) <= (c = Math.pow(A.radius + B.radius, 2))) {
var ax = (A.x_vel * (A.mass - B.mass) + (2 * B.mass * B.x_vel)) / (A.mass + B.mass);
var ay = (A.y_vel * (A.mass - B.mass) + (2 * B.mass * B.y_vel)) / (A.mass + B.mass);
B.x_vel = (B.x_vel * (B.mass - A.mass) + (2 * A.mass * A.x_vel)) / (A.mass + B.mass);
B.y_vel = (B.y_vel * (B.mass - A.mass) + (2 * A.mass * A.y_vel)) / (A.mass + B.mass);
A.x_vel = ax;
A.y_vel = ay;
A.x = A.x + (t * A.x_vel / 16);
A.y = A.y + (t * A.y_vel / 16);
B.x = B.x + (t * B.x_vel / 16);
B.y = B.y + (t * B.y_vel / 16);
}
}
}
});
}
this.update = function (t) {
var quad = this.quad;
quad.clear();
this.each(function () {
quad.insert(this);
this.x += (t * this.x_vel / 16);
this.y += (t * this.y_vel / 16);
var t_x_vel = this.x_vel;
var t_y_vel = this.y_vel;
if (this.x >= this.context.canvas.width - this.radius && this.x_vel > 0) this.x_vel = -this.x_vel;
if (this.x <= this.radius && this.x_vel < 0) this.x_vel = -this.x_vel;
if (this.y >= this.context.canvas.height - this.radius && this.y_vel > 0) this.y_vel = -this.y_vel;
if (this.y <= this.radius && this.y_vel < 0) this.y_vel = -this.y_vel;
if (this.x_vel != t_x_vel) this.x += (t * this.x_vel / 16);
if (this.y_vel != t_y_vel) this.y += (t * this.y_vel / 16);
});
}
}
Object.prototype.ball = function ball(context) {
this.context = context;
this.canvas = context.canvas;
this.context.fillStyle = '#ABC123';
this.radius = 15;
this.x = random_int(this.radius + 1, this.canvas.width - this.radius - 1);
this.y = random_int(this.radius + 1, this.canvas.height - this.radius - 1);
this.x_vel = random_int(-8, 8);
this.y_vel = random_int(-8, 8);
this.draw = function () {
this.context.beginPath();
this.context.arc(this.x, this.y, this.radius, 0, (Math.PI / 180) * 360, false);
this.context.fillStyle = this.col;
this.context.fill();
this.context.closePath();
}
this.color = function (col) {
this.col = col;
}
this.resize = function (r) {
this.radius = r;
this.mass = Math.ceil(r * r * Math.PI / 750);
}
this.resize(this.radius);
return this;
}
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.canvas.width = window.innerWidth * 0.9;
context.canvas.height = window.innerHeight * 0.9;
var Balls = new balls(context);
for (var i = 0; i < 2; i++) {
var b = Balls.add();
b.color("#" + ((1 << 24) * Math.random() | 0).toString(16));
b.resize(random_int(15, 50));
b.draw();
}
Balls.start();
}
</script>
<style>
#canvas {
border:1px solid #000000;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.