JavaScriptで作るテトリスアプリ③ テトロミノの移動
1270 回閲覧されました
みなさんこんにちは、WEB制作のエンジニアのjonioです。
今回はテトロミノを回転させる所までのアウトプットをします。
それではアウトプットの開始です。
テトロミノの回転
コードを↓にします。
テトロミノを回転させるのが96行目ですが式だけ見てもイメージが湧かないので図で説明します。
ここが多分凄く難しく感じると思います。
考え方が数学的資質に影響する部分があるので理解できて仕組みを覚えた方がいいです。
その内すっと考えることができるようになります。
回転前と回転後のそれぞれのブロックに数字をつけていますが回転前の①・②・③・④の座標は↓です。
- tetro[0][0]
- tetro[0][1]
- tetro[1][1]
- tetro[1][2]
そして回転後の①・②・③・④の座標は↓です。
- ntetro[0][3]
- ntetro[1][3]
- ntetro[1][2]
- ntetro[2][2]
回転前のx座標と回転後のy座標が同じなので回転前のテトロミノのx座標は回転後のy座標を使ってtetro[ ][y]と置くことができます。
回転前のx座標ですがこれが難しくて気がつかないといけないです。
回転後の①・②・③・④のx座標は[3]・[3]・[2]・[2]です。
回転前の①・②・③・④のx座標は[0]・[0]・[1]・[1]です。
回転前のx座標ですが「4 – (回転後のx座標)- 1」で求めることができると思いませんか?
4と1をどうやって見つけたかですが規則性から気がついたんです。(自分から気がつくことができなくてもあっ、そうか!と思えればいいです)
よって回転後のテトロミノの座標がntetro[y][x]に対して回転前のテトロミノの座標はtetro[4-x-1][y]となります。
これで回転ができるのですがバグがあります、↓を見てください。
回転した時に壁にぶつかっているのに回転することができます。
壁や他のブロックに当たった状態では回転できないようにしますが回転のチェックは壁や他のブロックにぶつかっているかぶつかってないかなので「checkMove」関数のコードを↓にします。
74行目で「ntetro」が引数に追加されていますがこれは移動するテトロミノと回転するテトロミノを別の物として考えるためです。
移動のテトロミノが「tetro」で回転のテトロミノが「ntetro」です。
104行目・107行目・110行目・113行目の「checkMove」関数は3つ目の引数がないですが「tetro」をつけてもいいです。
その場合は75行目が必要ないです。
75行目の「ntetro == undefined」はntetroがない(回転のテトロミノではなく移動のテトロミノの場合)という意味です。
75 行目が付いたことによって80行目のif文の中の「tetro」が「ntetro」になります。
これで回転できるできないを考えたのでキーボードを押した時に回転を考えることができるようにするためにコードを↓にします。
119行目で一旦ntetroにrotate()を代入してntetroを120行目で使っていますがそんなことをせず119行目と120行目を合わせて「if(checkMove(0,0,ntetro)) tetro = rotate();」とした方が早くないですか?
しかしこれはできません、理由はcheckMove関数の引数の「ntetro」が定義されていないからです。
引数に「ntetro」を使うためにわざわざ面倒な置き方をしています。
120行目ですがif文の条件を満たしている時に回転するテトロミノを元々のテトロミノに代入することで回転を表現しています。
ちなみに「checkMove(0,0,ntetro)」の引数の値に0があるのは回転する場合はその場を動かない(x方向やy方向に進まない)からです。
今回はここまで次はテトロミノがフィールドの一番下に着いた時の処理です。