シーンごとのソース管理
シーンごとのソース管理
DXライブラリを使わせてもらって数ヶ月がたちました。
こちらのライブラリ製作者様には本当に感謝しております。
このライブラリを使って今まで色々なゲームを作ってきたのですが
どれもシーンの管理をフラグでやっていた為、
1つのファイルにソースコードを書いてしまっております。
最近、見づらくなり解析が面倒になってきたので
今後の為にDXライブラリをシーンごとにファイルを管理できるように改変したいです。
ただよくやり方がわかりません。
多分できるかと思うのですが、本当にできるのでしょうか?(分割コンパイル?)
主に
初期化
処理(メインループ)
画像の読み込み
描画
後処理 - 変数の後処理など
の5つの関数をそれぞれのファイルに書いて呼び出したいです。
ただ作り方が全く検討もつかないのでサンプルコードを頂けますと助かります。
丸投げになってしまって申し訳ないのですがご教授頂けますと助かります。
こちらのライブラリ製作者様には本当に感謝しております。
このライブラリを使って今まで色々なゲームを作ってきたのですが
どれもシーンの管理をフラグでやっていた為、
1つのファイルにソースコードを書いてしまっております。
最近、見づらくなり解析が面倒になってきたので
今後の為にDXライブラリをシーンごとにファイルを管理できるように改変したいです。
ただよくやり方がわかりません。
多分できるかと思うのですが、本当にできるのでしょうか?(分割コンパイル?)
主に
初期化
処理(メインループ)
画像の読み込み
描画
後処理 - 変数の後処理など
の5つの関数をそれぞれのファイルに書いて呼び出したいです。
ただ作り方が全く検討もつかないのでサンプルコードを頂けますと助かります。
丸投げになってしまって申し訳ないのですがご教授頂けますと助かります。
Re:シーンごとのソース管理
>DXライブラリを使わせてもらって数ヶ月がたちました。
>こちらのライブラリ製作者様には本当に感謝しております。
大きな勘違いを・・・w
DXライブラリを制作された方のページを以下に。
ttp://homepage2.nifty.com/natupaji/DxLib/index.html
いきなりは厳しいので、まず、分割コンパイルと検索かければ、
入門ページが出てきますので、一度一通り目を通されてはいかがでしょうか?
それから分からないことがあれば、再度質問するとよいと思います。
>こちらのライブラリ製作者様には本当に感謝しております。
大きな勘違いを・・・w
DXライブラリを制作された方のページを以下に。
ttp://homepage2.nifty.com/natupaji/DxLib/index.html
いきなりは厳しいので、まず、分割コンパイルと検索かければ、
入門ページが出てきますので、一度一通り目を通されてはいかがでしょうか?
それから分からないことがあれば、再度質問するとよいと思います。
Re:シーンごとのソース管理
分割コンパイルのやり方はわかるのですが
私がしたいことのロジックがわかりません。
どのように組めばよいかアドバイスをいただきたいです。
分割コンパイル
ヘッダにプロトコル宣言してcppに実際の処理を書きメインでインクルードするみたいな
流れかとおもいます。
今回やりたいのは毎回インクルードするのでは手間なので一箇所にどんなシーンがあるかを登録?してやる感じにしたいです。
なるほど、勘違いしておりました><
ご指摘ありがとうございます。
私がしたいことのロジックがわかりません。
どのように組めばよいかアドバイスをいただきたいです。
分割コンパイル
ヘッダにプロトコル宣言してcppに実際の処理を書きメインでインクルードするみたいな
流れかとおもいます。
今回やりたいのは毎回インクルードするのでは手間なので一箇所にどんなシーンがあるかを登録?してやる感じにしたいです。
なるほど、勘違いしておりました><
ご指摘ありがとうございます。
Re:シーンごとのソース管理
>今後の為にDXライブラリをシーンごとにファイルを管理できるように改変したいです。
ただよくやり方がわかりません。
>今回やりたいのは毎回インクルードするのでは手間なので一箇所にどんなシーンがあるかを登録?してやる感じにしたいです。
よく分からないですが、もしかしてシューティング等で定番のシーン管理のシステムの擬似タスクシステムのことを言っているのでしょうか?
とりあえず下記サイトを読んでもらって狙っているものか確認してもらえますか?
http://www5f.biglobe.ne.jp/~kenmo/progr ... task2.html
話の内容からソースファイル分割をちゃんとしたいのか、ゲームとしての流れ・組み立てをちゃんとしたいのかはっきりしないんで答え辛い状況です。両方いっぺんにやりたいのでも良いんですけどね。
ただよくやり方がわかりません。
>今回やりたいのは毎回インクルードするのでは手間なので一箇所にどんなシーンがあるかを登録?してやる感じにしたいです。
よく分からないですが、もしかしてシューティング等で定番のシーン管理のシステムの擬似タスクシステムのことを言っているのでしょうか?
とりあえず下記サイトを読んでもらって狙っているものか確認してもらえますか?
http://www5f.biglobe.ne.jp/~kenmo/progr ... task2.html
話の内容からソースファイル分割をちゃんとしたいのか、ゲームとしての流れ・組み立てをちゃんとしたいのかはっきりしないんで答え辛い状況です。両方いっぺんにやりたいのでも良いんですけどね。
Re:シーンごとのソース管理
早速のご回答ありがとうございます。
多分、そのような考え方ではないかと思います。
ただそのような考え方があるのですねw
上手く説明できなくて申し訳ないです。
シーンごとに管理したいというのは
・タイトルシーン(ゲームロゴなどが出るシーン)
・ゲームシーン
・エンディングシーン
各シーンごとにソースを管理したいということです。
またこれをメイン処理する部分に
include "title.h"
include "game.h"
include "ending.h"
などと描くのは面倒なので
またシーンごとに変数を初期化するエリア等、同じものを設けるといったやり方です。
私のプログラムの書き方がおかしいかもしれないのですが
・初期化
・処理
・描画
・後処理
を関数でまとめて管理しております。
include "scene.h"
などとして
scene.hかscene.cにテーブルデータなどでそれぞれのシーンを登録したいです。
よくわからないかと思いますのでご指摘頂けますと幸いです。
多分、そのような考え方ではないかと思います。
ただそのような考え方があるのですねw
上手く説明できなくて申し訳ないです。
シーンごとに管理したいというのは
・タイトルシーン(ゲームロゴなどが出るシーン)
・ゲームシーン
・エンディングシーン
各シーンごとにソースを管理したいということです。
またこれをメイン処理する部分に
include "title.h"
include "game.h"
include "ending.h"
などと描くのは面倒なので
またシーンごとに変数を初期化するエリア等、同じものを設けるといったやり方です。
私のプログラムの書き方がおかしいかもしれないのですが
・初期化
・処理
・描画
・後処理
を関数でまとめて管理しております。
include "scene.h"
などとして
scene.hかscene.cにテーブルデータなどでそれぞれのシーンを登録したいです。
よくわからないかと思いますのでご指摘頂けますと幸いです。
Re:シーンごとのソース管理
おむずびさんの仰っていることがいまいち分かりかねるんですが、
あとはmain.cでscene.hをインクルードして、
各関数を呼び出す、ということでしょうか?
----scene.h----- void Init(); void MainLoop(); void Draw(); void Finish(); ---------------- ----init.c---- #include "scene.h" void Init() { 処理 } -------------- ----mainloop.c---- #include "scene.h" void MainLoop() { 処理 } --------------同じようにDrawとFinishの分も用意して、
あとはmain.cでscene.hをインクルードして、
各関数を呼び出す、ということでしょうか?
Re:シーンごとのソース管理
皆さん曖昧な表現の中、ご回答誠にありがとうございます。
その為1枚のソースに数千行書いてしまっております。
//////////////////////////////////////////////////////////////////////
これを修正して以下のようにしたいです
////////////
main.cpp
////////////
main関数{
~シーンを呼び出す処理・関数~ //引数にSCENE_STARTなどと入れたらそのシーンへ移動
}
////////////
tbl.cpp どんなシーンがあるか登録
////////////
enum{SCENE_START,SCENE_GAME,SCENE_LAST};
////////////
START.cpp
////////////
void Init(void){
~処理~
}
~LOOPなども同様~
みにくくて申し訳ございません
//現在のプログラムのイメージ //main.c enum{SCENE_START,SCENE_GAME,SCENE_LAST} void Init(void); int Scene_Num = SCENE_START; main関数{ Init(); Loop(); Draw(); Finish(); } void Init(void){ switch(Scene_Num){ case SCENE_START: ~処理~ break; case SCENE_GAME: ~処理~ break; case SCENE_LAST: ~処理~ break; } } ~LOOPなども同様~上記な感じでシーンを管理しております。
その為1枚のソースに数千行書いてしまっております。
//////////////////////////////////////////////////////////////////////
これを修正して以下のようにしたいです
////////////
main.cpp
////////////
main関数{
~シーンを呼び出す処理・関数~ //引数にSCENE_STARTなどと入れたらそのシーンへ移動
}
////////////
tbl.cpp どんなシーンがあるか登録
////////////
enum{SCENE_START,SCENE_GAME,SCENE_LAST};
////////////
START.cpp
////////////
void Init(void){
~処理~
}
~LOOPなども同様~
みにくくて申し訳ございません
Re:シーンごとのソース管理
メイン関数と、シーンを定める定数の定義と、各関数の定義を分けたい、
という認識であっているでしょうか?
という認識であっているでしょうか?
---scene.h--- enum{SCENE_START,SCENE_GAME,SCENE_LAST}; void Init(int sn); void Loop(int sn); //... ---init.cpp--- #include "scene.h" void Init(int sn) { switch(sn) { case SCENE_START: //... break; case SCENE_GAME: //... break; case SCENE_LAST: //... break; } } ---loop.cpp--- #include "scene.h" void Loop(int sn) { //... } ---main.cpp--- #include "scene.h" int main() { Init(SCENE_START); //... return 0; }こういうことでしょうか?
Re:シーンごとのソース管理
何度も回答させてしまいまして申し訳ございません。
惜しいです。
その場合ですとシーンが仮に100あった場合100ソースに分けられず
5ソースくらいなってしまうかと思います。
strat_scene.cppとSCENE_STARTをどう紐付けすればよいかもわかりません。
ですのでシーンごとに列挙した値をいれるのかと考えております
↑自分でもよくわかりません。
惜しいです。
その場合ですとシーンが仮に100あった場合100ソースに分けられず
5ソースくらいなってしまうかと思います。
//strat_scene.cpp Init(){} Loop(){} Draw(){} Finish(){} //game_scene.cpp Init(){} Loop(){} Draw(){} Finish(){} //finish_scene.cpp Init(){} Loop(){} Draw(){} Finish(){} //main.cpp main{ ~シーンを呼び出す処理~ SceneChange(SCENE_START); }ただこれだとシーンごとに関数名がかぶりダメかと思います。
strat_scene.cppとSCENE_STARTをどう紐付けすればよいかもわかりません。
ですのでシーンごとに列挙した値をいれるのかと考えております
↑自分でもよくわかりません。
Re:シーンごとのソース管理
なるほど、各シーンごとにInit,Loop,Draw、Finish等の関数が必要だということですね?
そういったことになると、C言語の範囲でやるのは難しいかもしれません。
C++のクラスの機能を使えば実装できますが、おむずびさんはC++の経験はお有りでしょうか?
そういったことになると、C言語の範囲でやるのは難しいかもしれません。
C++のクラスの機能を使えば実装できますが、おむずびさんはC++の経験はお有りでしょうか?
Re:シーンごとのソース管理
かじる程度ならあります。
私もクラスでならできそうかと思ったのですが
ややこしいのでアマリ使いたくないです。
ですのでデータテーブルに登録すると言った考え方をしました。
例えば2つシーンがある場合
//data_tbl.cpp
~シーンの登録~
のようにしメインで呼び出すと考えております。
私のソースの書き方の癖が悪いのですが
何せこれで続けていきたいです。
私もクラスでならできそうかと思ったのですが
ややこしいのでアマリ使いたくないです。
ですのでデータテーブルに登録すると言った考え方をしました。
例えば2つシーンがある場合
//strat_scene.cpp start_Init(){} start_Loop(){} start_Draw(){} start_Finish(){} //game_scene.cpp game_Init(){} game_Loop(){} game_Draw(){} game_Finish(){}などど名前を変えてしまい
//data_tbl.cpp
~シーンの登録~
のようにしメインで呼び出すと考えております。
私のソースの書き方の癖が悪いのですが
何せこれで続けていきたいです。
Re:シーンごとのソース管理
C言語におけるタスクシステムに近いものがありますが、
[color=#d0b0c0" face="monospace]
>ただこれだとシーンごとに関数名がかぶりダメかと思います。
[/color]
static にすればかぶりませんよ。
[color=#d0d0ff" face="monospace"><hr width="40%" align="left" color="#101010]
typedef struct SceneFunc
{
void (*init)();
void (*loop)();
void (*draw)();
void (*finish)();
} SceneFunc;
[/color]
こんな感じの構造体を用意しておいて
[color=#d0d0ff" face="monospace"><hr width="40%" align="left" color="#101010]
// -----strat_scene.cpp
static void Init() {}
static void Draw() {}
static void Finish() {}
const SceneFunc *GetSceneFunc_Start()
{
static const SceneFunc func = { &Init, NULL, &Draw, &Finish };
return &func;
}
[color=#d0f0d0" >// -----strat_scene.h[/color]
const SceneFunc *GetSceneFunc_Start();
// -----game_scene.cpp
static void Init() {}
static void Loop() {}
static void Draw() {}
static void Finish() {}
const SceneFunc *GetSceneFunc_Game()
{
static const SceneFunc func = { &Init, &Loop, &Draw, &Finish };
return &func;
}
[color=#d0f0d0" >// -----game_scene.h[/color]
const SceneFunc *GetSceneFunc_Start();
[/color]
と、各ファイルで staticにした Init()~Finish()を用意します。
関数がなければ NULLを入れておきます。
次に IDに応じて各 SceneFuncの情報を取得するする関数を作ります。
[color=#d0d0ff" face="monospace"><hr width="40%" align="left" color="#101010]
[color=#d0f0d0" >// -----main.cpp[/color]
// シーンID
typedef enum SceneID
{
SCENE_START,
SCENE_GAME,
SCENE_MAX
} SceneID;
// シーンIDから呼び出す関数の情報を取得
const SceneFunc *GetSceneFunc(SceneID id)
{
const SceneFunc *sceneFunc;
switch(id)
{
case SCENE_START:
sceneFunc = GetSceneFunc_Start();
break;
case SCENE_GAME:
sceneFunc = GetSceneFunc_Game();
break;
default:
sceneFunc = NULL;
break;
}
return sceneFunc;
}
[/color]
これで準備は終わりです。
あとは
[color=#d0d0ff" face="monospace"><hr width="40%" align="left" color="#101010]
{
const SceneFunc *sceneFunc = GetSceneFunc(SCENE_START);
if(sceneFunc)
{
if(sceneFunc->init)
sceneFunc->init();
if(sceneFunc->loop)
sceneFunc->loop();
if(sceneFunc->draw)
sceneFunc->draw();
if(sceneFunc->finish)
sceneFunc->finish();
}
}
[/color]
とすることで、各ファイルの Init~~Finish()を呼び出すことができます。
あ、あとGetSceneFunc()は今回は switch-caseで実装しましたが、関数の型が統一できるのであれば、
関数テーブルにしてもいいですね。
特に 100もあるなら。
[color=#d0b0c0" face="monospace]
>ただこれだとシーンごとに関数名がかぶりダメかと思います。
[/color]
static にすればかぶりませんよ。
[color=#d0d0ff" face="monospace"><hr width="40%" align="left" color="#101010]
typedef struct SceneFunc
{
void (*init)();
void (*loop)();
void (*draw)();
void (*finish)();
} SceneFunc;
[/color]
こんな感じの構造体を用意しておいて
[color=#d0d0ff" face="monospace"><hr width="40%" align="left" color="#101010]
// -----strat_scene.cpp
static void Init() {}
static void Draw() {}
static void Finish() {}
const SceneFunc *GetSceneFunc_Start()
{
static const SceneFunc func = { &Init, NULL, &Draw, &Finish };
return &func;
}
[color=#d0f0d0" >// -----strat_scene.h[/color]
const SceneFunc *GetSceneFunc_Start();
// -----game_scene.cpp
static void Init() {}
static void Loop() {}
static void Draw() {}
static void Finish() {}
const SceneFunc *GetSceneFunc_Game()
{
static const SceneFunc func = { &Init, &Loop, &Draw, &Finish };
return &func;
}
[color=#d0f0d0" >// -----game_scene.h[/color]
const SceneFunc *GetSceneFunc_Start();
[/color]
と、各ファイルで staticにした Init()~Finish()を用意します。
関数がなければ NULLを入れておきます。
次に IDに応じて各 SceneFuncの情報を取得するする関数を作ります。
[color=#d0d0ff" face="monospace"><hr width="40%" align="left" color="#101010]
[color=#d0f0d0" >// -----main.cpp[/color]
// シーンID
typedef enum SceneID
{
SCENE_START,
SCENE_GAME,
SCENE_MAX
} SceneID;
// シーンIDから呼び出す関数の情報を取得
const SceneFunc *GetSceneFunc(SceneID id)
{
const SceneFunc *sceneFunc;
switch(id)
{
case SCENE_START:
sceneFunc = GetSceneFunc_Start();
break;
case SCENE_GAME:
sceneFunc = GetSceneFunc_Game();
break;
default:
sceneFunc = NULL;
break;
}
return sceneFunc;
}
[/color]
これで準備は終わりです。
あとは
[color=#d0d0ff" face="monospace"><hr width="40%" align="left" color="#101010]
{
const SceneFunc *sceneFunc = GetSceneFunc(SCENE_START);
if(sceneFunc)
{
if(sceneFunc->init)
sceneFunc->init();
if(sceneFunc->loop)
sceneFunc->loop();
if(sceneFunc->draw)
sceneFunc->draw();
if(sceneFunc->finish)
sceneFunc->finish();
}
}
[/color]
とすることで、各ファイルの Init~~Finish()を呼び出すことができます。
あ、あとGetSceneFunc()は今回は switch-caseで実装しましたが、関数の型が統一できるのであれば、
関数テーブルにしてもいいですね。
特に 100もあるなら。
Re:シーンごとのソース管理
すいません。
タスクシステムは良いサンプルを見つけれなかったので、シンプルなJustyさんの案で検討してみてください。
キャラの重ねあわせ制御や、シーンの切り替えが複雑になる場合、同じルーチンを複数のキャラで使いたい(キャラ毎にワークを切り替えて複数のキャラを1つの関数で操る機能)等が必要ならタスクシステムが有効なのですが、そこまで必要ないですかね。
タスクシステムは良いサンプルを見つけれなかったので、シンプルなJustyさんの案で検討してみてください。
キャラの重ねあわせ制御や、シーンの切り替えが複雑になる場合、同じルーチンを複数のキャラで使いたい(キャラ毎にワークを切り替えて複数のキャラを1つの関数で操る機能)等が必要ならタスクシステムが有効なのですが、そこまで必要ないですかね。
Re:シーンごとのソース管理
Justy様
それです!!
試してみます。
ありがとうございます。
zwi様
いえいえ><
タスクシステムといった言葉自体知らなかったので
勉強になりました。
私レベルのPGではまだそのような処理の実相はむずがしそうです。
善処いたします。
それです!!
試してみます。
ありがとうございます。
zwi様
いえいえ><
タスクシステムといった言葉自体知らなかったので
勉強になりました。
私レベルのPGではまだそのような処理の実相はむずがしそうです。
善処いたします。
Re:シーンごとのソース管理
画像を描画できないのですがなぜでしょうか・・・
普通に書くと問題なくできます。
普通に書くと問題なくできます。
start_scene.h ////////////// const SceneFunc *GetSceneFunc_Start(); start_scene.cpp ////////////// #include "DxLib.h" #include "main.h" // 画像の読み込み int H_Chr = LoadGraph("BMP/chr.png"); static void Init(){ } static void Loop(){} static void Draw(){ //DrawGraph( (int)Play.Px , (int)Play.Py , H_Chr , true ); DrawGraph( 0 , 0 , H_Chr , true ); } static void Finish(){} const SceneFunc *GetSceneFunc_Start(){ static const SceneFunc func = { &Init, &Loop, &Draw, &Finish }; return &func; } main.cpp ////////////// #include "DxLib.h" #include "main.h" #include "start_scene.h" typedef enum SceneID{ SCENE_START, SCENE_GAME, SCENE_MAX }SceneID; // シーンIDから呼び出す関数の情報を取得 const SceneFunc *GetSceneFunc(SceneID id) { const SceneFunc *sceneFunc; switch(id){ case SCENE_START: sceneFunc = GetSceneFunc_Start(); break; case SCENE_GAME: break; default: // sceneFunc = NULL; break; } return sceneFunc; } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){ ChangeWindowMode(true); // ウインドウの変更 フルスクリーン・ウインドウ SetDrawScreen( DX_SCREEN_BACK ) ; // 描画先を裏画面に設定 // DXライブラリ初期化処理 if( DxLib_Init() == -1 ){ return -1; // エラーが起きたら直ちに終了 } const SceneFunc *sceneFunc = GetSceneFunc(SCENE_START); // if(sceneFunc){ // if(sceneFunc->init) sceneFunc->init(); // if(sceneFunc->loop) sceneFunc->loop(); // if(sceneFunc->finish) sceneFunc->finish(); // } // 処理 while(1){ // BMP画像の表示 ClearDrawScreen(); if(sceneFunc->draw) sceneFunc->draw(); ScreenFlip(); // 処理の終了 if(CheckHitKey(KEY_INPUT_ESCAPE)) break; } // 描画が終ったのでグラフィックをメモリ上から削除する // DeleteGraph( H_Chr ) ; DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 }
Re:シーンごとのソース管理
[color=#d0b0c0" face="monospace]
>画像を描画できないのですがなぜでしょうか・
> H_Chr = LoadGraph("BMP/chr.png");
[/color]
ここが原因のような気がします。
DxLib_Init関数の呼び出し前の LoadGraph()は無効なので、Init()の中とかで
呼んでみてはどうでしょうか。
>画像を描画できないのですがなぜでしょうか・
> H_Chr = LoadGraph("BMP/chr.png");
[/color]
ここが原因のような気がします。
DxLib_Init関数の呼び出し前の LoadGraph()は無効なので、Init()の中とかで
呼んでみてはどうでしょうか。