ページ 1 / 1
シーンごとのソース管理
Posted: 2009年9月01日(火) 10:23
by おむずび
DXライブラリを使わせてもらって数ヶ月がたちました。
こちらのライブラリ製作者様には本当に感謝しております。
このライブラリを使って今まで色々なゲームを作ってきたのですが
どれもシーンの管理をフラグでやっていた為、
1つのファイルにソースコードを書いてしまっております。
最近、見づらくなり解析が面倒になってきたので
今後の為にDXライブラリをシーンごとにファイルを管理できるように改変したいです。
ただよくやり方がわかりません。
多分できるかと思うのですが、本当にできるのでしょうか?(分割コンパイル?)
主に
初期化
処理(メインループ)
画像の読み込み
描画
後処理 - 変数の後処理など
の5つの関数をそれぞれのファイルに書いて呼び出したいです。
ただ作り方が全く検討もつかないのでサンプルコードを頂けますと助かります。
丸投げになってしまって申し訳ないのですがご教授頂けますと助かります。
Re:シーンごとのソース管理
Posted: 2009年9月01日(火) 13:05
by kazuoni
>DXライブラリを使わせてもらって数ヶ月がたちました。
>こちらのライブラリ製作者様には本当に感謝しております。
大きな勘違いを・・・w
DXライブラリを制作された方のページを以下に。
ttp://homepage2.nifty.com/natupaji/DxLib/index.html
いきなりは厳しいので、まず、分割コンパイルと検索かければ、
入門ページが出てきますので、一度一通り目を通されてはいかがでしょうか?
それから分からないことがあれば、再度質問するとよいと思います。
Re:シーンごとのソース管理
Posted: 2009年9月01日(火) 14:05
by おむずび
分割コンパイルのやり方はわかるのですが
私がしたいことのロジックがわかりません。
どのように組めばよいかアドバイスをいただきたいです。
分割コンパイル
ヘッダにプロトコル宣言してcppに実際の処理を書きメインでインクルードするみたいな
流れかとおもいます。
今回やりたいのは毎回インクルードするのでは手間なので一箇所にどんなシーンがあるかを登録?してやる感じにしたいです。
なるほど、勘違いしておりました><
ご指摘ありがとうございます。
Re:シーンごとのソース管理
Posted: 2009年9月01日(火) 16:26
by zwi
>今後の為にDXライブラリをシーンごとにファイルを管理できるように改変したいです。
ただよくやり方がわかりません。
>今回やりたいのは毎回インクルードするのでは手間なので一箇所にどんなシーンがあるかを登録?してやる感じにしたいです。
よく分からないですが、もしかしてシューティング等で定番のシーン管理のシステムの擬似タスクシステムのことを言っているのでしょうか?
とりあえず下記サイトを読んでもらって狙っているものか確認してもらえますか?
http://www5f.biglobe.ne.jp/~kenmo/progr ... task2.html
話の内容からソースファイル分割をちゃんとしたいのか、ゲームとしての流れ・組み立てをちゃんとしたいのかはっきりしないんで答え辛い状況です。両方いっぺんにやりたいのでも良いんですけどね。
Re:シーンごとのソース管理
Posted: 2009年9月01日(火) 19:03
by おむずび
早速のご回答ありがとうございます。
多分、そのような考え方ではないかと思います。
ただそのような考え方があるのですねw
上手く説明できなくて申し訳ないです。
シーンごとに管理したいというのは
・タイトルシーン(ゲームロゴなどが出るシーン)
・ゲームシーン
・エンディングシーン
各シーンごとにソースを管理したいということです。
またこれをメイン処理する部分に
include "title.h"
include "game.h"
include "ending.h"
などと描くのは面倒なので
またシーンごとに変数を初期化するエリア等、同じものを設けるといったやり方です。
私のプログラムの書き方がおかしいかもしれないのですが
・初期化
・処理
・描画
・後処理
を関数でまとめて管理しております。
include "scene.h"
などとして
scene.hかscene.cにテーブルデータなどでそれぞれのシーンを登録したいです。
よくわからないかと思いますのでご指摘頂けますと幸いです。
Re:シーンごとのソース管理
Posted: 2009年9月01日(火) 19:11
by MNS
おむずびさんの仰っていることがいまいち分かりかねるんですが、
----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:シーンごとのソース管理
Posted: 2009年9月01日(火) 21:00
by おむずび
皆さん曖昧な表現の中、ご回答誠にありがとうございます。
//現在のプログラムのイメージ
//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:シーンごとのソース管理
Posted: 2009年9月01日(火) 21:21
by MNS
メイン関数と、シーンを定める定数の定義と、各関数の定義を分けたい、
という認識であっているでしょうか?
---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:シーンごとのソース管理
Posted: 2009年9月01日(火) 21:42
by おむずび
何度も回答させてしまいまして申し訳ございません。
惜しいです。
その場合ですとシーンが仮に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:シーンごとのソース管理
Posted: 2009年9月01日(火) 22:00
by MNS
なるほど、各シーンごとにInit,Loop,Draw、Finish等の関数が必要だということですね?
そういったことになると、C言語の範囲でやるのは難しいかもしれません。
C++のクラスの機能を使えば実装できますが、おむずびさんはC++の経験はお有りでしょうか?
Re:シーンごとのソース管理
Posted: 2009年9月01日(火) 22:14
by おむすび
かじる程度ならあります。
私もクラスでならできそうかと思ったのですが
ややこしいのでアマリ使いたくないです。
ですのでデータテーブルに登録すると言った考え方をしました。
例えば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:シーンごとのソース管理
Posted: 2009年9月01日(火) 22:22
by zwi
お話を伺うと、それこそ何らかのタスクシステムを使った方が管理しやすそうですけどね。
良いサンプルソースが無いか探してみます。
Re:シーンごとのソース管理
Posted: 2009年9月01日(火) 22:33
by Justy
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もあるなら。
Re:シーンごとのソース管理
Posted: 2009年9月01日(火) 23:27
by zwi
すいません。
タスクシステムは良いサンプルを見つけれなかったので、シンプルなJustyさんの案で検討してみてください。
キャラの重ねあわせ制御や、シーンの切り替えが複雑になる場合、同じルーチンを複数のキャラで使いたい(キャラ毎にワークを切り替えて複数のキャラを1つの関数で操る機能)等が必要ならタスクシステムが有効なのですが、そこまで必要ないですかね。
Re:シーンごとのソース管理
Posted: 2009年9月01日(火) 23:45
by おむすび
Justy様
それです!!
試してみます。
ありがとうございます。
zwi様
いえいえ><
タスクシステムといった言葉自体知らなかったので
勉強になりました。
私レベルのPGではまだそのような処理の実相はむずがしそうです。
善処いたします。
Re:シーンごとのソース管理
Posted: 2009年9月01日(火) 23:58
by omusubi
画像を描画できないのですがなぜでしょうか・・・
普通に書くと問題なくできます。
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:シーンごとのソース管理
Posted: 2009年9月02日(水) 00:00
by おむすび
すみません。
名前をローマ字のまま投稿してしまいました。
上記のバグ?の対処法を教えていただけますと助かります。
Re:シーンごとのソース管理
Posted: 2009年9月02日(水) 00:22
by Justy
[color=#d0b0c0" face="monospace]
>画像を描画できないのですがなぜでしょうか・
> H_Chr = LoadGraph("BMP/chr.png");
[/color]
ここが原因のような気がします。
DxLib_Init関数の呼び出し前の LoadGraph()は無効なので、Init()の中とかで
呼んでみてはどうでしょうか。
Re:シーンごとのソース管理
Posted: 2009年9月02日(水) 00:33
by おむすび
justyさん
原因はそれでした。
ありがとうございます。
Re:シーンごとのソース管理
Posted: 2009年9月15日(火) 20:22
by おむすび