BREW ブロック崩しゲーム 〜 BREW C++ ゲームプログラミング 〜
準備
SophiaFramework AppWizard
最初に、SophiaFramework AppWizard を起動して、必要な設定を行いましょう。設定する項目は、
- BREW SDK 2.1 を使用
- GUI フレームワークは使用しない
- 次のイベント ハンドラを生成 :
- SFEVT_APP_START
- SFEVT_APP_RESUME
- SFEVT_APP_SUSPEND
- SFEVT_KEY
です。他の設定はデフォルトのままで構いません。
メンバ変数の追加
今回の場合、「ブロック崩しのためのクラスを作っておいて後でそれを再利用する」といったことはまず考えられませんよね?
そこで今回、設計をオブジェクト指向にするのは止めて、寧ろ C 言語風にしてみました。ただし衝突判定処理はクラスにした方が綺麗だったので、そこはオブジェクト指向になっています。
では、ウィザードが生成したアプリケーションクラス “Block” に、必要な変数の定義を追加して行きましょう。
最初はボールやラケット、ブロックの情報を格納するための構造体を定義します。具体的には、Block.hpp の先頭付近に次のように記述します。
- Block.hpp - ... // ボールに関するデータを保持する構造体 SFMTYPEDEFSTRUCT(BallData) struct BallData { SFXCircle ball; // ボールそのもの SFXRGBColor color; // 色情報 SFXGrid velocity; // 速度 }; // ラケットに関するデータを保持する構造体 SFMTYPEDEFSTRUCT(RacketData) struct RacketData { SFXRectangle racket; // ラケットそのもの SFXRGBColor color; // 色情報 SFXGrid velocity; // 速度 }; // ブロックに関するデータを保持する構造体 SFMTYPEDEFSTRUCT(BlockData) struct BlockData { UInt16 type; // ブロックのタイプ SInt16 life; // ブロックの寿命(後何回衝突に耐えられる?) SInt16 score; // スコア SFXRectangle block; // ブロックそのもの SFXRGBColor color; // 色情報 }; ...
そして、ゲーム進行に必要な変数を Block クラスの private なメンバ変数として定義します。
- Block.hpp - ... SFMTYPEDEFCLASS(Block) class Block : public SFCApplication { ... private: ... // ブロック崩しのための変数たち SFXGraphicsPtr _pgraphics; // グラフィック・インターフェース SFXRectangle _gameArea; // プレー領域 SFXRectangle _messageArea; // 得点類表示領域 SFXRectangle _basicBlock; // このブロックが基準となる。 //他はこれをコピー BallData _usingBall; // プレーに使っているボール Bool _ballPassing; // ボールがブロック中を通過中? BallData _spareBalls[SPARE_BALLS]; // 予備のボール RacketData _racket; // ラケット BlockData _blocks[BLOCK_H_NUM * BLOCK_V_NUM]; // ブロック SInt32 _score; // スコア SInt16 _spareBallNumber; // 予備のボールの数 SInt16 _blockNumber; // 残りのブロックの数 Bool _blockMotion; // ブロックが動くステージ? SInt16 _nowStage; // 現在のステージ SInt32 _drawInterval; // 画面更新間隔(msec単位) SInt16 _ballYSpeed; // ボールのy方向の速さ //(1フレーム当たり何ドット?) SInt16 _racketSpeed; // ラケットの速さ //(フレーム当たり何ドット?) UInt16 _status; // 現在のアプリケーションの状態 ...
メンバ関数の追加
続いて、ゲーム進行に必要な関数を定義します。これらの関数については外部から呼び出されることはありませんので、すべて private として定義します。
ただしタイマー関連で使用するコールバック関数については、メンバ関数ではない通常の関数として定義します。
- Block.hpp - ... SFMTYPEDEFCLASS(Block) class Block : public SFCApplication { ... private: ... // ブロック崩しのためだけの関数たち Void Initialize(Void); // 基本的な初期化関数 Void DrawBlock(SInt16 n = -1, Bool flag = true); // n番目のブロックを描画 //(flag = falseは消去) Void DrawRacket(Bool flag = true); // ラケット描画(flag = falseは消去) Void DrawBall(Bool flag = true); // ボールの描画(flag = falseは消去) Void DrawMessage(SFXWideStringConstRef msg); // メッセージを表示(Msg、予備のボールの数) Void DrawMessage(Void); // メッセージを表示(スコア、予備のボールの数) Void CreateStage(SInt16 n); // ステージnを生成 UInt16 CheckEnd(Void); // ステージ終了? Void ShowGameOver(Void); // ゲーム・オーバーを通知 Void ShowGameClear(Void); // ゲームをクリアしたことを通知 }; Void CBMoveBlocks(VoidPtr pdata); // ブロック全体を移動(タイマー登録用) Void CBAnimate(VoidPtr pdata); // 衝突判定とアニメーション(タイマー登録用) ...
パラメータの定義
ボールの色や速さといった変更される可能性が高い定数は、保守のことを考えて、Parameters.hpp というヘッダー ファイルにまとめます。
- Parameters.hpp - #ifndef __PARAMETERS_HPP #define __PARAMETERS_HPP // 様々なパラメータの定義 // 背景は黒 #define BGCOLOR SFXRGBColor(0, 0, 0, 0) // ボールは白 #define BALL_COLOR SFXRGBColor(255, 255, 255, 0) // ラケットは赤 #define RACKET_COLOR SFXRGBColor(255, 0, 0, 0) // メッセージの色は白 #define MESSAGE_COLOR SFXRGBColor(255, 255, 255, 0) // 水平方向のブロックの最大数 #define BLOCK_H_NUM 5 // 垂直方向のブロックの最大数 #define BLOCK_V_NUM 6 // 予備のボールの数 #define SPARE_BALLS 2 // ブロックの幅に対するラケットのそれ(分子) #define RACKET_WIDTH2BLOCK_NUM 3 // ブロックの幅に対するラケットのそれ(分母) #define RACKET_WIDTH2BLOCK_DEN 4 // ブロックの高さに対するラケットのそれ(分子) #define RACKET_HEIGHT2BLOCK_NUM 1 // ブロックの高さに対するラケットのそれ(分母) #define RACKET_HEIGHT2BLOCK_DEN 2 // ボールの速さに対するラケットの速さ(分子) #define RACKET_SPEED2BALL_NUM 16 // ボールの速さに対するラケットの速さ(分母) #define RACKET_SPEED2BALL_DEN 10 // ラケットの角の円の直径 #define RACKET_CORNER 4 // ボールがy方向を通過しきるのにかかる時間(msec単位) #define TRAVEL_TIME 1400 // 1秒間の描画回数 #define DRAW_RATE 50 // ブロックが移動を開始するまでの時間(msec単位) #define BLOCK_MOVEMENT_TIME 10000 // ブロック全体の移動間隔(msec単位) #define BLOCK_MOVEMENT_INTERVAL 4000 // ブロックなし #define BLOCK_TYPE_NONE 0 // 通常のブロック #define BLOCK_TYPE_NORMAL 1 // 見えないブロック #define BLOCK_TYPE_INVISIBLE 2 // 何もしていない状態 #define APP_STATUS_NOTHING 0 // ゲーム中 #define APP_STATUS_PLAYING 1 // ユーザー待ち(ゲーム開始時) #define APP_STATUS_READY 2 // ユーザー待ち(再始動) #define APP_STATUS_WAIT_RESTART 3 // ステージ続行 #define STAGE_END_CONTINUE 0 // ミスにより終了 #define STAGE_END_MISS 1 // ステージクリア(攻略) #define STAGE_END_CLEAR 2 // ステージ数 #define MAX_STAGE 4 #endif
ある定数の、別の定数に対する比が分子と分母とに分けて定義してありますが、これは ARM プロセッサでは浮動小数点計算が極端に遅くなるということを考慮した結果です。整数であっても他の四則演算に比べて除算は遅いですが、それでも浮動小数点演算に比べれば格段に早いので、浮動小数点演算は出来る限り整数の演算に置き換えるように心掛けましょう。