HTML5 Canvas – Angle bounce using some rotational maths

February 9, 2011
/ / /

Rotating line with angle bounce

OK here we go. I’ll try and explain this one a little bit. I looked everywhere for a good tutorial on performing angled bounces with an object in the <canvas> element but found nothing specific enough. So after a lot of late nights, I finally found one that was written in ActionScript. I’ve adapted it back to JavaScript (which is basically the same thing) to further play with what the new HTML5 features give us.

I won’t go into detail about the movement of the ball or the paddle… If you want me to – email me.

Please excuse my variable names. They’re horrible – I know… Just bare with them for now. posx and posy are the positions of the ball. x1 and y1 are the starting positions of the line and x2 and y2 are the end of the line.

cos and sin are tricky ones. I haven’t shown the whole code here (obviously) but further up I have made these into sort of a shortcut.

var angle = lineAngle * Math.PI / 180;
var cos = Math.cos(angle);
var sin = Math.sin(angle);

For all this rotational stuff to work your degrees need to be converted to radians. pi / 180 will convert that for you.

I have commented most of the code in the actual HTML page(click the picture at the top to get there).

Right, below is where all the magic happens… I think the math is based on a 3×3 rotational matrix, that isn’t something I’m very familiar with so apologies if that’s not 100% correct. If there is anyone that has a better explanation of rotational matrices than the ones currently online please let me know!

The reason it looks messy is because you need to rotate everything(ball position, the line position and the velocity of the ball) to (0,0) coordinates. Then run the test to see if the ball has hit the line, if it has, make the ball bounce in the other direction and rotate everything back, if not, just rotate everything back and carry on as before with the ball traveling in the same direction. Next frame, rotate it all and test again. That’s right! So 25 times a second it is rotating all the elements to (0,0), testing if something happens, then rotating it all back. Seems criminally inefficient right? That’s just how it works.

Hope this is easy enough to follow:

get position of ball, relative to line
x1 y1 – Start point of line and x2 y2 – end point

newposx = posx - x1;
newposy = posy - y1;
newposx2 = posx - x2;
newposy2 = posy - y2;

rotate coordinates giving the rotated position of the ball
relative to the line

rotposx = cos * newposx + sin * newposy;
rotposy = cos * newposy - sin * newposx;
rotposx2 = cos * newposx2 + sin * newposy2;
rotposy2 = cos * newposy2 - sin * newposx2;

rotate velocity
vx1 vy1

rotvelx = cos * velx + sin * vely;
rotvely = cos * vely - sin * velx;

perform bounce with rotated values
if ball hits on top of the line

if (rotposy >  -  r && rotposy < 0 - (r / 2) &&
    newposx > 0 && newposx < 100)
	rotvely *=  bounce;
	rotposy =  -  r;

if ball hits on the bottom of the line

if (rotposy <  r && rotposy > 0 + (r / 2) &&
    newposx > 0 && newposx < 100)
	rotvely *=  bounce;
	rotposy =  r;

rotate everything back;

newposx = cos * rotposx - sin * rotposy;
newposy = cos * rotposy + sin * rotposx;
newposx2 = cos * rotposx2 - sin * rotposy2;
newposy2 = cos * rotposy2 + sin * rotposx2;
velx = cos * rotvelx - sin * rotvely;
vely = cos * rotvely + sin * rotvelx;
posx = x1 + newposx;
posy = y1 + newposy;

As you can see, when rotating everything back, you are simply changing the + to a – in the cos and sin equations. I’ll look at optimising this code a little bit too when I get some free time. I’m sure there’s a few shortcuts that I could have taken. But you get the general idea of how the physics work.

I hope you have got something beneficial out it.

– Stevo

Comments are closed.