「番兵を置く」
さて、フィールドを実装してみましょう。フィールドを実装したソースコードは以下になります。別ウィンドウでファイルを開いておくと、説明が分かりやすいでしょう。
- DoJa:TemplateAppli.java
- MIDP:TemplateMIDlet.java
縦20行×横10列なので、フィールドの上下左右に外枠を用意して、22行×12列と定義します。このような配列の終わりに(今回は先頭にも)それと分かるデータを配置することを「番兵を置く」といいます。番兵があると、処理が簡潔になります。
フィールドはFIELD_WIDTHとFIELD_HEIGHTという変数を用いて定義しています。これは、後で変更したくなったときに全体的に変えられるようにしています。従って、フィールドの幅と高さが必要な個所は、すべてこの変数を参照していなければなりません。
initField()はフィールドを初期化するメソッドです。フィールドを表す2次元配列に番兵(-1)をセットして、それ以外を0にセットしています。drawBlocks()はフィールドを描画するメソッドです。フィールドの値が−1なら灰色に、それ以外なら黒で描画しています。それ以外にも画面サイズを計算してできるだけ大きく描画するように計算しています。
先ほどのJavaファイルをダウンロードしてソースコードを差し替えて実行してみてください。
自動落下とスレッドを実装する
フィールドだけ実装したソースコードを実行しても、見た目は何も起こりません。次は動きを与えたいので、仕様の1つである「時間とともにブロックが落ちる」を実装してみましょう。自動落下を実装したソースコードは以下になります。こちらも別ウィンドウでファイルを開いておくと、説明が分かりやすいでしょう。
- DoJa:TemplateAppli.java
- MIDP:TemplateMIDlet.java
ブロックのパターン
まずは、落下するブロックのパターンを定義します。縦横3マスのブロックは、組み合わせとして2パターンしかありません。図3のパターンを3次元配列で表すと、以下のようになります。0と1の並びがそのまま見た目になっています。非常に簡単です。
int[][][] pattern = { { {0, 1, 0}, {0, 1, 0}, {0, 1, 0} }, { {0, 1, 0}, {0, 1, 1}, {0, 0, 0} } };
状態を表す変数「モード」
今回追加したコードに、以下のような行があります。
int mode = 0; // ゲーム内の状態を表すモード(0:落下開始、1:落下中、2:着地)
これはコメントにもあるとおり、ゲーム内の状態を表す変数で、非常に重要な役割を持っています。ゲームだけでなく、それ以外のプログラミングでも、状態を表す変数というのは、時には「フラグ」、時には「ステート」という名前などでも登場します。
今回は3つの状態を用意しています。それぞれの状態がどういう役割であるかを簡単に説明します。
- 落下開始:次のブロックの準備やゲームオーバーの判定を行う
- 落下中:キー入力に応じて落下中のブロックを移動する
- 着地:ブロックが横一列にそろったかどうかを判定する
タイトル画面やゲームオーバー画面を用意するには、この変数に定義を追加して処理を加えればよさそうです。
スレッドをしっかり押さえる
いままでの連載では、スレッドはあまり意識せず使ってきましたが、ここでスレッドについてしっかり説明します。スレッドが把握できれば「ブロックが時間とともに自動的に落ちていく」というのがスレッドを用いて処理すれば簡単に実現できるということが理解できると思います。
スレッドとは「何かをしながら別の何かをすることができるモノ」なのですが、この概念を理解するのがなかなか難しいのです。
あなたはマルチスレッドですか?
人は無意識のうちにいろいろなことを同時に行っています。
同時に行ってはいるものの、完全に同時ではないのも理解できると思います。テレビと雑誌はまったく同時には見られませんし、雑誌を見ながらコーヒーを飲もう手を伸ばすとこぼしてしまうかもしれませんから、そのときはコーヒーの方を見て確認するはずです。雑誌を読むことに100%没頭してしまうと、テレビを見ることもコーヒーを飲むこともできません。
上記はあなたのスレッドスケジューリングを模式図にしたものです。基本的に雑誌を読んでいますが、時々テレビを見たりコーヒーを飲んだりしているようです。
ここで重要なのは、雑誌とテレビを同時に見ているようでも、細かく分解すると、短い周期で交互に見ているということです。
スレッドの主なメソッド
Javaの世界では、上記のスレッドスケジューリングのように自分の処理だけをタイムスライスできるわけではなく、実際にはJavaがシステムとして処理するためのスレッドがあり、そのシステムスレッドが処理を行うための猶予を与えなければなりません。
スレッドは優先度を与えたり、同期したり、待機したり、一時的に休止したり、割り込んだり、一時的に停止したりできます。
現在実行中のスレッドを取得 | currentThread() |
---|---|
優先度の取得・設定 | getPriority()/setPriority(int) |
割り込み | interrupt() |
終了まで待機 | join() |
一時的に停止 | sleep(long) |
一時的に休止 | yield() |
次ページでは、「synchronizedメソッド」「相互排他ロック」「メインループ」について説明し、最後に例外を発生させます。
Copyright © ITmedia, Inc. All Rights Reserved.