11日目です。前回はimg要素を使って数字の画像を表示しました。今回はimg要素でなくdiv要素に画像を表示してみます。ちなみにdiv要素に画像を表示したからと言ってゲームが面白くなるわけではありません。
まず、div要素はinput要素やimg要素のようにHTMLファイル内にそれだけしかない要素ではありません。そこでスタイルシートでクラス名を指定しておきます。今回はnumというクラス名にしました。numberの略でnumというわけです。また、div要素はimg要素と違って、そのまま出力してしまうと1つずつ改行されて表示してしまいます。つまり、数字が縦横に並ばずに縦方向に並んでしまいます。さすがに、これでは困るので以下のようにHTMLファイル内にスタイルシートを記述します。
.num { width:48px; height: 48px; display: inline-block; }
display: inline-block;とすればimg要素と同様に横並びで表示することができます。(インライン要素として扱われます)
次にプログラムの修正です。これまでは以下のようにquerySelectorAll()では要素名を指定していましたが、これをスタイルシートクラス名であるnumに変更します。
var ele = document.querySelectorAll(".num"); // ●クリックしたら処理するようにイベントを設定
また、img要素の場合はsrc属性に画像のURLを指定していましたが、div要素の場合styleプロパティのbackgroundImageプロパティに画像のURLを指定する必要があります。つまり以下のようになります。
ele[i].style.backgroundImage = "url(images/"+num[i]+".png)"; // ●画像を表示する
今回の変更はこれで終わりです。例によって変更があった部分は●印をつけてあります。○印部分はコメントのみ修正した部分です。
次回はcanvas要素を使って表示したいところですが、その前にプログラムを多少スリムにし、ゲームオーバー後でもプレイできてしまう不具合を修正します。
HTMLファイルの内容
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TEN</title>
<style>
#stage { width : 200px; height : 320px; background-image: url(images/bg.png); }
.num { width:48px; height: 48px; display: inline-block; }
#clearMsg { position : absolute; left: 10px; top: 200px; font-size: 18pt; color: red; visibility: hidden; }
</style>
</head>
<body>
<h1>TEN</h1>
<div>SCORE : <span id="score">0</span> TIME : <span id="timeString">0</span></div>
<div id="stage"></div>
<div id="msg"></div>
<div id="clearMsg">ステージクリア!</div>
<script src="main.js"></script>
</body>
</html>
JavaScriptファイル (main.js) の内容
// TEN HTML5 version
// (c) 2014 Cybermuse
// Arranger 古籏一浩
var score = 0; // スコア(得点)を入れる変数
var count = 0; // ボタンの合計を入れる変数
var prevNumber = 0; // 直前にクリックした数字を入れる変数
var prevEle = null; // 直前にクリックした要素を入れる変数
var time = 0; // ゲームオーバーまでの時間
var timerID = null; // カウントダウンタイマーのIDを入れる変数
var firstClickFlag = false; // 最初にクリックしたかどうかのフラグ
// 初期化処理
function init(){
// ----- ステージを動的に生成する ------
var w = 4; // 横の数字の個数
var h = 6; // 縦の数字の個数
var htmlString = "";
for(var j=0; j<h; j++){
for(var i=0; i<w; i++){
htmlString = htmlString + '<div class="num"></div>'; // ●div要素で生成
}
htmlString = htmlString + '<br>';
}
document.getElementById("stage").innerHTML = htmlString;
// ------ ここまで ------
var ele = document.querySelectorAll(".num"); // ●クリックしたら処理するようにイベントを設定
for(var i=0; i<ele.length; i++){ // 要素の数だけ繰り返す
ele[i].onclick = addNumber; // クリック時に呼び出す関数を指定する
}
count = ele.length; // ○div要素の総数を入れる
setRandomValue(ele); // ○div要素の数を渡す
time = 30; // 30秒に設定する
document.getElementById("timeString").innerHTML = time + "秒"; // 時間を表示する
}
// ランダムに値を設定する関数
function setRandomValue(ele){
var len = ele.length; // 要素の総数
// ○img要素にランダムな値を設定する
var num = [ ];
for(var i=0; i<len; i+=2){ // 要素の数だけ繰り返す
var n = Math.floor(Math.random() * 9) + 1; // 1〜9までの数値をランダムに生成する
num.push(n);
num.push(10 - n);
}
// 配列要素をele.length回シャッフルする
for(var i=0; i<len; i++){
var p1 = Math.floor(Math.random() * len); // ○div.num要素の数の範囲で乱数を発生させる
var p2 = Math.floor(Math.random() * len); // ○div.num要素の数の範囲で乱数を発生させる
var n = num[p1]; // 2つの要素の内容を入れ替える
num[p1] = num[p2];
num[p2] = n;
}
// ○img要素に値を設定する
for(var i=0; i<len; i++){ // 要素の数だけ繰り返す
ele[i].value = num[i]; // 値を設定する
ele[i].style.backgroundImage = "url(images/"+num[i]+".png)"; // ●画像を表示する
}
}
// 2つの数字の合計が10かどうか調べる
function addNumber(){
// 初めてのクリックかどうか調べる
if (firstClickFlag === false){
firstClickFlag = true; // クリックされたらtrueにする
timerID = setInterval("displayTimer()", 1000); // 1秒ごと定期的にタイマー表示関数を呼び出す
}
// 1個目のクリックの場合
if (prevNumber === 0){
prevEle = this; // 要素の情報を変数に入れる
prevEle.style.backgroundColor = "red"; // 背景を赤色にする
prevNumber = parseInt(this.value); // クリックされた要素の番号を変数に入れる
return; // 関数から抜ける
}
// 2個目のクリックの場合
var total = prevNumber + parseInt(this.value); // 直前の数値とクリックされた要素の数値を加算する
if (total === 10){ // 合計が10の場合の処理
this.style.visibility = "hidden"; // 現在の要素を非表示にする
prevEle.style.visibility = "hidden"; // 前の要素を非表示にする
prevNumber = 0; // 数値を0にする
document.getElementById("msg").innerHTML = "OK!"; // メッセージを表示する
score = score + 1; // スコア(得点)を追加する
document.getElementById("score").innerHTML = score; // スコア(得点)を表示する
count = count - 2; // 合計から2を引く
if (count === 0){ // 全部消したかどうか調べる
document.getElementById("clearMsg").style.visibility = "visible"; // ステージクリアメッセージを表示する
clearInterval(timerID); // タイマーを停止する
setTimeout(function(){ // 2秒後に表示されているメッセージを消すためのタイマー
document.getElementById("clearMsg").style.visibility = "hidden"; // ステージクリアメッセージを消す
var ele = document.querySelectorAll(".num"); // ●div.num要素を取得する
setRandomValue(ele); // 乱数値を設定する
for(var i=0; i<ele.length; i++){
ele[i].style.visibility = "visible"; // 表示する
ele[i].style.backgroundColor = ""; // 透明にする
}
count = ele.length; // input要素の総数を入れる
document.getElementById("msg").innerHTML = ""; // メッセージをクリア
timerID = setInterval("displayTimer()", 1000); // 1秒ごと定期的にタイマー表示関数を呼び出す
}, 2000);
}
return; // 関数から抜ける
}
// 合計が10でなかった場合
prevNumber = 0; // 数値を0にする
prevEle.style.backgroundColor = ""; // 透明にする
document.getElementById("msg").innerHTML = "合計が10じゃないよ!"; // メッセージを表示する
}
// タイマーの表示処理
function displayTimer(){
time = time - 1;
document.getElementById("timeString").innerHTML = time + "秒";
if (time < 1){ // 時間が1より少なくなったらゲームオーバー
clearInterval(timerID); // タイマーを停止する
alert("ゲームオーバー");
}
}
init(); // 初期化処理を呼び出す