先日の長期休暇で子供(中学生)から嬉しいリクエストがありました。
「ゲームを作ってみたい!」というリクエストを受け、子供と楽しく作れるゲームを一緒に実装しました。
その時の教えた流れや、開発言語・ゲーム内容の選定についてご紹介いたします。
開発言語を選定
子供と話していると、以下をイメージしていたようでした。
- パソコンでもスマホでも動かしたい
- ゆくゆくの拡張は自分で行い、「オリジナルのゲーム」を作りたい
- スマホにインストールして友達に見せたいわけでは無い
条件を満たす言語として、「HTML/JavaScript」を選定!
言語の難易度的にもちょうど良く、すぐに動きを確認できるため理解もしやすいかと思いました。
ゲームの内容
一番悩んだのが「ゲームの内容」です。
オリジナリティを出さないと条件に合わなくなりますし、かといって複雑なプログラミングはできません。
じゃんけん、オセロ、テトリス・・・色々考えましたが、どれもピンと来るものがなく、
最終的に「神経衰弱ゲーム」になりました。
自分の「推し」をカード表の画像にすれば、オリジナリティも出せますし、
枚数を増やして難易度を上げることもできるため子供でも拡張できます。
全体構成
神経衰弱ゲームは、以下のようなファイル構成で開発しました。
ファイルリスト
/
|- img/
| |- 0.jpg ~ 4.jpg
| |- back.jpg
|- index.html
|- sample.js
HTMLとはどんなもの?
ここからはどのように子供に教えていったのか、教え方のポイントを紹介します。
先ずはHTMLからです。ブラウザで実際に表示しながら記述していきました。
文法
HTML の文法は、以下のように伝えると理解しやすいようでした。
- 「タグ」と呼ばれるマーカーで文字を囲うことにより記述(「開く」タグ~「閉じる」タグ)
- 「ヘッダー」と「ボディ」に分かれており、それぞれ使えるタグが決まっている
- 位置・色などのスタイルはCSSで定義する
以上の3点だけです。
以降、使用するタグの意味などを調べながら説明していきました。
コードと画面の対応
ヘッダー
1 2 3 4 5 |
<head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>神経衰弱ゲーム</title> </head> |
先ずはヘッダー部分です。
2行目は「ここから HTML で書きますよ」というおまじないとだけ伝えました(笑)
3行目は「このゲームのタイトル」で、ブラウザの「タブ」に表示されることを一緒に確認。
ボディ
1 2 3 4 5 6 |
<body> <div> <div><img src="img/back.jpg" /></div> </div> </body> |
今回使用する div タグと img タグを使って、この HTML がどのように表示されるかを
一緒にブラウザで確認しながらタグとエレメントとの紐づけを理解させます。
img タグを含む div をコピペすることで、簡単に画像を羅列できることも教えます。
CSSでスタイリッシュに!
次にスタイルを記述するCSSについてです。
先ほど羅列したカードの裏面の画像は、CSSで「float: left」を指定しないと縦並びになります。
CSSでは、以下のようなポイントを教えました。
- CSS はスタイルを記述できる
- ID と CLASS という考え方がある
- HTML ファイルに直接記述したり、別のファイルで記述して読込むことができる
先ほど記述した HTML のヘッダーに CSS を書き、以下のようにしてカードを並べます。
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 |
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>神経衰弱ゲーム</title> <style> #panel { width: 910px; height: 490px; } .card { width: 180px; height: 240px; float: left; } /* 裏の状態 */ .back { background-image: url('img/back.jpg'); background-size: 180px 240px; } </style> </head> <body> <div id="panel"> <div class="card back"></div> <div class="card back"></div> <div class="card back"></div> <div class="card back"></div> <div class="card back"></div> <div class="card back"></div> <div class="card back"></div> <div class="card back"></div> <div class="card back"></div> <div class="card back"></div> </div> </body> </html> |
ここでは、以下のポイントについて実感してもらいます。
- 座標の計算が必要になること
- background-image を利用すれば img タグが不要になる場合があること
- 手書きだとカードを並べる冗長な記述が面倒なこと
JavaScriptで動きを付ける
最後は JavaScript で動きを付けていきます。
神経衰弱ゲームを作っているので、ここが一番の肝になります。
カードを並べる
先ほど「面倒」と体感した部分の自動化から始めます。
1 2 3 4 5 6 7 |
<body> <div id="panel"> </div> </body> |
1 2 3 4 5 6 7 8 9 10 11 |
var maxPair = 5; window.onload = function(){ var panel = document.getElementById('panel'); for (i = 0; i < (maxPair * 2); i++) { var div = document.createElement('div'); div.className = 'card back'; panel.appendChild(div); } } |
カードをシャッフル
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 |
var maxPair = 5; window.onload = function(){ var arr = []; for (var i = 0; i < maxPair; i++){ arr.push(i); arr.push(i); } shuffle(arr); var panel = document.getElementById('panel'); for (i = 0; i < (maxPair * 2); i++) { var div = document.createElement('div'); div.className = 'card back'; div.number = arr[i]; panel.appendChild(div); } } function shuffle(arr) { var n = arr.length; var temp, i; while (n) { i = Math.floor(Math.random() * n--); temp = arr[n]; arr[n] = arr[i]; arr[i] = temp; } return arr; } |
最初の for ループで、配列に 0~4 の数字を 2 つずつ格納します。
shuffle という関数を用意して中身をシャッフルし、カード1枚を表示する div の number にセット。
後ほど、この number に従って表の画像をセットします。
シャッフルのアルゴリズムはネットで検索し、ここでは「配列要素の入れ替え方」だけを教えます。
クリック動作の追加
最後の仕上げ、カードをクリックした際の動作を実装します。
先ずは、クリックした際にカードの表面を表示する動作を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function turn(e){ var div = e.target; // 裏向きのカードをクリックした場合 if (div.innerHTML == '') { div.className = 'card'; div.innerHTML = '<img src="img/' + div.number + '.jpg" />'; }else{ // 数字が表示されているカードは return return; } } |
先ほどカードの div エレメントに保存した number を使って、
innerHTML を使って内部に img タグのエレメントを作成します。
更にここでは、
- 1枚目と2枚目の区別
- 1枚目と2枚目が一致していた場合の動作
- 1枚目と2枚目が一致していなかった場合の動作
を実装する必要があります。条件分岐 if 文を教えます。
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 |
// 1枚目の処理 if (flgFirst) { cardFirst = div; flgFirst = false; // 2枚目の処理 } else { // 数字が1枚目と一致する場合 if (cardFirst.number == div.number) { backTimer = setTimeout(function() { div.className = 'card finish'; cardFirst.className = 'card finish'; backTimer = NaN; }, 500); // 一致しない場合 } else { backTimer = setTimeout(function() { div.className = 'card back'; div.innerHTML = ''; cardFirst.className = 'card back'; cardFirst.innerHTML = ''; cardFirst = null; backTimer = NaN; }, 500); } flgFirst = true; } |
完成したプログラム
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 |
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>神経衰弱ゲーム</title> <script type="text/javascript" src="sample.js"></script> <style> #panel { width: 910px; height: 490px; } .card { width: 180px; height: 240px; float: left; cursor: pointer; } /* 裏の状態 */ .back { background-image: url('img/back.jpg'); background-size: 180px 240px; } /* 終了時 */ .finish { cursor: default; } </style> </head> <body> <div id="panel"> </div> </body> </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 |
var backTimer; var flgFirst = true; var cardFirst; var maxPair = 5; window.onload = function(){ var arr = []; for (var i = 0; i < maxPair; i++){ arr.push(i); arr.push(i); } shuffle(arr); var panel = document.getElementById('panel'); for (i = 0; i < (maxPair * 2); i++) { var div = document.createElement('div'); div.className = 'card back'; div.number = arr[i]; div.onclick = turn; panel.appendChild(div); } } function shuffle(arr) { var n = arr.length; var temp, i; while (n) { i = Math.floor(Math.random() * n--); temp = arr[n]; arr[n] = arr[i]; arr[i] = temp; } return arr; } function turn(e){ var div = e.target; // カードのタイマー処理が動作中 if (backTimer) return; // 裏向きのカードをクリックした場合 if (div.innerHTML == '') { div.className = 'card'; div.innerHTML = '<img src="img/' + div.number + '.jpg" />'; }else{ // 数字が表示されているカードは return return; } // 1枚目の処理 if (flgFirst) { cardFirst = div; flgFirst = false; // 2枚目の処理 } else { // 数字が1枚目と一致する場合 if (cardFirst.number == div.number) { backTimer = setTimeout(function() { div.className = 'card finish'; cardFirst.className = 'card finish'; backTimer = NaN; }, 500); // 一致しない場合 } else { backTimer = setTimeout(function() { div.className = 'card back'; div.innerHTML = ''; cardFirst.className = 'card back'; cardFirst.innerHTML = ''; cardFirst = null; backTimer = NaN; }, 500); } flgFirst = true; } } |
おわりに
いかがでしたでしょうか。
唐突なリクエストで作り始めたゲームですが、カード表の画像を「推し」にすることで
ゴールに向かって一緒に楽しめました。