ピンポンゲームダブルスクリーンver(簡易版)。(2)
RGKT-NDS-HMBR-005_2(002)
こちらもソース公開いたします。
シングル版と足踏み合わせてたため公開まで時間が出来てしまいましたが
そのお陰で、シングル版もわりとまとまったものが書けたように思えます。
シングル版との違いは
コンソールを2画面分利用するため
consoleInit() 関数を使いコンソールを初期化、その返値を PrintConsole 構造体にて持ち、
コンソール上下を区別してます。
consoleDemoInit() 内部で自動設定されてた
画面モード、VRAM 設定は consoleInit() では設定されないので
これも自分で設定してます(videoSetMode(), videoSetModeSub(), vramSetBankA(), vramSetBankC())。
ボール描画だけは上下2画面を縦 00-47 として内部で解釈させるようにして
上下画面それぞれに描画するときはじめて
本来のDSの画面縦タイルサイズ(00-23)に丸め処理を行ってます。
他は、描画する画面指定から各シーンを描画させてます(consoleSelect())。
それ以外はシングル版とほぼ同じです。同じになるようにしました。
アルゴリズム(というか、ブロック崩しや PONG のボール跳ね返り処理)を知りたいなら
シングル版の方が、このダブル版よりも余計なことしてなくて分かりやすいと思いますので
シングル版の方を参考にされると良いです。
ピンポンゲームダブルスクリーンver(簡易版)ソースコード
main.h
// TODO: ここに一意の識別子を定義する(重複インクルード防止用)。 #ifndef _MAIN_H_ #define _MAIN_H_ // TODO: ここに、このヘッダファイルが必要とする外部ヘッダファイルを記述する。 #include <nds.h> #ifdef __cplusplus extern "C" { #endif // TODO: ここに #define 定義、ならびに関数のプロトタイプ宣言を追加する。 //シーン定数 typedef enum{ SCENE_TITLE, SCENE_GAME }SCENE_SEQ; //シーン遷移フラグ用構造体 typedef struct{ u16 act; }ST_SCENE; #ifdef __cplusplus } #endif #endif
main.c
// root //--------------------------------------------------------------------------------- #include <stdio.h> #include "main.h" #include "title.h" #include "game.h" #include "gamePlay.h" //--------------------------------------------------------------------------------- // シーン遷移フラグ static ST_SCENE scene = {SCENE_TITLE}; //--------------------------------------------------------------------------------- void initMain(void); void checkScene(void); //--------------------------------------------------------------------------------- int main(void) { initMain(); while(1) { scanKeys(); // シーケンス遷移動作 switch(scene.act){ case SCENE_TITLE: updateTitle(); break; case SCENE_GAME: updateGame(); break; default: break; } // 遷移トリガチェック checkScene(); swiWaitForVBlank(); } return 0; } //--------------------------------------------------------------------------------- void initMain(void) { // TODO: ここに 初期化処理を追加する。 // 上下画面コンソールの初期化。 videoSetMode(MODE_0_2D); videoSetModeSub(MODE_0_2D); vramSetBankA(VRAM_A_MAIN_BG); vramSetBankC(VRAM_C_SUB_BG); top_screen = *consoleInit(0, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, true); bottom_screen = *consoleInit(0, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, false); } //--------------------------------------------------------------------------------- // シーン遷移トリガ関数 void checkScene(void) { switch(scene.act){ case SCENE_TITLE: if(isExitTitle()) scene.act = SCENE_GAME; break; case SCENE_GAME: if(isExitGame()) scene.act = SCENE_TITLE; break; default: break; } } //---------------------------------------------------------------------------------
title.h
// TODO: ここに一意の識別子を定義する(重複インクルード防止用)。 #ifndef _TITLE_H_ #define _TITLE_H_ // TODO: ここに、このヘッダファイルが必要とする外部ヘッダファイルを記述する。 #include <nds.h> #ifdef __cplusplus extern "C" { #endif // TODO: ここに #define 定義、ならびに関数のプロトタイプ宣言を追加する。 //シーン定数 typedef enum{ TITLE_INIT, TITLE_EXIT }TITLE_SEQ; //シーン遷移フラグ用構造体 typedef struct{ u16 act; }ST_TITLE; //グローバル関数(シーン更新・シーン終了確認用)、プロトタイプ宣言 void updateTitle(void); bool isExitTitle(void); #ifdef __cplusplus } #endif #endif
title.c
// SCENE_TITLE //--------------------------------------------------------------------------------- #include <stdio.h> #include "title.h" #include "gamePlay.h" //--------------------------------------------------------------------------------- // シーン遷移フラグ static ST_TITLE title = {TITLE_INIT}; //--------------------------------------------------------------------------------- static void initTitle(void); static void exitTitle(void); //--------------------------------------------------------------------------------- // シーン更新関数 void updateTitle(void) { switch(title.act){ case TITLE_INIT: initTitle(); break; case TITLE_EXIT: exitTitle(); break; default: break; } } //--------------------------------------------------------------------------------- static void initTitle(void) { // TODO: ここに 初期化処理を追加する。 // コンソールクリア consoleSelect(&top_screen); consoleClear(); consoleSelect(&bottom_screen); consoleClear(); // タイトルの表示 consoleSelect(&top_screen); iprintf("\x1b[7;7HP i n g P o n g"); iprintf("\x1b[8;3HD o u b l e S c r e e n"); // ハイスコアの表示 iprintf("\x1b[14;9HHigh Score:%d", high_score); // コピーライトの表示 iprintf("\x1b[20;7H(C)2009 REGEKATSU"); iprintf("\x1b[21;9HNDS-HMBR-005_2"); // タイトルシーンを終了し、ゲームコンフィグシーンへ遷移する。 title.act = TITLE_EXIT; } //--------------------------------------------------------------------------------- static void exitTitle(void) { title.act = TITLE_INIT; } //--------------------------------------------------------------------------------- // シーン終了確認関数 bool isExitTitle(void) { return (title.act == TITLE_INIT) ? true : false; } //---------------------------------------------------------------------------------
game.h
// TODO: ここに一意の識別子を定義する(重複インクルード防止用)。 #ifndef _GAME_H_ #define _GAME_H_ // TODO: ここに、このヘッダファイルが必要とする外部ヘッダファイルを記述する。 #include <nds.h> #ifdef __cplusplus extern "C" { #endif // TODO: ここに #define 定義、ならびに関数のプロトタイプ宣言を追加する。 //シーン定数 typedef enum{ GAME_INIT, GAME_CONFIG, GAME_PLAY, GAME_EXIT }GAME_SEQ; //シーン遷移フラグ用構造体 typedef struct{ u16 act; }ST_GAME; //グローバル関数(シーン更新・シーン終了確認用)、プロトタイプ宣言 void updateGame(void); bool isExitGame(void); #ifdef __cplusplus } #endif #endif
game.c
// SCENE_GAME //--------------------------------------------------------------------------------- #include <stdio.h> #include "game.h" #include "gamePlay.h" #include "gameConfig.h" //--------------------------------------------------------------------------------- // シーン遷移フラグ static ST_GAME game = {GAME_INIT}; //--------------------------------------------------------------------------------- static void initGame(void); static void exitGame(void); static void checkSceneGame(void); //--------------------------------------------------------------------------------- // シーン更新関数 void updateGame(void) { switch(game.act){ case GAME_INIT: initGame(); break; case GAME_CONFIG: updateGameConfig(); checkSceneGame(); break; case GAME_PLAY: updateGamePlay(); checkSceneGame(); break; case GAME_EXIT: exitGame(); break; default: break; } } //--------------------------------------------------------------------------------- static void initGame(void) { // TODO: ここに 初期化処理を追加する。 game.act = GAME_CONFIG; } //--------------------------------------------------------------------------------- static void exitGame(void) { game.act = GAME_INIT; } //--------------------------------------------------------------------------------- // シーン遷移トリガ関数 // タイトルシーンより遷移してくる。 // 最初にゲームコンフィグシーンに遷移。 // ゲームコンフィグシーンが終了したら // ゲームプレイシーンに遷移する。 // ゲームプレイシーンが終了したら、 // ゲームシーンを抜けて、タイトルシーンへ遷移する。 static void checkSceneGame(void) { switch(game.act){ case GAME_INIT: break; case GAME_CONFIG: if(isExitGameConfig()) game.act = GAME_PLAY; break; case GAME_PLAY: if(isExitGamePlay()) game.act = GAME_EXIT; break; case GAME_EXIT: break; default: break; } } //--------------------------------------------------------------------------------- // シーン終了確認関数 bool isExitGame(void) { return (game.act == GAME_INIT) ? true : false; } //---------------------------------------------------------------------------------
gamePlay.h
// TODO: ここに一意の識別子を定義する(重複インクルード防止用)。 #ifndef _GAME_PLAY_H_ #define _GAME_PLAY_H_ // TODO: ここに、このヘッダファイルが必要とする外部ヘッダファイルを記述する。 #include <nds.h> #ifdef __cplusplus extern "C" { #endif // TODO: ここに #define 定義、ならびに関数のプロトタイプ宣言を追加する。 //シーン定数 typedef enum{ GAME_PLAY_INIT, GAME_PLAY_MAIN_INIT, GAME_PLAY_MAIN_EXEC, GAME_PLAY_MAIN_MISS, GAME_PLAY_MAIN_END, GAME_PLAY_EXIT }GAME_PLAY_SEQ; //ゲームレベル定義 typedef enum{ LEVEL_EASY, LEVEL_NORMAL, LEVEL_HARD }LEVEL_STATUS; //シーン遷移用、構造体変数 typedef struct{ u16 act; }ST_GAME_PLAY; //外部公開用変数 extern PrintConsole top_screen; extern PrintConsole bottom_screen; extern int high_score; extern LEVEL_STATUS game_level; //外部公開用関数、プロトタイプ宣言 void updateGamePlay(void); bool isExitGamePlay(void); void setGameLevel(void); #ifdef __cplusplus } #endif #endif
gamePlay.c
// SCENE_GAME_PLAY //--------------------------------------------------------------------------------- #include <stdio.h> #include "gamePlay.h" //--------------------------------------------------------------------------------- // ゲーム画面内の移動・描画の為の定義 typedef enum{ CONSOLE_WIDTH_MIN = 0, CONSOLE_WIDTH_MAX = 31, CONSOLE_HEIGHT_MIN = 0, CONSOLE_HEIGHT_MAX = 23 }CONSOLE_SCREEN_SIZE; // 上下画面描画の為の定数・マクロ定義 typedef enum{ CONSOLE_SCREEN_TOP = 0, CONSOLE_SCREEN_BOTTOM = 24 }CONSOLE_SCREEN_SELECT; #define ROUND_SCREEN_TOP(x) ((x)-0) #define ROUND_SCREEN_BOTTOM(x) ((x)-24) // パドル動作・描画の為の定義 typedef enum{ PADDLE_WIDTH_SIZE = 3, PADDLE_HEIGHT_SIZE = 1, PADDLE_WIDTH_POS = 15, PADDLE_HEIGHT_POS = 21 }PADDLE_STATUS; // ボール動作・描画の為の定義 typedef enum{ BALL_WIDTH_SIZE = 1, BALL_HEIGHT_SIZE = 1, BALL_WIDTH_POS = 5, BALL_HEIGHT_POS = 5, BALL_WIDTH_DIR = 1, BALL_HEIGHT_DIR = 1 }BALL_STATUS; // ゲーム用、デフォルト値 #define DEFAULT_BALL_NUM 3 #define DEFAULT_SCORE_NUM 0 // ゲーム用、キャラクタ描画パラメータ typedef enum{ DRAW_HIDE, DRAW_SHOW }DRAW_PARAM; // ゲーム速度設定用マクロ // ゲームレベルの低いほどゲーム速度は遅く、高いほどゲーム速度は速くなる。 #define SET_WAIT_LEVEL(x) (3-(x)) //--------------------------------------------------------------------------------- // シーン遷移フラグ static ST_GAME_PLAY game_play = {GAME_PLAY_INIT}; //--------------------------------------------------------------------------------- // ゲーム構造体、メンバー変数定義 typedef struct{ int px; // パドルX座標 int py; // パドルY座標 int bx; // ボールX座標 int by; // ボールY座標 int dx; // ボールX移動方向 int dy; // ボールY移動方向 }GAME_STATUS; static GAME_STATUS game_stat = {0}; // ゲームプレイステータス int ball_num, // 持ちボール数 score, // スコア high_score = DEFAULT_SCORE_NUM; // ハイスコア LEVEL_STATUS game_level = LEVEL_EASY; // ゲームレベル PrintConsole top_screen; // 上画面コンソール設定情報 PrintConsole bottom_screen; // 下画面コンソール設定情報 //--------------------------------------------------------------------------------- // ゲームプレイ用、シーン遷移関数 static void initGamePlay(void); static void initGamePlayMain(void); static void execGamePlayMain(void); static void missGamePlayMain(void); static void endGamePlayMain(void); static void exitGamePlay(void); // ゲームプレイ用、動作別更新関数 static void updatePaddle(void); static void updateBall(void); static void updateStatus(void); // ゲームプレイ用、キャラクタ描画関数 static void drawPaddle(DRAW_PARAM); static void drawBall(DRAW_PARAM); // ゲームプレイ用、トリガチェック関数 static bool isUpdateBall(void); static bool isMissGamePlayMain(void); static bool isEndGamePlayMain(void); // ゲームプレイ用、状態ウェイト関数 static void setWaitForVBlank(u32); //--------------------------------------------------------------------------------- // シーン更新関数 void updateGamePlay(void) { swiWaitForVBlank(); scanKeys(); switch(game_play.act){ case GAME_PLAY_INIT: initGamePlay(); break; case GAME_PLAY_MAIN_INIT: initGamePlayMain(); break; case GAME_PLAY_MAIN_EXEC: execGamePlayMain(); break; case GAME_PLAY_MAIN_MISS: missGamePlayMain(); break; case GAME_PLAY_MAIN_END: endGamePlayMain(); break; case GAME_PLAY_EXIT: exitGamePlay(); break; default: break; } } //--------------------------------------------------------------------------------- static void initGamePlay(void) { ball_num = DEFAULT_BALL_NUM; score = DEFAULT_SCORE_NUM; // 上下画面のコンソールをクリアする。 consoleSelect(&top_screen); consoleClear(); consoleSelect(&bottom_screen); consoleClear(); game_play.act = GAME_PLAY_MAIN_INIT; } //--------------------------------------------------------------------------------- static void initGamePlayMain(void) { game_stat.px = PADDLE_WIDTH_POS; game_stat.py = PADDLE_HEIGHT_POS + CONSOLE_SCREEN_BOTTOM; game_stat.bx = BALL_WIDTH_POS; game_stat.by = BALL_HEIGHT_POS + CONSOLE_SCREEN_TOP; game_stat.dx = BALL_WIDTH_DIR; game_stat.dy = BALL_HEIGHT_DIR; // ゲーム画面のクリアを行う。ゲームミス後の再ゲームスタート等に必要。 // 上下画面のコンソールをクリアする(ダブル版)。 // //(表示は全て下に集約されてるので(スコア等)、 // 現状ボールクリア以外で上画面をクリアする必要はないが一応。) consoleSelect(&top_screen); consoleClear(); consoleSelect(&bottom_screen); consoleClear(); game_play.act = GAME_PLAY_MAIN_EXEC; } //--------------------------------------------------------------------------------- static void execGamePlayMain(void) { // プレイヤ移動動作の更新を行う。 updatePaddle(); // ボール移動動作の更新を行う。 // キー入力受付を2回するうちボール更新を1回までとする。 if(isUpdateBall()) updateBall(); // ゲーム情報(スコア、残機数)の更新・表示を行う。 updateStatus(); // ゲームミスの確認。ミスしていれば状態遷移を行う。 if(isMissGamePlayMain()) game_play.act = GAME_PLAY_MAIN_MISS; // ゲームレベルに応じてウエイトを設ける // ここの数値が低い程、ゲーム速度が速くなる(ゲーム難易度が上がる)。 setWaitForVBlank(SET_WAIT_LEVEL(game_level)); } //--------------------------------------------------------------------------------- static void missGamePlayMain(void) { // 画面に「ミス」のメッセージを割り込ませるかたちで表示する。 // 下画面へ描画する(ダブル版)。 consoleSelect(&bottom_screen); iprintf("\x1b[11;14Hmiss"); // ボール残数を減らす。 ball_num--; // 1秒間のウェイトを設ける。 setWaitForVBlank(60); // ボール残数が無くなったらゲームオーバーへ遷移する。 if(isEndGamePlayMain()) game_play.act = GAME_PLAY_MAIN_END; // ボール残数が有るならゲームを再スタートへ遷移する。 else game_play.act = GAME_PLAY_MAIN_INIT; } //--------------------------------------------------------------------------------- static void endGamePlayMain(void) { // 画面をクリアして、「ゲームオーバー」のメッセージを表示する。 // 下画面へ描画する(ダブル版)。 consoleSelect(&bottom_screen); consoleClear(); iprintf("\x1b[11;10HGame Over!!"); // 3秒間のウェイトを設ける。 setWaitForVBlank(180); // 状態遷移。ゲームプレイシーン終了へ遷移。 game_play.act = GAME_PLAY_EXIT; } //--------------------------------------------------------------------------------- static void exitGamePlay(void) { game_play.act = GAME_PLAY_INIT; } //--------------------------------------------------------------------------------- static void updatePaddle(void) { // パドル動作の更新 // 前回のパドル画像を消去する。 // 下画面をクリアする(ダブル版)。 drawPaddle(DRAW_HIDE); // 現在のパドル位置を取得・更新する。 if(keysHeld() & KEY_LEFT){ if(game_stat.px > CONSOLE_WIDTH_MIN) game_stat.px--; } if(keysHeld() &KEY_RIGHT){ if(game_stat.px <= CONSOLE_WIDTH_MAX - PADDLE_WIDTH_SIZE) game_stat.px++; } // 現在のパドル画像を描画する。 // 下画面をクリアする(ダブル版)。 drawPaddle(DRAW_SHOW); } //--------------------------------------------------------------------------------- static void updateBall(void) { // ボール移動方向 // ボール情報の取得と描画。 // ボールY座標(game_stat.by) のみ、 // 00-47 の範囲で値を持つものとして考える // (2画面分の座標範囲を1画面と仮定して計算する)。 // ・ボールY座標 00-23 上画面 // ・ボールY座標 24-47 下画面 // // 描画時、そのままの値では以下の問題が発生する。 // ・00-23 までの値が上下画面どちらの値か明快でない // ・24-47 までの値がオーバーフローしてて正しく描画できない // なので描画時には、Y座標値を本来の 00-23 の範囲内に丸めた値で // ボールY座標値で描画を指定しなければならない。 // // Y座標値の値丸め処理は、以下の関数マクロを使うことで可能である。 // ・ROUND_SCREEN_BOTTOM(game_stat.by) − 下画面へ描画する為の丸め動作 // ・ROUND_SCREEN_TOP(game_stat.by) − 上画面へ描画する為の丸め動作 // // ボールが画面左端の場合、移動方向を右へ変更する。 // 上下画面共用。 if(game_stat.bx <= CONSOLE_WIDTH_MIN){ game_stat.dx = -game_stat.dx; } // ボールが画面右端の場合、移動方向を左へ変更する。 // 上下画面共用。 if(game_stat.bx >= CONSOLE_WIDTH_MAX){ game_stat.dx = -game_stat.dx; } // ボールが画面上端の場合、移動方向を下へ変更する。 // 上画面として処理する(ダブル版)。 if(game_stat.by <= CONSOLE_HEIGHT_MIN + CONSOLE_SCREEN_TOP){ game_stat.dy = -game_stat.dy; } // ボールが画面下端の場合、移動方向を上へ変更する。(デバッグ用) // 下画面として処理する(ダブル版)。 /* if(game_stat.by >= CONSOLE_HEIGHT_MAX + CONSOLE_SCREEN_BOTTOM){ game_stat.dy = -game_stat.dy; } */ // ボールがパドルに当たってるかを確認する。 // 下画面として処理する(ダブル版)。 if((ROUND_SCREEN_BOTTOM(game_stat.by) == (ROUND_SCREEN_BOTTOM(game_stat.py) - 1))){ if((game_stat.bx >= game_stat.px - 1) && (game_stat.bx <= game_stat.px + PADDLE_WIDTH_SIZE)){ game_stat.dy = -game_stat.dy; // ボールを跳ね返したらスコアを更新する。 score++; // 現在のスコアがハイスコアを越えてたらハイスコアを更新する。 if(score > high_score) high_score = score; } } // 前回のボール画像を消去する。 // 上下画面どちらか、ボール画像をクリアする(ダブル版)。 drawBall(DRAW_HIDE); // ボール座標を移動方向へ進める。 game_stat.bx += game_stat.dx; game_stat.by += game_stat.dy; // 現在のボール画像を描画する。 // 上下画面どちらか、ボール画像を描画する(ダブル版)。 drawBall(DRAW_SHOW); } //--------------------------------------------------------------------------------- static void updateStatus(void) { // 下画面へ描画する(ダブル版)。 consoleSelect(&bottom_screen); iprintf("\x1b[23;0Hball:%d score:%d", ball_num , score); } //--------------------------------------------------------------------------------- static void drawPaddle(DRAW_PARAM param) { char str[] = " "; switch(param){ case DRAW_HIDE: break; case DRAW_SHOW: sprintf(str, "---"); break; default: break; } // 下画面へ描画する(ダブル版)。 consoleSelect(&bottom_screen); iprintf("\x1b[%d;%dH%s", ROUND_SCREEN_BOTTOM(game_stat.py), game_stat.px, str); } //--------------------------------------------------------------------------------- static void drawBall(DRAW_PARAM param) { char c; c = (param == DRAW_SHOW) ? 'O' : ' '; // ダブル版、ボール描画処理。 // 計算用の 00-47 までの仮座標値を上下画面それぞれの 本来の座標値へと変換する。 // ボールY座標 が 00-23 の場合。上画面へ新たにボール画像を描画する。 if(game_stat.by < CONSOLE_SCREEN_BOTTOM){ consoleSelect(&top_screen); iprintf("\x1b[%d;%dH%c", ROUND_SCREEN_TOP(game_stat.by), game_stat.bx, c); // ボールY座標 が 24-47 の場合。下画面へ新たにボール画像を描画する。 }else if(game_stat.by >= CONSOLE_SCREEN_BOTTOM){ consoleSelect(&bottom_screen); iprintf("\x1b[%d;%dH%c", ROUND_SCREEN_BOTTOM(game_stat.by), game_stat.bx, c); } } //--------------------------------------------------------------------------------- static bool isUpdateBall(void) { static u32 update_interval; update_interval++; return (update_interval % 2) ? true : false; } //--------------------------------------------------------------------------------- static bool isMissGamePlayMain(void) { // 下画面へ描画する(ダブル版)。 return (ROUND_SCREEN_BOTTOM(game_stat.by) > PADDLE_HEIGHT_POS) ? true : false; } //--------------------------------------------------------------------------------- static bool isEndGamePlayMain(void) { return (ball_num <= 0) ? true : false; } //--------------------------------------------------------------------------------- // シーン終了確認関数 bool isExitGamePlay(void) { return (game_play.act == GAME_PLAY_INIT) ? true : false; } //--------------------------------------------------------------------------------- // ゲームレベル変更関数 void setGameLevel(void) { if(game_level < LEVEL_HARD){ game_level++; }else if(game_level >= LEVEL_HARD){ game_level = LEVEL_EASY; } } //--------------------------------------------------------------------------------- // 状態ウェイト関数 static void setWaitForVBlank(u32 frame) { while(frame){ swiWaitForVBlank(); frame--; } } //---------------------------------------------------------------------------------
gameConfig.h
// TODO: ここに一意の識別子を定義する(重複インクルード防止用)。 #ifndef _GAME_CONFIG_H_ #define _GAME_CONFIG_H_ // TODO: ここに、このヘッダファイルが必要とする外部ヘッダファイルを記述する。 #include <nds.h> #ifdef __cplusplus extern "C" { #endif // TODO: ここに #define 定義、ならびに関数のプロトタイプ宣言を追加する。 //シーン定数 typedef enum{ GAME_CONFIG_INIT, GAME_CONFIG_EXEC, GAME_CONFIG_EXIT }GAME_CONFIG_SEQ; //シーン遷移フラグ用構造体 typedef struct{ u16 act; }ST_GAME_CONFIG; //グローバル関数(シーン更新・シーン終了確認用)、プロトタイプ宣言 void updateGameConfig(void); bool isExitGameConfig(void); #ifdef __cplusplus } #endif #endif
gameConfig.c
// SCENE_GAME_CONFIG //--------------------------------------------------------------------------------- #include <stdio.h> #include "gameConfig.h" #include "gamePlay.h" //--------------------------------------------------------------------------------- // レベルセレクト表示座標 #define SELECT_LEVEL_WIDTH_POS 13 #define SELECT_LEVEL_HEIGHT_POS 10 //--------------------------------------------------------------------------------- // シーン遷移フラグ static ST_GAME_CONFIG game_config = {GAME_CONFIG_INIT}; //--------------------------------------------------------------------------------- // ゲームコンフィグ用、シーン遷移関数 static void initGameConfig(void); static void execGameConfig(void); static void exitGameConfig(void); // ゲームコンフィグ用、ゲームレベル選択関数 static void selectGameLevel(void); //--------------------------------------------------------------------------------- // シーン更新関数 void updateGameConfig(void) { switch(game_config.act){ case GAME_CONFIG_INIT: initGameConfig(); break; case GAME_CONFIG_EXEC: execGameConfig(); break; case GAME_CONFIG_EXIT: exitGameConfig(); break; default: break; } } //--------------------------------------------------------------------------------- static void initGameConfig(void) { // TODO: ここに 初期化処理を追加する。 // レベルセレクトをメイン画面に表示するか、サブ画面にするか設定する。 consoleSelect(&top_screen); // 初期レベル(イージーレベル)になるよう初期化する。 game_level = LEVEL_HARD; selectGameLevel(); // レベルセレクトの表示 iprintf("\x1b[%d;%dHeasy", SELECT_LEVEL_HEIGHT_POS + LEVEL_EASY, SELECT_LEVEL_WIDTH_POS); iprintf("\x1b[%d;%dHnormal", SELECT_LEVEL_HEIGHT_POS + LEVEL_NORMAL, SELECT_LEVEL_WIDTH_POS); iprintf("\x1b[%d;%dHhard", SELECT_LEVEL_HEIGHT_POS + LEVEL_HARD, SELECT_LEVEL_WIDTH_POS); game_config.act = GAME_CONFIG_EXEC; } //--------------------------------------------------------------------------------- static void execGameConfig(void) { // TODO: ここに 実行動作を追加する。 // セレクトボタンが押されたらゲームレベルを選択する。 if(keysDown() & KEY_SELECT) selectGameLevel(); // スタートボタンが押されたらゲームコンフィグシーンを終了する。 if(keysDown() & KEY_START) game_config.act = GAME_CONFIG_EXIT; } //--------------------------------------------------------------------------------- static void exitGameConfig(void) { game_config.act = GAME_CONFIG_INIT; } //--------------------------------------------------------------------------------- // シーン終了確認関数 bool isExitGameConfig(void) { return (game_config.act == GAME_CONFIG_INIT) ? true : false; } //--------------------------------------------------------------------------------- // ゲームレベル選択関数 static void selectGameLevel(void) { // 前回のカーソルを消す。 iprintf("\x1b[%d;%dH ", SELECT_LEVEL_HEIGHT_POS + game_level, SELECT_LEVEL_WIDTH_POS - 1); // ゲームレベルを上げる。 setGameLevel(); // 現在のカーソルを表示する。 iprintf("\x1b[%d;%dH*", SELECT_LEVEL_HEIGHT_POS + game_level, SELECT_LEVEL_WIDTH_POS - 1); } //---------------------------------------------------------------------------------