ボールが壁に反射する挙動を表現してみます。
まずはじめに、X軸方向/Y軸方向に速度があらかじめ分解されているパターンで考えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>requestAnimationFrame</title> <style> *{ margin: 0px; padding: 0px; } #canvas { background-color: #000; } </style> <head> <body> <canvas id="canvas" width="600" height="500"> ブラウザが対応しておりません。 </canvas> <script> window.addEventListener('load', draw, false); function draw(){ var x = 30, y = 30; var speedx = 5.0, speedy = 5.0; var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); function loop() { ctx.clearRect(0 ,0, canvas.width, canvas.height); //キャンバス上の図形をクリアにする x +=speedx; y +=speedy; if(x < 10 || x > 600-10){ speedx *= -1; } if(y < 10 || y > 500-10){ speedy *= -1; } ctx.beginPath(); ctx.fillStyle = 'green'; ctx.arc(x, y, 10, 0, Math.PI*2.0, true); ctx.fill(); requestAnimationFrame(loop); } loop(); } </script> </body> </html> |
36〜42行目
左右横の壁にボールが到達した場合には、ボールのX軸方向の速度のみを反転させています。また上下の壁に到達した場合には、ボールのY軸方向の速度のみを反転させます。
次に「反射の法則」を考慮してみます。反射の法則は下記の図のように、入射角と反射角は等しくなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>reflection</title> <style> *{ margin: 0px; padding: 0px; } #canvas { background-color: #000; } </style> <head> <body> <canvas id="canvas" width="600" height="500"> ブラウザが対応しておりません。 </canvas> <script> window.addEventListener('load', draw, false); function draw(){ var x = 30, y = 30; var speed = 7.0; //速さ var angle = 30; //角度 var radians = 0; //ラジアン var vx = 0; var vy = 0; updateBall(); var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); function updateBall(){ radians = angle * Math.PI / 180; //度をラジアンに変換 vx = Math.cos(radians)*speed; vy = Math.sin(radians)*speed; } function loop() { ctx.clearRect(0 ,0, canvas.width, canvas.height); //キャンバス上の図形をクリアにする x +=vx; y +=vy; if(x < 10 || x > 600-10){ angle = 180-angle; updateBall(); } if(y < 10 || y > 500-10){ angle = 360-angle; updateBall(); } ctx.beginPath(); ctx.fillStyle = 'green'; ctx.arc(x, y, 10, 0, Math.PI*2.0, true); ctx.fill(); requestAnimationFrame(loop); } loop(); } </script> </body> </html> |
47〜55行目
左右横の壁にボールが到達した場合は、角度を「180-angle」に、上下の壁にボールが到達した場合は、角度を「360-angle」に変換しています(参照文献『HTML5 Canvas』オライリージャパン p.166-169)。結局はデモ画面1の説明と同じことをしています。
関連ページ
角度を指定してオブジェクトを動かす[cos/sin][ベクトル]
参照文献