このページについて
コンパイルしないES2015(ES6)なブラウザゲームを作ります。ES2015(ES6)を触り始めたとか、これから触ってみたいとか、HTML/CSS/JSがなんとなくわかるとかいう方向けに、コマンドとか難しいものを使わずに、Chromeで動くコンパイル不要なES2015ゲームを作ろうというのをコンセプトに掲げて数回にわけて連載しているチュートリアル記事です。
TL;DR
前回は 仕様の確認と設計、基本パーツのHTMLとCSS ということで、単純なHTML/CSS をコーディングしましたが、そのままでは当然どうにもならないので、基本的なjsに切り分けていきます。
シリーズ目次
- phase0: [はじめに、対象者、使う技術、成果物](https://qiita.com/snakada/items/eb86ed81e0eb28e8d0ea) ([demo](https://snakada.github.io/wallgame/)) - phase1: [仕様の確認と設計、基本パーツのHTMLとCSSを作る](https://qiita.com/snakada/items/538067a6cae7d92eb866) ([demo](https://snakada.github.io/wallgame/phase1/)) - **phase2: 各DOMをjsで生成する** ([demo](https://snakada.github.io/wallgame/phase2/)) - phase3: [プレイヤーを動かせられるようにする](https://qiita.com/snakada/items/d8edefb2b071d96d7893) ([demo](https://snakada.github.io/wallgame/phase3/)) - phase4: プレイヤーが壁に当たらないようにする ([demo](https://snakada.github.io/wallgame/phase4/)) - phase5: プレイヤーを動かすとスコアが増えるようにする ([demo](https://snakada.github.io/wallgame/phase5/)) - phase6: 壁をランダムに生成する ([demo](https://snakada.github.io/wallgame/phase6/)) - phase7: 壁を自動で動くようにする ([demo](https://snakada.github.io/wallgame/phase7/)) - phase8: プレイヤーと壁が衝突するとゲームオーバーにする ([demo](https://snakada.github.io/wallgame/phase8/)) - phase9: ゲームオーバーになったらタイマーを止める ([demo](https://snakada.github.io/wallgame/phase9/))index.htmlファイルを編集する
前回のindex.htmlは一切jsがありませんでしたが、本記事では各DOMをjsで生成することにしますので、それらを読み込むように準備しておきます。修正前と修正後を比較すると、divタグがなくなってjsファイルの読み込みに置き換わっていますね。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>wallgame</title>
<link rel="stylesheet" href="./css/app.css">
</head>
<body>
<div id="app">
<div id="field">
<div id="player" style="top: 100px; left: 40px;"></div>
<div class="wall" style="right: 100px;">
<div class="wallTop" style="height: 150px;"></div>
<div class="wallBottom" style="height: 50px;"></div>
</div>
</div>
<div id="score">123</div>
<!--
<div id="gameover">GAMEOVER<br><span>RETRY</span></div>
-->
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>wallgame</title>
<link rel="stylesheet" href="./css/app.css">
</head>
<body>
<script src="./js/dom.js"></script>
<script src="./js/player.js"></script>
<script src="./js/wall.js"></script>
<script src="./js/score.js"></script>
<script src="./js/field.js"></script>
<script src="./js/gameover.js"></script>
<script src="./js/app.js"></script>
</body>
</html>
以降、今回新たに追加した各jsを詳しく見ていきます。
各DOMをjsで生成する
前の記事では、基本パーツのHTMLとCSSを作りました。パーツである各DOMを扱いやすくするために、本記事ではそれらをjsで生成するように置き換えていきます。
dom.js
jQueryはDOMやイベント等を操作するのに便利なライブラリですが、本シリーズではブラウザのネイティブなjsで動作させることを目的としているため、今回は使わないことにします。その代わりというわけでもないのですが、少しDOMの操作を便利にするためのユーティリティをまずはじめに用意しておきます。以下のとおりです。このあとの記事でもよく使うものばかりですので、しっかり見ておいてください。
/**
* idを持ったDOMを生成して返します。
* @param {string} id 設定するid
* @return {object} 生成したDOM
*/
const createDivWithId = id => {
const $div = document.createElement('div');
$div.id = id;
return $div;
};
/**
* CSSクラス名を持ったDOMを生成して返します。
* @param {string} className 設定するCSSクラス
* @return {object} 生成したDOM
*/
const createDivWithClassName = className => {
const $div = document.createElement('div');
$div.className = className;
return $div;
};
/**
* DOMにCSSスタイルを付与します。
* @param {object} $dom 処理対象のDOM
* @param {string} property 設定するCSSプロパティ名
* @param {string} value 設定するCSSプロパティ値
*/
const setDomStyle = ($dom, property, value) => $dom.style[property] = value;
/**
* 親DOMに子DOMを組み込みます。
* @param {object} $parent 親DOM
* @param {object} $child 子DOM
*/
const appendDomChild = ($parent, $child) => $parent.appendChild($child);
/**
* 親DOMに子DOMを複数まとめて組み込みます。
* @param {object} $parent 親DOM
* @param {object} children 子DOMの配列
*/
const appendDomChildren = ($parent, children) =>
children.forEach($child => appendDomChild($parent, $child));
/**
* DOMにテキストをセットします。
* @param {object} $dom 処理対象のDOM
* @param {string} text セットするテキスト
*/
const setDomText = ($dom, text) => $dom.textContent = text;
/**
* DOMにHTMLをセットします。
* @param {object} $dom 処理対象のDOM
* @param {string} html セットするHTML
*/
const setDomHtml = ($dom, html) => $dom.innerHTML = html;
app.js
次に、いわゆるエントリーポイントとなるapp.js
を見てみます。上記で用意しておいたcreateDivWithId()
とappendDomChild()
およびappendDomChildren()
を使います。$
で始まる変数が登場していますが、それらはあとで実装するDOMを表しています。ここではアプリ本体となる$app
に子DOM達を組み込んだうえでbody
タグに埋め込むくらいにぼんやり把握していただければ大丈夫です。
/**
* アプリDOMを生成して
* フィールドDOMとスコアDOMを組み込みます。
*/
const $app = createDivWithId('app');
appendDomChildren($app, [$field, $score, $gameover]);
/**
* bodyにアプリDOMを組み込みます。
*/
appendDomChild(document.body, $app);
player.js
キーボードでぐりぐり動かすことになるDOMです。壁にぶつかったら駄目な子です。ここでは$player
として、その位置を仮でセットしています。あとで$field
に組み込まれます。
/**
* プレイヤーDOMを生成します。
*/
const $player = createDivWithId('player');
setDomStyle($player, 'top', '100px');
setDomStyle($player, 'left', '40px');
wall.js
プレイヤーの障害物となるDOMです。ここで注目するのは$wall
という親DOMに対して$wallTop
と$wallBottom
という子DOMを組み込んでおくという点です。諸々含んでおいた$wall
はあとで$field
に組み込まれます。
/**
* 壁(枠)DOMを生成します。
*/
const $wall = createDivWithClassName('wall');
setDomStyle($wall, 'right', '100px');
/**
* 壁(上)DOMを生成します。
*/
const $wallTop = createDivWithClassName('wallTop');
setDomStyle($wallTop, 'height', '150px');
/**
* 壁(下)DOMを生成します。
*/
const $wallBottom = createDivWithClassName('wallBottom');
setDomStyle($wallBottom, 'height', '50px');
/**
* 壁(枠)DOMに壁(上)と壁(下)DOMを組み込みます。
*/
appendDomChildren($wall, [$wallTop, $wallBottom]);
score.js
$score
をつくって、仮の点数123
をセットしてあります。
/**
* スコアDOMを生成します。
*/
const $score = createDivWithId('score');
setDomText($score, '123');
field.js
$field
はゲームの舞台(=フィールド、面)となるDOMです。事前に作っておいた$player
と$wall
を組み込みます。
/**
* フィールドDOMを生成して
* プレイヤーDOMと壁(枠)DOMを組み込みます。
*/
const $field = createDivWithId('field');
appendDomChildren($field, [$player, $wall]);
gameover.js
ゲームオーバーになったときに出現する$gameover
というDOMです。ここまでと様相が違うのは、このDOM専用のhideGameOver()
という関数を用意しておき、実際に使っているという点です。あとの工程では表示する用の関数showGamveOver()
も作るのですが、今は要らないので省略しています。
/**
* ゲームオーバーDOMを生成します。
*/
const $gameover = createDivWithId('gameover');
setDomHtml($gameover, 'GAMEOVER<br><span>RETRY</span>');
/**
* ゲームーバー画面を隠す関数。
*/
const hideGameOver = () => setDomStyle($gameover, 'display', 'none');
/**
* 一旦ゲームオーバー画面は隠しておきます。
*/
hideGameOver();
本日は以上です。
ここで提示したコードは https://github.com/snakada/wallgame/tree/phase2 でもご覧いただけます。
また実際の画面は https://snakada.github.io/wallgame/phase2/ でご覧いただけます。
phace3: プレイヤーを動かせられるようにする に続きます。