<!DOCTYPE html>
<html>
<head>
<title>CS 86 example Bounce</title>
<!-- Based on: http://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_building_practice -->
<script>
"use strict";
/*
**************************************************
* Main class
**************************************************
*/
class Main { //*8 Initialize
constructor () { //*8
// Save these, for convenience
this._ctx = myCanvas.getContext("2d"); //*5 General set up
myCanvas.width = window.innerWidth; //*5
myCanvas.height = window.innerHeight; //*5
// Create list of circles
this._circles = [] //*5
for (let i=0; i<100; i++) { //*5
this._circles.push(new Circle ( //*5
random (0, myCanvas.width), //*5
random (0, myCanvas.height), //*5
random (-4, 4), //*5
random (-4, 4), //*5
'rgb(' + random (0,255) + ',' + random(0,255) + ',' + random(0,255) +')', //*5
random (10,20))); //*5
}
this.loop() //*8
}
// Update everything and redraw for animation loop
loop() { //*6 Animation
this._ctx.fillStyle = 'rgba(0, 0, 0, 0.2)'; //*6
this._ctx.fillRect(0, 0, myCanvas.width, myCanvas.height); //*6
for (let c of this._circles) { //*6
c.draw(this._ctx); //*6
c.update(this._circles); //*6
}
// Set up for next frame, use arrow function to override "this"
requestAnimationFrame(() => this.loop()); //*6
}
}
class Circle { //*1 Circle class, like Square
constructor (x, y, velX, velY, color, size) { //*2 Maintains info
this._x = x; //*2
this._y = y; //*2
this._velX = velX; //*2
this._velY = velY; //*2
this._color = color; //*2
this._size = size; //*2
}
draw (ctx) { //*3 Knows how to draw itself when told
ctx.beginPath (); //*3
ctx.fillStyle = this._color; //*3
ctx.arc (this._x, this._y, this._size, 0, 2 * Math.PI); //*3
ctx.fill (); //*3
}
update (circles) { //*4 Knows how to update itself when told
// Check if circle has hit edge of canvas
if ((this._x + this._size) >= myCanvas.width) { //*4
this._velX = -(this._velX); //*4
}
if ((this._x - this._size) <= 0) { //*4
this._velX = -(this._velX); //*4
}
if ((this._y + this._size) >= myCanvas.height) { //*4
this._velY = -(this._velY); //*4
}
if ((this._y - this._size) <= 0) { //*4
this._velY = -(this._velY); //*4
}
// Check if circle has hit another circle
for (let c of circles) { //*7 Check for collision
if (!(this === c)) { //*7
let dx = this._x - c._x; //*7
let dy = this._y - c._y; //*7
let distance = Math.sqrt(dx*dx + dy*dy); //*7
if (distance < this._size + c._size) { //*7
c._color = this._color = 'rgb(' + random(0, 255) + ',' + random(0, 255) + ',' + random(0, 255) +')'; //*7
}
}
}
this._x += this._velX; //*4
this._y += this._velY; //*4
}
}
// Utility function, generate random integer between min and max
function random(min,max) {
return Math.floor (Math.random() * (max-min)) + min;
}
/*
**************************************************
* Initialize
**************************************************
*/
window.onload = function () { //*8
// Just instantiate, and loop the first time, which will trigger the next times
new Main() //*8
}
</script>
</head>
<body>
<h1>Bouncing Circles</h1>
<canvas id="myCanvas"></canvas>
</body>
</html>