フィールドをつくる
今回はC#でブロック崩しをつくります。まずはフィールドをつくりましょう。
フィールドの幅と高さは450×450とします。
1 2 3 4 5 |
public partial class Form1 : Form { const int FIELD_WIDTH = 450; const int FIELD_HEIGHT = 450; } |
フィールドを描画するにはForm.OnPaintをオーバーライドしてそこでおこないます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); BackColor = Color.Black; // 背景は黒 this.DoubleBuffered = true; } protected override void OnPaint(PaintEventArgs e) { DrawField(e.Graphics); base.OnPaint(e); } } |
DrawFieldメソッドは以下のようなものです。
1 2 3 4 5 6 7 8 9 10 11 |
public partial class Form1 : Form { const int FIELD_POSITION_X = 10; const int FIELD_POSITION_Y = 10; void DrawField(Graphics g) { Rectangle rect = new Rectangle(FIELD_POSITION_X, FIELD_POSITION_Y, FIELD_WIDTH, FIELD_HEIGHT); g.DrawRectangle(new Pen(Color.White), rect); // フィールドの境界線は白 } } |
ブロックを描画する
ブロックは15列で8行とします。また同じ色ではなく複数色のブロックをつくります。ブロックはDrawBlocksメソッドで描画します。
そのまえにブロックが存在するのかどうかを管理するための配列をつくります。そしてゲームが開始されたときであればすべてのブロックは壊されていない状態なのでClearAllBreakedメソッドですべてfalseにします(あとで気がついたけど isBreakedはis + breakの過去分詞型のつもりだったけれども実はbrokenだった)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class Form1 : Form { const int BLOCK_COLUM_COUNT = 15; const int BLOCK_ROW_COUNT = 8; bool[,] isBreaked = new bool[BLOCK_ROW_COUNT, BLOCK_COLUM_COUNT]; // コンストラクタ内とゲームを開始するメニューが選択されたときに実行する void ClearAllBreaked() { for(int y = 0; y < BLOCK_ROW_COUNT; y++) { for(int x = 0; x < BLOCK_COLUM_COUNT; x++) isBreaked[y, x] = false; } } } |
描画処理部分です。現状、フィールドとブロックしかつくっていないのでこれだけです。
1 2 3 4 5 6 7 8 9 10 |
public partial class Form1 : Form { protected override void OnPaint(PaintEventArgs e) { DrawField(e.Graphics); DrawBlocks(e.Graphics); base.OnPaint(e); } } |
DrawBlocksメソッドは壊されていないブロックを調べて、それを描画するためのDrawBlockメソッドを呼び出します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public partial class Form1 : Form { void DrawBlocks(Graphics g) { for(int y = 0; y< BLOCK_ROW_COUNT; y++) { Color color = Color.Empty; if(y == 0 || y == 1) color = Color.Red; if(y == 2 || y == 3) color = Color.Orange; if(y == 4 || y == 5) color = Color.Green; if(y == 6 || y == 7) color = Color.Yellow; for(int x = 0; x < BLOCK_COLUM_COUNT; x++) { if(!isBreaked[y, x]) DrawBlock(g, x, y, color); } } } void DrawBlock(Graphics g, int colum, int row, Color color) { Rectangle rect = GetBlockRect(colum, row); SolidBrush brush = new SolidBrush(color); g.FillRectangle(brush, rect); g.DrawRectangle(new Pen(Color.Black), rect); } Rectangle GetBlockRect(int colum, int row) { Rectangle rect = new Rectangle( new Point(colum * BLOCK_WIDTH + FIELD_POSITION_X, row * BLOCK_HEIGHT + FIELD_POSITION_Y + 20), new Size(BLOCK_WIDTH, BLOCK_HEIGHT) ); return rect; } } |
GetBlockRectメソッドは ブロックの場所(colum,row)を指定してブロックが描画されるべき矩形を返します。ブロックの幅はフィールドの幅と横にならべるブロックの数から求めることができます。このときFIELD_WIDTH / BLOCK_COLUM_COUNTが割り切れないとフィールドの右側に空間ができてしまいかっこ悪くなってしまいます。
1 2 3 4 5 |
public partial class Form1 : Form { const int BLOCK_WIDTH = FIELD_WIDTH / BLOCK_COLUM_COUNT; const int BLOCK_HEIGHT = 10; } |
それから二元配列isBreakedはブロックがすでに壊されているかどうかの情報を管理するためのものです。壊されているブロックであれば表示してはならないし、存在するものとして扱ってはなりません。
最初はすべてのブロックが存在するわけですからゲーム開始時(ゲームオーバーになってもう一度プレイするとき)にはisBreakedはすべてクリアする必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class Form1 : Form { void GameStart() { ClearAllBreaked(); } void ClearAllBreaked() { for(int y = 0; y < BLOCK_ROW_COUNT; y++) { for(int x = 0; x < BLOCK_COLUM_COUNT; x++) isBreaked[y, x] = false; } } } |
バー(パドル)を表示する
ブロック崩しでボールを跳ね返すためのものです。パドルというらしいですが・・・。
バーはDrawBarメソッドで表示します。表示させる場所はフィールド変数barPosで管理します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public partial class Form1 : Form { const int BAR_WIDTH = 50; const int BAR_HEIGHT = 15; int barPosX = FIELD_POSITION_X; int barPosY = FIELD_POSITION_Y + FIELD_HEIGHT - 50; protected override void OnPaint(PaintEventArgs e) { DrawBar(e.Graphics); DrawBlocks(e.Graphics); DrawField(e.Graphics); base.OnPaint(e); } void DrawBar(Graphics g) { Point barPos = new Point(barPosX, barPosY); Size size = new Size(BAR_WIDTH, BAR_HEIGHT); SolidBrush brush = new SolidBrush(Color.Black); Rectangle rect = new Rectangle(barPos, size); g.FillRectangle(brush, rect); } } |
バーは最初は真ん中に
バーはゲーム開始時は真ん中にあったほうがいいですね。
1 2 3 4 5 6 7 8 |
public partial class Form1 : Form { void GameStart() { ClearAllBreaked(); barPosX = (FIELD_WIDTH - BAR_WIDTH) / 2; } } |
あとはボールの動きとブロックが壊れる動作を実装すれば大部分は完成です。
こんにちは。
いきなりの質問しつれいします。
このisBreakedはどこで定義していますか?
記述忘れでした。記事を修正したので確認してください。