広告
広告
↓発売日:2017年04月04日↓
Java 第2版 入門編 ゼロからはじめるプログラミング (プログラミング学習シリーズ) 新品価格 |
今回はブロックを複数表示したいと思います。
前回のように一つ一つに座標を指定していたのでは非常に大変ですよね。
なのでここは2次元配列を使って一気にブロックを初期化、表示したいと思います。
最初にも少し説明しましたがまずはブロックを表示できる位置というのを事前に決めてしまいます。
少しわかりずらいかもしれませんが、こんな感じで先にブロックを表示する為のマス目を設定してそこにブロックを当てはめていくような感じにします。
ではさきほどのマス目に対応する2次元配列を用意します。
マス目は6×6になるので2次元配列も同じように用意します。
private final int block_map[][] = { {0,0,0,0,0,0}, {0,0,0,0,0,0}, {0,0,0,0,0,0}, {0,0,0,0,0,0}, {0,0,0,0,0,0}, {0,0,0,0,0,0} };
そしてこの2次元配列のそれぞれの数字によってブロックを表していきます。
「0」・・・ブロックなし
「1」・・・赤ブロック
「2」・・・緑ブロック
「3」・・・青ブロック
などのようにします。
たとえば
private final int block_map[][] = { {1,0,0,0,0,0}, {0,2,0,0,0,0}, {0,0,3,0,0,0}, {0,0,0,1,0,0}, {0,0,0,0,2,0}, {0,0,0,0,0,3} };
こんな感じで配置すると
このようになります。
広告
では次にこの2次元配列をもとにブロックそれぞれの座標、色、フラグなどを初期化していきます。
事前に前回作ったブロックをこのマス目分36個用意しておきましょう。
class BreakoutThread extends AnimationTimer{ private GraphicsContext gc; private Key key; private Ball ball; private Bar bar; /*ブロックを36個用意する*/ private Blocks blocks[] = new Blocks[Define.MAX_BLOCK]; /*省略*/ }
ではブロックの初期化などを行うクラス「BlockMap」になります。
class BlockMap{ private Blocks blocks[]; private final int block_map[][] = { {1,2,3,1,2,3}, {2,3,1,2,3,1}, {3,1,2,3,1,2}, {1,2,3,1,2,3}, {2,3,1,2,3,1}, {3,1,2,3,1,2} }; BlockMap(Blocks blocks[]){ this.blocks = blocks; } void init(){ int count = 0; for(int i = 0;i < Define.BLOCK_MAP_INDEX_Y;i++){ for(int j = 0;j < Define.BLOCK_MAP_INDEX_X;j++){ if(block_map[i][j] != 0){ blocks[count].set_x(Define.BLOCK_WIDTH * j); blocks[count].set_y(Define.BLOCK_HEIGHT * i); blocks[count].set_flag(true); blocks[count].set_color(block_map[i][j]); } count++; } } } }
ブロック初期化の為の2次元配列と、それを実際のブロックに当てはめていくメソッド「init()」があります。
引数としてさきほど36個用意した「Blocks blocks[]」を受け取ってこちらで初期化していきます。
それではブロックの情報を実際のブロックに当てはめていくメソッド「init()」を見てみましょう!
void init(){ int count = 0; for(int i = 0;i < Define.BLOCK_MAP_INDEX_Y;i++){ for(int j = 0;j < Define.BLOCK_MAP_INDEX_X;j++){ if(block_map[i][j] != 0){ blocks[count].set_x(Define.BLOCK_WIDTH * j); blocks[count].set_y(Define.BLOCK_HEIGHT * i); blocks[count].set_flag(true); blocks[count].set_color(block_map[i][j]); } count++; } } }
「for」ループが2重になっていて慣れないと少しややこしいと思いますので一つ一つ分解して見ていきたいと思います。
for(int i = 0;i < 6;i++){ for(int j = 0;j < 6;j++){ } }
まずは2重の「for」ループでさきほどの2次元配列を調べます。
この時のループが進む時のイメージですが
先に内側のループを進めてから外側のループを一つずつ進めていくようなイメージになります。
private final int block_map[][] = { {1,0,0,0,0,0}, {0,2,0,0,0,0}, {0,0,3,0,0,0}, {0,0,0,1,0,0}, {0,0,0,0,2,0}, {0,0,0,0,0,3} };
たとえばこの2次元配列だったら最初に一番上の横一列
{1,0,0,0,0,0}
ここまで進めます。
ここで内側のループが終わるので、外側のループを一つ進めて
{1,0,0,0,0,0}
{0
2列目に入っていく、そんなイメージになります。
ではそれを踏まえた上で、わかりやすいように座標を割り振るトコロだけを抜き出してあらためて見てみます。
for(int i = 0;i < 6;i++){ for(int j = 0;j < 6;j++){ if(block_map[i][j] != 0){ blocks[count].set_x(50 * j); blocks[count].set_y(10 * i); } count++; } }
なんとなくわかりますでしょうか?
さきほどの動きに従って一つ一つ座標を割り振っていくと・・・、
「blocks[0].x = 0,blocks[0].y = 0」
「blocks[1].x = 50,blocks[1].y = 0」
「blocks[2].x = 100,blocks[2].y = 0」
「blocks[3].x = 150,blocks[3].y = 0」
「blocks[4].x = 200,blocks[4].y = 0」
「blocks[5].x = 250,blocks[5].y = 0」
ここで最初の内側の1ループが終わって外側のループを一つ進めて次のループへと移ります。
「blocks[6].x = 0,blocks[6].y = 10」
「blocks[7].x = 50,blocks[7].y = 10」
・
・
・
こんな感じになるというワケです。
あとはついでにフラグ、色なども割り振っていけば初期化は完了です。
それでは36個全てのブロックを表示していきましょう!
クラス「Blocks」のメソッド「draw()」です。
void draw(GraphicsContext gc){ if(flag){ switch(color){ case 0: break; case 1: gc.setFill(Color.RED); break; case 2: gc.setFill(Color.GREEN); break; case 3: gc.setFill(Color.BLUE); break; } gc.fillRect(Define.X_POSI + x,y,width,height); gc.setStroke(Color.WHITE); gc.strokeRect(Define.X_POSI + x,y,width,height); } }
さきほど割り振った色情報によってブロックを色分けします。
ブロック同士の隙間がほしかったのでついでに「外枠」の部分も描いております。
あとは描画する時に36個分全て描くだけです。
for(int i=0;i<Define.MAX_BLOCK;i++){ blocks[i].draw(gc); }
36個全てのブロックを描きます。
ブロック複数表示!
他のステージ分の初期化はどうするんだ?と思われるかもしれません。
その場合、今回のやり方だとブロック初期化の2次元配列をそれぞれのステージ分用意、つまり3次元にして
private final int block_map[][][] = { { {1,2,3,1,2,3}, {2,3,1,2,3,1}, {3,1,2,3,1,2}, {1,2,3,1,2,3}, {2,3,1,2,3,1}, {3,1,2,3,1,2} }, { {1,1,1,1,1,1}, {2,2,2,2,2,2}, {3,3,3,3,3,3}, {1,1,1,1,1,1}, {2,2,2,2,2,2}, {3,3,3,3,3,3} } };
現在のステージ数を表す変数、たとえば「int stage_num」みたいな感じで用意して初期化部分も少し変更、
void init(){ int count = 0; for(int i = 0;i < Define.BLOCK_MAP_INDEX_Y;i++){ for(int j = 0;j < Define.BLOCK_MAP_INDEX_X;j++){ if(block_map[stage_num][i][j] != 0){ blocks[count].set_x(Define.BLOCK_WIDTH * j); blocks[count].set_y(Define.BLOCK_HEIGHT * i); blocks[count].set_flag(true); blocks[count].set_color(block_map[stage_num][i][j]); } count++; } } }
こうすれば「stage_num」の値を変化させれば、それに合わせてブロックも初期化されるようになります。
ここまでの中間ソースになります。
中間ソースでは前回のブロックひとつだけの当たり判定部分をエラーにならないようにコメントアウトしております。
では次回はブロック全てに当たり判定をつけたいと思います。
広告
↓発売日:2017年04月18日↓
Java本格入門 ~モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで 新品価格 |
↓発売日:2016年06月25日↓
新品価格 |
↓発売日:2016年08月31日↓
新品価格 |
↓発売日:2018年11月21日↓
新品価格 |
↓発売日:2016年12月15日↓
新品価格 |
↓発売日:2016年09月28日↓
新品価格 |