パソコンのキー操作に対応させるためには以下のようにします。これだとキーが押されているあいだだけ移動の処理がおこなわれます。
Contents
PCでキーが押されているときだけキャラクタを移動させる
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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>サンプル</title> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> #container { border: 1px #000 solid; width: 320px; } </style> </head> <body> <canvas id = "canvas"></canvas> <script> // 描画関連の処理 const charSize = 32; const width = 320; const height = 480; let canvas = document.getElementById('canvas'); canvas.width = width; canvas.height = height; let ctx = canvas.getContext('2d'); let initX = (canvas.width - charSize) / 2; let initY = (canvas.height - charSize) / 2; let x = initX; let y = initY; // キーが押されているか? let up = false; let down = false; let left = false; let right = false; setInterval(()=>{ // キーが押されている場合はXY座標を変更 if(up) y--; if(down) y++; if(left) x--; if(right) x++; // canvas全体を黒で塗りつぶす ctx.fillStyle = '#000'; ctx.fillRect(0, 0, canvas.width, canvas.height); // x,yの値にあわせて正方形を描画する ctx.fillStyle = '#f00'; ctx.fillRect(x, y, charSize, charSize); }, 33); // キー操作関連の処理 document.onkeydown = (e) => { if(e.key == 'ArrowUp') up = true; if(e.key == 'ArrowDown') down = true; if(e.key == 'ArrowLeft') left = true; if(e.key == 'ArrowRight') right = true; } document.onkeyup = (e) => { if(e.key == 'ArrowUp') up = false; if(e.key == 'ArrowDown') down = false; if(e.key == 'ArrowLeft') left = false; if(e.key == 'ArrowRight') right = false; } </script> </body> </html> |
スマホでキャラクタを移動させる
ではスマホの場合はどうすればいいでしょうか?
スマホにはPCのようなキーボードがないのでボタンをタップしたらキャラクターが移動するようにします。
HTML部分にボタンを追加します。
1 2 3 4 5 6 7 8 9 |
<div id = "container" > <canvas id = "canvas"></canvas> <!-- ボタンを追加 --> <button id = "up">UP</button> <button id = "down">DOWN</button> <button id = "left">LEFT</button> <button id = "right">RIGHT</button> </div> |
clickはPCだけでなくスマホにも対応している
JavaScript部分に以下を追加します。
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
let $up = document.getElementById('up'); let $down = document.getElementById('down'); let $left = document.getElementById('left'); let $right = document.getElementById('right'); // タップしやすいようにボタンを大きくする(地味に重要) let arr = [$up, $down, $left, $right]; for(let i=0; i<4; i++){ arr[i].style.width = '75px'; arr[i].style.height = '70px'; } $up.addEventListener('click', (e) => { y--; }); $down.addEventListener('click', (e) => { y++; }); $left.addEventListener('click', (e) => { x--; }); $right.addEventListener('click', (e) => { x++; }); |
PCのmousedown mouseupはtouchstart touchendに対応
上のコードだとボタンをクリックすることで1ピクセルだけ移動します。またスマホでボタンをタップしても動作します。ただ連続で移動させることができません。ボタンを押している間だけ連続して移動させるためには以下のようにします。
ロングタッチ時のデフォルトの動作を抑止する
スマホはロングタッチをすると文字選択状態になってしまい、この状態で指を離しても’touchend’イベントを処理することができません。これでは移動を開始したキャラクターを止めることができません(実際にはそのボタンを押してすぐ離せばよいのだが、ユーザーにとってはそんなこと知る由もありません)。
自動で行なわれる動作を抑止するにはEvent.preventDefault()関数を呼び出すのですが、コンテキストメニューの表示も別に抑止する処理を入れてあります。
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 |
// $up.addEventListener('click', (e) => { // y--; // }); // $down.addEventListener('click', (e) => { // y++; // }); // $left.addEventListener('click', (e) => { // x--; // }); // $right.addEventListener('click', (e) => { // x++; // }); $up.addEventListener('touchstart', (e) => { // ロングタップ時に自動で行なわれる動作を抑止する e.preventDefault(); up = true; }); $down.addEventListener('touchstart', (e) => { e.preventDefault(); down = true; }); $left.addEventListener('touchstart', (e) => { e.preventDefault(); left = true; }); $right.addEventListener('touchstart', (e) => { e.preventDefault(); right = true; }); $up.addEventListener('touchend', (e) => { up = false; }); $down.addEventListener('touchend', (e) => { down = false; }); $left.addEventListener('touchend', (e) => { left = false; }); $right.addEventListener('touchend', (e) => { right = false; }); // ロングタッチでコンテキストメニューが表示されないようにする document.oncontextmenu = () => { return false; }; |
ユーザビリティは最悪?
各ボタンをタップしたときにe.preventDefault()を実行しなくても全体でデフォルトの動作を抑制する方法もあるのですが、これだとスクロールすることすらできなくなってしまいます。スクロール不要のゲームをつくるのであれば、これでもよいかもしれませんが、ユーザビリティは非常に悪くなります。
1 2 3 4 5 6 7 8 9 10 11 12 |
document.addEventListener('touchstart', (e) => { e.preventDefault(); }, {passive: false}); $up.addEventListener('touchstart', (e) => { // 不要 e.preventDefault(); up = true; }); // 不要 document.oncontextmenu = () => { // return false; // }; |
PCのマウス操作と落とし穴
PCのマウス操作に対応させるためには以下のようにします。これだけだと、マウスボタンを押したまま表示されているボタン以外の部分に移動したあとマウスボタンを離したときに問題がおきます。なので、どこであってもマウスボタンが離されたときにはすべての移動フラグをクリアする処理を入れています。
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 |
$up.addEventListener('mousedown', (e) => { up = true; }); $down.addEventListener('mousedown', (e) => { down = true; }); $left.addEventListener('mousedown', (e) => { left = true; }); $right.addEventListener('mousedown', (e) => { right = true; }); $up.addEventListener('mouseup', (e) => { up = false; }); $down.addEventListener('mouseup', (e) => { down = false; }); $left.addEventListener('mouseup', (e) => { left = false; }); $right.addEventListener('mouseup', (e) => { right = false; }); // マウスボタンを押したまま移動して離されたときにも対応させる document.addEventListener('mouseup', (e) => { up = false; down = false; left = false; right = false; }); |