前回はJavaScriptでおみくじアプリをつくりました。今回はもぐら叩きをつくります。
前回との共通点は絶対配置(position: absolute;)とz-indexを使うことです。
ではさっそくはじめましょう。
まずもくらの素材を仕入れます。これとかどうでしょうか?
モグライラスト – No: 805158/無料イラストなら「イラストAC」
Contents
HTML部分
最初はこんな感じで配置します。全部黒だとわかりにくいのでモグラを隠す帯の部分は別の色にしています。
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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
<!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> body { background-color: #000; } #container { width: 320px; height: 460px; position: relative; margin-top: 20px; } #first, #second, #third,#fourth { position: absolute; border:1px solid #000; height:50px; width:300px; } #first, #second, #third,#fourth { background-color: #555; } #second, #third,#fourth { background-color: #888; } #third,#fourth { background-color: #aaa; } #fourth { background-color: #ddd; } #first { top: 100px; } #second { top: 200px; } #third { top: 300px; } #fourth { top: 400px; } #mo1,#mo2,#mo3,#mo4,#mo5,#mo6,#mo7,#mo8,#mo9,#mo10 { position: absolute; height:60px; width:50px; } #mo1,#mo2,#mo3 { top: 80px; } #mo4,#mo5 { top: 180px; } #mo6,#mo7, #mo8 { top: 280px; } #mo9,#mo10 { top: 380px; } #mo1,#mo6 { left:20px; } #mo2,#mo7 { left:120px; } #mo3,#mo8 { left:220px; } #mo4, #mo9 { left:70px; } #mo5, #mo10 { left:170px; } </style> </head> <body> <div id = "container"> <div id = "game-result"></div> <div id = "first"></div> <div id = "second"></div> <div id = "third"></div> <div id = "fourth"></div> <div id = "mo1"><img src="mogura.png" width="50" alt="" /></div> <div id = "mo2"><img src="mogura.png" width="50" alt="" /></div> <div id = "mo3"><img src="mogura.png" width="50" alt="" /></div> <div id = "mo4"><img src="mogura.png" width="50" alt="" /></div> <div id = "mo5"><img src="mogura.png" width="50" alt="" /></div> <div id = "mo6"><img src="mogura.png" width="50" alt="" /></div> <div id = "mo7"><img src="mogura.png" width="50" alt="" /></div> <div id = "mo8"><img src="mogura.png" width="50" alt="" /></div> <div id = "mo9"><img src="mogura.png" width="50" alt="" /></div> <div id = "mo10"><img src="mogura.png" width="50" alt="" /></div> <button id="start-button" type="button">スタート</button> </div> <script src="app.js"></script> </body> </html> |
するとこのようになります。
つぎに適切にz-indexを指定して帯の向こう側にもぐらを隠します。
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 |
<style> #first { top: 100px; z-index: 10; } #second { top: 200px; z-index: 20; } #third { top: 300px; z-index: 30; } #fourth { top: 400px; z-index: 40; } #mo1,#mo2,#mo3 { z-index: 5; } #mo4,#mo5 { z-index: 15; } #mo6,#mo7, #mo8 { z-index: 25; } #mo9,#mo10 { z-index: 35; } </style> |
これでもぐらを土のなかに隠すことができます。
それからゲームを開始するためのボタンやゲームの結果を表示する部分の座標も設定しておきましょう。
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 |
<style> #start-button { position: absolute; top: 130px; left: 80px; width:150px; z-index: 100; } #game-result { position: absolute; top: 20px; left: 100px; z-index: 100; } #mogura-count { font-weight: bold; color: #ff0; } #hit-count { font-weight: bold; color: #0ff; } #miss-count { font-weight: bold; color: #f00; } #pass-count { font-weight: bold; color: #f0f; } </style> |
するとこんな感じになります。
JavaScript部分
次にモグラを移動させる処理をJavaScriptで書きます。
グローバル変数
app.js
まず各DOM要素を変数に格納します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
let $container = document.getElementById('container'); let $startButton = document.getElementById('start-button'); let $gameResult = document.getElementById('game-result'); let $mo1 = document.getElementById('mo1'); let $mo2 = document.getElementById('mo2'); let $mo3 = document.getElementById('mo3'); let $mo4 = document.getElementById('mo4'); let $mo5 = document.getElementById('mo5'); let $mo6 = document.getElementById('mo6'); let $mo7 = document.getElementById('mo7'); let $mo8 = document.getElementById('mo8'); let $mo9 = document.getElementById('mo9'); let $mo10 = document.getElementById('mo10'); let $mos = [$mo1,$mo2,$mo3,$mo4,$mo5,$mo6,$mo7,$mo8,$mo9, $mo10]; |
baseYsはもぐらの初期のY座標、moYsはそのときのもぐらのY座標、moveUpsはもぐらの移動方向が上かどうかのフラグです。
1 2 3 |
let baseYs = [100, 100, 100, 200, 200, 300, 300, 300, 400, 400]; let moYs = [100, 100, 100, 200, 200, 300, 300, 300, 400, 400]; let moveUps = [false,false,false,false,false,false,false,false,false,false]; |
もぐらは全部で30体、これまでの出現数、叩くことができた数、ミス(モグラ以外の部分を叩いてしまった場合)の数、見逃してしまった数を格納する変数を定義します。また30体目のもぐらがでてきて消滅したらゲーム終了です。isFinishingフラグは30体目のもぐらが出現したときにtrueになります。isFinishingがtrueのとき、すべてのモグラが初期座標にいるのであればゲーム終了であり、isPlayingフラグをfalseにします。
1 2 3 4 5 6 7 8 |
const maxCount = 30; let count = 0; let hitCount = 0; let missCount = 0; let passCount = 0; let isFinishing = false; let isPlaying = false; |
効果音を鳴らします。finishSound1はドラムロールの音です。しばらくしたら「ジャン!」という音(finishSound2)とともに結果を表示します。
1 2 3 4 |
let hitSound = new Audio('hit.mp3'); let missSound = new Audio('miss.mp3'); let finishSound1 = new Audio('finish1.mp3'); let finishSound2 = new Audio('finish2.mp3'); |
ミス判定
モグラ以外の部分がクリックされたらミスとして処理をします。そのためにイベントリスナを定義します。
ここではmissCountをインクリメントするとともに効果音を鳴らしています。
1 2 3 4 5 |
$container.addEventListener('click', (e) => { missCount++; missSound.currentTime = 0; missSound.play(); }); |
当たり判定
モグラの部分がクリックされたらポイントを追加します。このときクリックイベントがそのむこうがわに伝搬しては困るのでe.stopPropagation()を実行しています。
叩かれたモグラは土のなかに姿を消すようにしたいので、Y座標には初期座標を設定して移動方向は下にしています。モグラは初期座標より下には移動しないので動作を止めることができます。
モグラを叩いたときはhitCountをインクリメントして効果音を鳴らします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
for(let i=0; i<$mos.length; i++){ // 最初にモグラを初期座標に設定する $mos[i].style.top = moYs[i] + 'px'; // 叩かれたときの処理 $mos[i].addEventListener('click', (e) => { e.stopPropagation(); moYs[i] = baseYs[i]; $mos[i].style.top = moYs[i] + 'px'; moveUps[i] = false; hitCount++; hitSound.currentTime = 0; hitSound.play(); }, false); } |
ゲーム開始の処理
スタートボタンがクリックされたときの処理を示します。ゲーム中はボタンを非表示にします。念のためisPlayingがtrueかどうかも確認してtrueのときはなにもしません。またクリックイベントが伝搬しないように止めています。
ゲームが開始されたらisPlayingフラグはtrueに、isFinishingフラグはfalseにするとともに、ヒット数、ミス、見逃しの回数を0にリセットします。ボタンとゲーム結果を非表示にします。
モグラを動かすためにMoveMogura1とMoveMogura2のふたつの関数を呼び出しています。MoveMogura1はモグラを出現させるための関数で、MoveMogura2は出現したモグラを最初は上に、そのあと下に移動させる関数です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$startButton.addEventListener('click', (e) => { e.stopPropagation(); if(!isPlaying){ isPlaying = true; isFinishing = false; count = 0; hitCount = 0; missCount = 0; passCount = 0; $startButton.style.display = 'none'; $gameResult.style.display = 'none'; MoveMogura1(); MoveMogura2(); } }, false); |
出現させる関数
モグラを出現させる関数を示します。
乱数を発生させて、該当するモグラを上に移動するフラグをtrueにしています。ただしフラグがtrueになるのはY座標が初期座標のものだけです(現在移動中のものを二重に移動しない)。
モグラを出現させたらその総数をカウントしてmaxCountと一致するかこれを超えたらタイマーを停止します。そしてisFinishingフラグをtrueにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function MoveMogura1(){ let timerId1 = setInterval(()=>{ let r = Math.floor(Math.random() * $mos.length); if(!moveUps[r] && moYs[r] == baseYs[r]){ moveUps[r] = true; count++; // 出現したモグラの総数 if(count >= maxCount){ clearInterval(timerId1); isFinishing = true; } } }, 500); } |
モグラを動かす&ゲーム終了時の処理
出現したモグラを移動する関数を示します。
最初は上に移動します。初期座標と比較して36以上上に移動したら下に移動させます。もとの位置まで下がってきたら動かなくなります。
isFinishingがtrueのときはこれ以上モグラは出現しません。このあとすべてのモグラが初期座標に戻ったらゲーム終了です。タイマーを停止させて isPlayingフラグをfalseにします。そのあと0.5秒待機した後ドラムロールの音を流します。そのあとゲームの結果を表示させ、スタートボタンも再表示させます。
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 |
function MoveMogura2(){ let timerId2 = setInterval(()=>{ for(let i=0; i<$mos.length; i++){ if(baseYs[i] - moYs[i] >= 36) moveUps[i] = false; if(moveUps[i]) moYs[i] -= 2; if(!moveUps[i] && baseYs[i] - moYs[i] > 0) moYs[i] += 2; $mos[i].style.top = moYs[i] + 'px'; } if(isFinishing){ // isFinishingがtrueならゲーム終了かもしれない let ret = true; for(let i=0; i<$mos.length; i++){ if(baseYs[i] - moYs[i] > 0){ ret = false; break; } } // retがtrueなら本当にゲーム終了 if(ret){ clearInterval(timerId2); setTimeout(()=>{ // もったいぶってドラムロールの音を鳴らす finishSound1.currentTime = 0; finishSound1.play(); }, 500); setTimeout(()=>{ isPlaying = false; finishSound1.pause(); finishSound2.currentTime = 0; finishSound2.play(); $startButton.innerHTML = '再挑戦する'; $startButton.style.display = 'block'; $gameResult.innerHTML = `<span id = "mogura-count">モグラ ${maxCount} 匹</span><br> <span id = "hit-count">ヒット ${hitCount}</span><br> <span id = "miss-count">ミス ${missCount}</span><br> <span id = "pass-count">見逃し ${maxCount - hitCount}</span>`; $gameResult.style.display = 'block'; }, 3000); } } }, 40); // この位の値がゲームとして面白いと思う(各自で調整) } |