Bouncing off a circular Boundary with multiple balls?
- by Anarkie
I am making a game like this :
Yellow Smiley has to escape from red smileys, when yellow smiley hits the boundary game is over, when red smileys hit the boundary they should bounce back with the same angle they came, like shown below:
Every 10 seconds a new red smiley comes in the big circle, when red smiley hits yellow, game is over, speed and starting angle of red smileys should be random. I control the yellow smiley with arrow keys. The biggest problem I have reflecting the red smileys from the boundary with the angle they came. I don't know how I can give a starting angle to a red smiley and bouncing it with the angle it came. I would be glad for any tips!
My js source code :
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext("2d");
// Object containing some global Smiley properties.
var SmileyApp = {
radius: 15,
xspeed: 0,
yspeed: 0,
xpos:200, // x-position of smiley
ypos: 200 // y-position of smiley
};
var SmileyRed = {
radius: 15,
xspeed: 0,
yspeed: 0,
xpos:350, // x-position of smiley
ypos: 65 // y-position of smiley
};
var SmileyReds = new Array();
for (var i=0; i<5; i++){
SmileyReds[i] = {
radius: 15,
xspeed: 0,
yspeed: 0,
xpos:350, // x-position of smiley
ypos: 67 // y-position of smiley
};
SmileyReds[i].xspeed = Math.floor((Math.random()*50)+1);
SmileyReds[i].yspeed = Math.floor((Math.random()*50)+1);
}
function drawBigCircle() {
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radiusBig = 300;
ctx.beginPath();
ctx.arc(centerX, centerY, radiusBig, 0, 2 * Math.PI, false);
// context.fillStyle = 'green';
// context.fill();
ctx.lineWidth = 5;
// context.strokeStyle = '#003300'; // green
ctx.stroke();
}
function lineDistance( positionx, positiony )
{
var xs = 0;
var ys = 0;
xs = positionx - 350;
xs = xs * xs;
ys = positiony - 350;
ys = ys * ys;
return Math.sqrt( xs + ys );
}
function drawSmiley(x,y,r) {
// outer border
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(x,y,r, 0, 2*Math.PI);
//red ctx.fillStyle="rgba(255,0,0, 0.5)";
ctx.fillStyle="rgba(255,255,0, 0.5)";
ctx.fill();
ctx.stroke();
// mouth
ctx.beginPath();
ctx.moveTo(x+0.7*r, y);
ctx.arc(x,y,0.7*r, 0, Math.PI, false);
// eyes
var reye = r/10;
var f = 0.4;
ctx.moveTo(x+f*r, y-f*r);
ctx.arc(x+f*r-reye, y-f*r, reye, 0, 2*Math.PI);
ctx.moveTo(x-f*r, y-f*r);
ctx.arc(x-f*r+reye, y-f*r, reye, -Math.PI, Math.PI);
// nose
ctx.moveTo(x,y);
ctx.lineTo(x, y-r/2);
ctx.lineWidth = 1;
ctx.stroke();
}
function drawSmileyRed(x,y,r) {
// outer border
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(x,y,r, 0, 2*Math.PI);
//red
ctx.fillStyle="rgba(255,0,0, 0.5)";
//yellow ctx.fillStyle="rgba(255,255,0, 0.5)";
ctx.fill();
ctx.stroke();
// mouth
ctx.beginPath();
ctx.moveTo(x+0.4*r, y+10);
ctx.arc(x,y+10,0.4*r, 0, Math.PI, true);
// eyes
var reye = r/10;
var f = 0.4;
ctx.moveTo(x+f*r, y-f*r);
ctx.arc(x+f*r-reye, y-f*r, reye, 0, 2*Math.PI);
ctx.moveTo(x-f*r, y-f*r);
ctx.arc(x-f*r+reye, y-f*r, reye, -Math.PI, Math.PI);
// nose
ctx.moveTo(x,y);
ctx.lineTo(x, y-r/2);
ctx.lineWidth = 1;
ctx.stroke();
}
// --- Animation of smiley moving with constant speed and bounce back at edges of canvas ---
var tprev = 0; // this is used to calculate the time step between two successive calls of run
function run(t) {
requestAnimationFrame(run);
if (t === undefined) {
t=0;
}
var h = t - tprev; // time step
tprev = t;
SmileyApp.xpos += SmileyApp.xspeed * h/1000; // update position according to constant speed
SmileyApp.ypos += SmileyApp.yspeed * h/1000; // update position according to constant speed
for (var i=0; i<SmileyReds.length; i++){
SmileyReds[i].xpos += SmileyReds[i].xspeed * h/1000; // update position according to constant speed
SmileyReds[i].ypos += SmileyReds[i].yspeed * h/1000; // update position according to constant speed
}
// change speed direction if smiley hits canvas edges
if (lineDistance(SmileyApp.xpos, SmileyApp.ypos) + SmileyApp.radius > 300) {
alert("Game Over");
}
// redraw smiley at new position
ctx.clearRect(0,0,canvas.height, canvas.width);
drawBigCircle();
drawSmiley(SmileyApp.xpos, SmileyApp.ypos, SmileyApp.radius);
for (var i=0; i<SmileyReds.length; i++){
drawSmileyRed(SmileyReds[i].xpos, SmileyReds[i].ypos, SmileyReds[i].radius);
}
}
// uncomment these two lines to get every going
// SmileyApp.speed = 100;
run();
// --- Control smiley motion with left/right arrow keys
function arrowkeyCB(event) {
event.preventDefault();
if (event.keyCode === 37) { // left arrow
SmileyApp.xspeed = -100;
SmileyApp.yspeed = 0;
} else if (event.keyCode === 39) { // right arrow
SmileyApp.xspeed = 100;
SmileyApp.yspeed = 0;
} else if (event.keyCode === 38) { // up arrow
SmileyApp.yspeed = -100;
SmileyApp.xspeed = 0;
} else if (event.keyCode === 40) { // right arrow
SmileyApp.yspeed = 100;
SmileyApp.xspeed = 0;
}
}
document.addEventListener('keydown', arrowkeyCB, true);
JSFiddle : http://jsfiddle.net/gj4Q7/