HTML + CSS + JavaScript でテトリスを作った話
はじめに
前の記事3件にも立て続けに書きましたが、仕事でWeb系の技術を使うことが増えたので、経験値貯めるために家でも何かしようと思って始めました。
こちらで動いています
操作法(テトリスのフレームを選択中は操作できます)
r
右回転 /shift + r
左回転左矢印(←)
左移動 /右矢印(→)
右移動 /下矢印(↓)
落下- ゲームオーバー時:
Enter
ゲーム再開
↓キーで画面も動いてしまうので、別ウィンドウで開く場合はこちらへどうぞ
仕様
作り込むとかなり時間を要しそうだったので、ある程度仕様を制限して作っています。
機能面
最低限の機能を実装する。これと言って特殊なことはしない
- ブロックが積まれること
- ちゃんと回せること
- ちゃんと移動できること
- 行が埋まったら消えること
- 消えたら上からブロックが詰まること
- 天井まで積み上がってしまったらゲームオーバーになること
- ゲームオーバーになったら、ゲームを再開できること
ちゃんと移動、ちゃんと回転、と言うのが意外と難しかったです。動作のパタンを分析していくと、特殊な移動を要するケースとして以下の場合があることが分かりました
- 壁際での回転した際に、壁にめり込まないよう内側にシフトする
- 床面すれすれで回転した際に、床にめり込まないよう上方向にシフトする
この辺への対応はアルゴリズムを考えました。(ソースコード参照)
サポートしない機能
全部作り込むときりが無いので、以下の内容は今回は作っていません。
- 得点計算
- 次に出てくるテトリスを予告する機能
- 時間が経つにつれレベルが上がる(出てくるインターバルや落下速度が速くなる)機能
- 消えるときのカッコいいアクション(本当は作りたい)
アルゴリズムを調べない
これは個人的にゲーム作りを楽しむために課したルールなのですが、アルゴリズムは自分で考えるようにしました。具体的には、先に書いた「壁際での回転時や、床面での回転」などです。
テトリス アルゴリズム などで検索すると、いろいろ出てきますが、改めて今見てみたところ、そこまで異なったことはしていないようで安心しました。
実装
HTML + CSS + JavaScript の総合的な勉強、という目的の下、今回は テーブルタグでどうにかする、を主方針として実装しました。
テーブルタグでどうにかする
<table><tr><th>
要素をグリッドとする- classを差し替えて
<th>
要素の背景を塗り替える - 不可視の
<th>
要素をステージ周囲において.wall
クラスを与え、壁や床として当たり判定を行う - 落ちて動かなくなったブロックを表す
<th>
要素に.inactive
クラスを与え、当たり判定を行う <tr>
を削除することで行が消えて残ったブロックが下に詰められ、新たに頭から<tr>
を加えることで、行数のつじつまを合わせる
処理のループ
ゲームを進める主要なループは以下の様になっています。特殊エフェクトのためのアニメーション等を入れていないので、非常にシンプルです。setTimeout()
で loop()
を繰り返します
var fallProcess = function() { if( block.fallJudge() ) { // 落ちられるなら block.fall(); // 落ちます } else { block.fix(); // 落ちられないなら、ブロックを固定します eraseJudge( block ); // 消える行ありますか?消します。詰めます。 if( block.gameOverJudge() ) { // ブロックが落ちないと言うことは、もしかしてゲームオーバーですか? return false; // fallProcess終了のおしらせ } block.initialize(); // ブロックを新たに生成(リセット) } return true; } var loop = function () { if( fallProcess() ) { // ゲームが続いている間は loopID = setTimeout(loop, 1000); // ループ継続 } else { loopID = null; // 終わっていたらloop継続をせず gameOverDisplay(); // 終了画面を出す } }; loopID = setTimeout(loop, 1000); // 初回のゲーム開始
最後に
コードは上げてあります。気まぐれに参考にしたい、なんて方がいらっしゃったら是非ともどうぞ
既存のゲームのコピーだし、アルゴリズムも特段こだわりがあるわけでもないので、この記事はこの程度でとどめておきます。
しかし、このくらいなら1週間程度で自力で作れるようになってきたので、少しはJavaScript力ついたかなぁ、と少し嬉しく感じております。