頑張る主婦!プログラミング Support by ウェブカツ‼️ vol.5.5[テトリス風ゲーム 全コード公開]
このブログは
ウェブカツ&プログラミング歴5ヶ月半の人による
・他のプログラミング初心者に送りたいこと
・自身の学習記録
などをまとめたものです。
JavaScriptで作るテトリス風ゲーム
See the Pen aboyvrV by hitoro (@hitoro) on CodePen.
※Resultを押すとゲームで遊べます(×1はレイアウトが崩れています)が矢印キーで画面が勝手にスクロールされてしまいます。改善方法がわからず申し訳ありません。
上記のコードはツイート後に書き換えたものになりますので、ツイート内の動画と異なる点がございます。
自主練テトリス、とりあえず完成した〜〜〜!!!
— ひとろ@ウェブカツ‼ (@hitoweb) 2019年8月28日
こんなシンプルなゲームでも作るんめっちゃ難しいんや。。。
動かせない範囲を設定するのが難しかった。
壁突っ切っていくし、壁にブロックが触れたら空中でブロック浮いたまま止まっちゃうし。
細かいところ修正が必要。#ウェブカツ女性割引 pic.twitter.com/kzwF2rQINw
ゲーム概要
・4つの正方形を組み合わせた7種類のブロックを使用する
・ブロックの可動範囲はグレーの壁の内側の横10×縦20列の黒い部分
・ブロック1つ落ちるごとに落ちる速さが少しづつ速くなる
・←→キーで左右移動、↓キーで速く落とす、↑キーでブロック回転する
・一列揃えて消すごとにスコアが入る
・まとめて消す方が高得点に繋がる
・次に落ちてくるブロックが右上に表示される
HTML・CSSはウェブカツのHTML/CSS部を頑張ってきている人には特別難しいことはないと思います。ただ一つ、ウェブカツでは出てきていないタグがあります。
<canvas>というものです。
グラフィックやアニメーションの描画領域を表します。描写領域だけなので実際の描写はJavaScriptで行います。
<canvas width= "200"; height="300" >のように
単位はつけません。
対応しているcssファイルにmarginやpaddingのように単位(px)をつけると拡大されてぼやけて表示されレイアウトが崩れます。
(参考) http://www.htmq.com/canvas/002.shtml
以下jsファイル内のコードについて、順を追って説明していきます。
(0)落ちてくるブロックを作る
\こんな形のブロック達を使いますよー/
と宣言し、配列データ(ブロックを)を作成して初期化します。
多次元連想配列の形式でブロックを箱に入れていきます。
0が空欄、1がボックスのある箇所を表しており、これがどのブロックなのか視覚的にわかります。
それぞれに色を指定します。
(1)スタンバイ画面
ここでゲームのバック画面を作ります。
getElementByIdで('back')を指定し、HTMLの中の<canvas id='back'>と関連付ける。続いてgetContextで描画機能を有効にする。('2d'がつくのはお決まりです)
壁の中の色や線の色の指定をします。
(2)ゲームスタート
背景が黒い('back')と、透明の('game')、2枚のスクリーンを重ねて透明の方にブロックを描きだしています。
ここではまず('game')を指定して要素を取得し、('2d')でブロックをかけるようにします。
ゲームが始まる前に一旦クリアしないと前のゲーム画面が残ったままなのでclearします。
runとはゲームが動いている状態(処理が走る)です。
全てのマス目に100という値を持たせます。
そして壁の部分にだけ99という値を持たせます。
後々ブロックは100のところだけ動けるという関数を作ります。
Math.floor(Math.random() * ◯ );
でブロックとその向きがランダムに出現するように設定します。
次のブロックを右上に表示させます。((7)を参考)
(3)ブロックを表示する
落下中のブロックは白い線で目立つようにしました。
bcolor[type] とすることで(0)で指定したブロックの形と色を対応させて表示します。
ここでのm:横方向、n:縦方向を表します。
例)T字のブロックの場合
mが左上から順に4個まで読み込む[0,0,0,0]
nが上から4列まで読み込む
[//
[0,0,0,0],
[1,1,1,0],
[0,1,0,0],
[0,0,0,0]
],
座標に1の値を持つところに枠線と色をつける
fillRect,strokeRectの引数の、前の2つはブロックを置く座標。
1つのブロックのサイズが20で作っているので座標を1表すのに*20している
後ろの2つは縦横20ずつ塗るという意味
(4)移動するための消しゴムモード
2Dコンテキストが消しゴムのようなモードに切り替わり描いた部分が消えます。
動作上ではそのまま形をキープして移動しているようにみえますが、
消す→次の場面に表示する、というのを繰り返しています。
(参考) globalCompositeOperationについて
http://www.htmq.com/canvas/globalCompositeOperation.shtml
(5)横移動と回転
ここでの(e)とは押したキーが何かを判断するための引数となっています。
ブロックを動かすので取得したいのは手前側の透明な('game')のスクリーンです。
動かす前に現在の座標と向きを一旦箱に保存しておきます。
消してから移動します。
keyCodeとは・・・
[←] 37 [ ↑ ] 38 [→] 39 [ ↓ ] 40
とコードが決まっているのです。
回転させるときの (iturn+1)%4; とあります。
%とは割った時の余りを表します。
なので上下左右それぞれに0〜3の数字を持たせて向きを変えています。
checkは(8)で説明します。
(6)下へ移動
('game')画面取得して('2d')で描けるようにします。
先ほどと同様現在の座標と向きを保存します。
消してから移動しますが、移動できるのか確認しています。
移動できるなら新しい場所に描き、できないなら移動前の場所に戻します。
当たり判定用の配列に設定します。
当たり判定とは・・・
移動したい方向に壁やブロックがあるとき、ブロックの上に乗ったときに動けないことを伝えないといけません。この判定がうまくできていないとブロックが壁を突っ切っていって、もはや何のゲームかわかりません。
stateという変数に値をいれて判断します。
0〜6ーブロック
99ー壁
100ー何もブロックがないところ
横一列のなかに99も100もなければ何かしらのブロックが入っている
=>1列揃った!!!
ということがわかります。
alineは(9)、scoreCalcは(11)で説明します。
(7)次のブロックの表示
次のブロックを表示する箇所('next')を取得します。
ここでも前のブロックが残って表示されないように一旦クリアします。
次のブロックをランダムで表示させます。
次ブロックが表示されるたびに(落ちるたびに)スピードをあげていきます。
初期値は1000ミリ秒で1マス落ちるのですが、50ミリ秒ずつ速くしていきます。
100ミリ秒より速くならないように設定しています。
(8)移動可能か調べる
移動したい場所にブロックが置けるかどうかを調べます。
引数は(置きたい場所の左からの座標,上からの座標,ブロックの回転向き,ブロックの種類)
範囲外のところには置けないようにします。
bx+m(横方向の座標)が<0(左の壁を指す)、>11(右の壁を指す)の場合はfalse
bx+n(縦方向の座標)が<20(下の壁を指す)の場合はfalse
また100(空欄を指す)じゃない場合はfalseという意味です。
これで壁を突っ切らず、ブロック同士が貫通せず表示できます。
(9)揃った列を消して下にずらす
左上のマス目から順に全てのマスをチェックしています。
(6)の当たり判定の話にでていたように、
1列全部100でも99でもない => 1列揃った!!
という判定が行われています。
列が揃ったら消えて残ったブロック達を下にずらします。
ここでデクリメント(--) を使うんですね。
インクリメント(++)はよく出てきますがデクリメントはどこで使うんだろうとずっと思っていました。
for文の引数はlineの「l」を取って列を消しています。
(10)ずれたブロックを表示する
canvasを取得 → 全部消す → もう一度表示
clearRectまではこれまでの説明と同じです。
次のfor文は100でも99でもないところ、つまり列が揃ったところに上書きしています。
(11)スコア計算
switch文で消した列が1列の場合は100点としていっぺんに多く消すとより高得点が出せます。
スコアがゲーム画面上部に表示されるようにinnerHTMLで書き換えています。
(12)自動落下
テトリス風ゲームの一番大事なのは自動落下ですよね。
runの間(ゲームが動いている間)はdown下に動く関数を実行することで、自動落下を再現することができます。
以上でテトリス風ゲームのコードの説明です。
最後までご覧いただきありがとうございます。
自分自身jsの理解が甘く、無駄なコードや、説明が不十分でわかりづらい点、誤っている点、多々あると思います。
今後も積極的に知識を入れて恐れずアウトプットに挑戦していけるように精進してまいります。
◆ウェブカツ記録◆
ウェブカツでプログラミングを学習し始めてから早5ヶ月半がたちます。
進歩状況
▼前回のブログはこちら
・オブジェクト指向部Lesson4
8月後半ウェブカツはやっていません。
少し気分転換して勢いをつけてまた頑張りたいなと思ったのでテトリス風ゲームを作ることになりました。
勉強時間
ウェブカツ → 180h
補足 → 24.5h
合計 204.5h
(自主練を含めた総勉強時間266h)
ウェブカツ、補足時間はほぼ増えておりません。自主練に多く費やしました。
8月末は19時間プログラミングと向き合うことができました。
▼女性割引を使ってプログラミングを学べるスクール
ウェブカツのサイトはこちら