質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

YouTube

YouTubeとはユーザーがビデオをアップロード・共有・閲覧できるビデオ共有ウェブサイトです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1596閲覧

テトリスの当たり判定が理解できません

teles

総合スコア1

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

YouTube

YouTubeとはユーザーがビデオをアップロード・共有・閲覧できるビデオ共有ウェブサイトです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2022/03/12 19:13

編集2022/03/12 23:51

テトリスをJavaScript作成中です。
あきちょんさんのyoutubeを見ながらコードを書いているのですが、ブロックの当たり判定の部分が理解できなくてどなたか教えていただけたら助かります。

if(field[ny][nx]){ retune false; } でなぜ当たり判定ができるのかが理解できません。

--------- 理解できない部分 ----------

JavaScript

1コード 2```当たり判定 3function checkMove(mx, my){ 4 for(let y=0; y<TETRO_SIZE; y++){ 5 for(let x=0; x<TETRO_SIZE; x++){ 6 let nx = tetro_x + mx + x; 7 let ny = tetro_y + my + y; 8 9 if( tetro[y][x]){ 10 if( field[ny][nx] || 11 ny < 0 || 12 nx < 0 || 13 ny >= FIELD_ROW|| 14 nx >= FIELD_COL ){ 15 return false; 16 } 17 } 18 } 19 } 20 return true; 21} 22 23 24 25------------ 参照コード ---------- 26<!DOCTYPE html> 27<html> 28<body> 29<canvas id="can"></canvas> 30<script> 31 32//フィールドサイズ 33const FIELD_COL = 10; 34const FIELD_ROW = 20; 35 36//ブロック一つのサイズ(px) 37const BLOCK_SIZE = 30; 38 39//キャンバスサイズ 40const SCREEN_W = BLOCK_SIZE * FIELD_COL; 41const SCREEN_H = BLOCK_SIZE * FIELD_ROW; 42 43//テトロミノのサイズ 44const TETRO_SIZE = 4; 45 46let can = document.getElementById("can"); 47let con = can.getContext("2d"); 48 49can.width = SCREEN_W; 50can.height = SCREEN_H; 51can.style.border = "4px solid #555"; 52 53//テトロミノ本体 54let tetro = [ 55 [ 0, 0, 0, 0], 56 [ 1, 1, 0, 0], 57 [ 0, 1, 1, 0], 58 [ 0, 0, 0, 0] 59]; 60 61//テトロミノの座標 62let tetro_x = 0; 63let tetro_y = 0; 64 65//フィールド本体 66let field = []; 67 68init(); 69drawAll(); 70 71//初期化 72function init(){ 73for(let y=0; y<FIELD_ROW; y++) 74{ 75 field[y] = []; 76 for(let x=0; x<FIELD_COL; x++) 77 { 78 field[y][x] = 0; 79 } 80} 81 //テスト 82 field[ 5][8] = 1; 83 field[19][0] = 1; 84 field[19][9] = 1; 85} 86 87//ブロック一つを描画する 88function drawBlock(x, y){ 89 let px = x * BLOCK_SIZE; 90 let py = y * BLOCK_SIZE; 91 92 con.fillStyle="red"; 93 con.fillRect(px, py, BLOCK_SIZE, BLOCK_SIZE); 94 con.strokeStyle="black"; 95 con.strokeRect(px, py, BLOCK_SIZE, BLOCK_SIZE); 96} 97 98//全部を描画する 99function drawAll(){ 100 con.clearRect(0,0,SCREEN_W,SCREEN_H); 101 102 for(let y=0; y<FIELD_ROW; y++){ 103 for(let x=0; x<FIELD_COL; x++){ 104 if( field[y][x] ){ 105 drawBlock(x, y); 106 } 107 } 108 } 109 for(let y=0; y<TETRO_SIZE; y++){ 110 for(let x=0; x<TETRO_SIZE; x++){ 111 if( tetro[y][x]){ 112 drawBlock(tetro_x+x, tetro_y+y); 113 } 114 } 115 } 116} 117 118//当たり判定 119function checkMove(mx, my){ 120 for(let y=0; y<TETRO_SIZE; y++){ 121 for(let x=0; x<TETRO_SIZE; x++){ 122 let nx = tetro_x + mx + x; 123 let ny = tetro_y + my + y; 124 125 if( tetro[y][x]){ 126 if( field[ny][nx] || 127 ny < 0 || 128 nx < 0 || 129 ny >= FIELD_ROW|| 130 nx >= FIELD_COL ){ 131 return false; 132 } 133 } 134 } 135 } 136 return true; 137} 138 139function rotate(){ 140 141} 142 143//キーボードが押されたときの処理 144document.onkeydown = function(e){ 145 switch(e.keyCode){ 146 case 37: //左 147 if( checkMove( -1, 0) ) 148 tetro_x--; 149 break; 150 case 38: //上 151 if( checkMove( 0, -1) ) 152 tetro_y--; 153 break; 154 case 39: //右 155 if( checkMove( 1, 0) ) 156 tetro_x++; 157 break; 158 case 40: //下 159 if( checkMove( 0, 1) ) 160 tetro_y++; 161 break; 162 case 32: //スペース 163 break; 164 } 165 166 drawAll(); 167} 168 169 170</script> 171</body> 172</html>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2022/03/12 23:17

このままではコードが読みづらいので、質問を編集し、</>(コードの挿入)ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
teles

2022/03/12 23:52

初めて使うのでやり方がわからず申し訳ありません。 教えていただきありがとうございました。
m.ts10806

2022/03/13 00:28

提示されたコードはどこまで理解されているのでしょうか。 結局は一つずつ追っていくしかないですけど。
m.ts10806

2022/03/13 00:30 編集

なんならその発信者にコメントで聞いては? この質問を見ている人にとっては他人が書いたコードなので、このような実装にした意図はわからないし読むだけで完全に把握できるわけではないです。
teles

2022/03/13 01:09

一応発信者様には今質問をしているところです。 ただ2年前の動画なので回答が来るかどうか... なのでこちらでも質問させていただきました。 他の部分のコードは一応理解出来ていて、for文の中で if(field[ny][nx]){ retune false; }このコードで当たり判定になることが理解できない状態です。
tabuu

2022/03/13 03:02

提示されているソースが全てでは無さそうなので推測ですが fieldという二次元配列が縦横に該当して、ブロックが配置されていない箇所は0のようです。 >if(field[ny][nx]){ retune false; } 当たり判定というよりは、移動可能かどうかチェックしていると思います。
guest

回答1

0

ベストアンサー

let nx = tetro_x + mx + x;
let ny = tetro_y + my + y;

テトリスのブロック全体を収めるものをテトロミノという用語で使われているのでそれに従います
tetro_x,tetro_y ・・・テトロミノの左上の座標がフィールド座標のどこにあるか
tetro_x+mx+x,tetro_y+mx+y・・・テトロミノ内部のローカル座標(x, y)の移動先座標(x+mx,y+my)をフィールド座標(グローバル座標)に変換している

JavaScript

1 //テトロミノ内部のローカル座標が空(0)の場合、常に隣に移動できるので当たり判定をする必要がなく、以下の判定を飛ばしてtrueを返す 2 //1の時はtrueなので当たり判定をする 3 if( tetro[y][x]){ 4 //テトロミノ内部の各座標が移動する先の座標が1の場合trueならfalseを返す 5 //すなわち移動先にフィールド内の障害物がある場合、falseを返す 6 //下4つの条件は移動先座標がフィールドの外に出る場合、falseを返す 7 if( field[ny][nx] || 8 ny < 0 || 9 nx < 0 || 10 ny >= FIELD_ROW|| 11 nx >= FIELD_COL ){ 12 return false; 13 } 14 }

checkMove関数は、移動する先の座標に障害物がある場合、または、外にはみ出る場合にfalseを返し、それ以外はtrueを返します。

そしてonkeydownイベントのところで、trueの時は座標の変更をしています。

投稿2022/03/13 05:06

gas.engine

総合スコア608

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

teles

2022/03/16 01:23

ようやく理解できました。 丁寧な解説ありがとうございました! 知らないことばかりですが、これからも頑張って勉強していこうと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問