ページ 1 / 1
Dxライブラリについて
Posted: 2013年6月14日(金) 12:36
by mi_l
私は、C++を勉強していて、DXライブラリで簡単なゲームを作ろうとしています。
C要素が多い、竜神録の館はほとんど理解できました(できたと思っています)ので、C++用のソースをダウンロードして開いたのですが、まったくわかりませんでした・・・
とりあえず、背景のスクロール(背景クラス)だけ、書きました・・
コード:
#include"Back.h"
#include"DxLib.h"
Back::Back(void)
{
count = 0
}
Back::~Back(void)
{
}
void Back::setPos()
{
posX = 100;
posY = 100+count;
}
void Back::calc()
{
count++;
}
void Back::Draw()
{
setPos();
calc();
DrawGraph( posX , posY , b_img , FALSE );
}
コード:
#ifndef BACK_H_
#define BACK_H_
class Back
{
private:
float posX;
float posY;
int count;
protected:
public:
Back(void);
~Back(void);
void setPos();
void calc();
void Draw();
};
#endif //BACK_H_
ここに、あとは、Loadクラスでも作って、画像をロードして、背景クラスにインクルードすればいいのだと思いますが、その後、下記のメイン関数にどのように書いていけばいいのかわかりません。
今は、背景だけですが、これから様々な要素(敵、自機、エフェクト、障害物など)を取り入れていくとき、竜神録みたいに「func_state」たる変数を用意してcase文で分けていくのでしょうか?
コード:
int Key[256];
int GetHitKeyStateAll_2(int GetHitKeyStateAll_InputKey[]){
char GetHitKeyStateAll_Key[256];
GetHitKeyStateAll( GetHitKeyStateAll_Key );
for(int i=0;i<256;i++){
if(GetHitKeyStateAll_Key[i]==1) GetHitKeyStateAll_InputKey[i]++;
else GetHitKeyStateAll_InputKey[i]=0;
}
return 0;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode(TRUE);//ウィンドウモード
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化
while(ProcessMessage()==0 && ClearDrawScreen()==0 && GetHitKeyStateAll_2(Key)==0 && Key[KEY_INPUT_ESCAPE]==0){
//↑メッセージ処理 ↑画面をクリア ↑入力状態を保存 ↑ESCが押されていない
//ココ!!
ScreenFlip();
}
DxLib_End();
return 0;
}
今は休み時間で、書いたのでスペルミスなどあるかもしれません・・・
メインはコピペしたものです。
上に、背景のヘッダーなどインクルードします(している設定で・・・)
お願いします。
※管理人さん、副管理人さんへ・・
私は結構前から残っているアンドロイドアプリのトピックがあります。
現在も忘れないように勉強していますが、それは忘れないようにするためであり、トピックの答えを出そうというのではありません。
Cを勉強して、C++に入って更に当然他にもやることがありますので、そのトピックは、このまま長い間放置になってしまいます・・
要するに、C++で何かを作ろうとしており、プログラムの授業なんて学校ではないので他のことも疎かにできません。
よって、Javaでの製作はストップしている状況です、ですので、そのトピックは削除してください。
Re: Dxライブラリについて
Posted: 2013年6月14日(金) 16:40
by softya(ソフト屋)
> よって、Javaでの製作はストップしている状況です、ですので、そのトピックは削除してください。
申し訳ないですが、フォーラムルールを読んで頂くと分かりますが原則として削除をお受けすることはできません。
解決していないトピックでも何らかのヒントに成る可能性があることと、第一に回答してくれた回答者に失礼になるからです。
他の掲示板でもそうですが、削除はできるだけ避けていただきたいと思います。
さて内容ですが、オブジェクト指向をちゃんとやるのか、手続き指向なのか(ベターC?)なのかスタンスを明確にしてもらったほうが良さそうです。
今のままだと、手続き指向をただクラスの形にしただけって印象なので勿体無いです。
それとクラスはインスタンスを生成しないと始まりません。そういう部分も勉強されていないように見えますが如何なのでしょうか?
Re: Dxライブラリについて
Posted: 2013年6月14日(金) 17:44
by mi_l
返信ありがとうございます。
softya(ソフト屋) さんが書きました:
申し訳ないですが、フォーラムルールを読んで頂くと分かりますが原則として削除をお受けすることはできません。
解決していないトピックでも何らかのヒントに成る可能性があることと、第一に回答してくれた回答者に失礼になるからです。
他の掲示板でもそうですが、削除はできるだけ避けていただきたいと思います。
おっしゃる通り、削除というのは回答者様にものすごい失礼な事ではあります。ですが、放置して、違うトピックを立て続けるのも失礼なので一応けじめとして書きました。
フォーラムルールに則り、削除はしない方向でお願いします。
softya(ソフト屋) さんが書きました:
さて内容ですが、オブジェクト指向をちゃんとやるのか、手続き指向なのか(ベターC?)なのかスタンスを明確にしてもらったほうが良さそうです。
今のままだと、手続き指向をただクラスの形にしただけって印象なので勿体無いです。
それとクラスはインスタンスを生成しないと始まりません。そういう部分も勉強されていないように見えますが如何なのでしょうか?
方向としては、「オブジェクト指向をちゃんとやる」の方向です。
そして、ここの、指摘していただいた個所なのですけど、最初の私の質問にもあります通り、プログラミングの館では、まずmainに骨格をコピペ、そこから始めるようになっております・・・
ですが、私がどうしてもmain.cppを作ると以下のようになります・・・
コード:
#ifndef MAIN_H_
#define MAIN_H_
class Main
{
private:
Back bg;
protected:
public:
Main(void);
~Main(void);
void calc();//なんとなく・・
void draw();
}
#endif //MAIN_H_
コード:
#include "Back.h"
#include "main.h"
#include "DxLib.h"
Main::Main()
{
}
Main::~Main()
{
}
void Main::calc()
{
}
void Main::draw()
{
bg.Draw();
}
これですと、ウィンドウの生成など、骨格に含まれていたことを何処に書けばいいのかわかりません。
竜神録のC++のコードにもmainに骨格は書いてありせんでした・・・
どこにウィンドウ生成、つまり、コピペする「必ず書く骨格」は書けばいいのでしょうか?
そもそもmainの記述に誤りがあればそれもお願いします。
Re: Dxライブラリについて
Posted: 2013年6月14日(金) 18:16
by KORYUOH
C++でもmainはmain関数で書きます。
なのでこの場合main.cppは
コード:
//インクルードは省略
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )
{
//実装(省略)
return 0;
}
の形で大丈夫です。
骨格に関しては別のクラスで用意し
実行メソッドを呼び出すだけの実装にするのがスマートだと思います。
Re: Dxライブラリについて
Posted: 2013年6月14日(金) 18:53
by mi_l
返信ありがとうございます。
ウィンドウ生成は、他クラスに骨格のウィンドウ生成を記述したメソッドを用意して、メインで実装すればよいというのはわかりました。
しかし、ループはどのように表現すればいいのでしょうか?
mainのなかに描画などを実装するならそこはループ内でないといけないのですが・・・
コード:
while(ProcessMessage()==0 && ClearDrawScreen()==0 && GetHitKeyStateAll_2(Key)==0 && Key[KEY_INPUT_ESCAPE]==0){
//↑メッセージ処理 ↑画面をクリア ↑入力状態を保存 ↑ESCが押されていない
//ココ!!
ScreenFlip();
}
はmain内に書かなくて大丈夫なのでしょうか?
Re: Dxライブラリについて
Posted: 2013年6月14日(金) 19:06
by KORYUOH
mi_l さんが書きました:
mainのなかに描画などを実装するならそこはループ内でないといけないのですが・・・
コード:
while(ProcessMessage()==0 && ClearDrawScreen()==0 && GetHitKeyStateAll_2(Key)==0 && Key[KEY_INPUT_ESCAPE]==0){
//↑メッセージ処理 ↑画面をクリア ↑入力状態を保存 ↑ESCが押されていない
//ココ!!
ScreenFlip();
}
はmain内に書かなくて大丈夫なのでしょうか?
考え方によりますがmainが描画、更新などをする必要性はないのでそれも別のクラスに任せてしまうとよいでしょう。
ざっくりとしたクラスですが
コード:
class Runner{
public:
Runner();
virtual ~Runner(){}
void run();
private:
//実装(省略)
}
このようなクラスを用意することでメイン関数内でインスタンスをつくりrun()を呼び出すだけになります。
run()ではウィンドウの作成からメインループを行う感じです。
Re: Dxライブラリについて
Posted: 2013年6月14日(金) 19:12
by softya(ソフト屋)
私はMain専用のクラスは別に用意しなくても大丈夫だと思います。
WinMainで最低限のインスタンスを用意して、メソッドを呼び出したら良いのではないでしょうか?
クラスを用意すれば、オブジェクト指向が出来ていると言うわけでもないですから。
最初のBackクラスの
setPos();
calc();
がDrawメソッドに有る方がよほど問題だと思います。
気になる点。
1.メソッドの機能がメソッド名から逸脱している所。
2.外部公開する必要性があるか疑問なsetPos();メソッドが有る所。
3.setPos();の存在意義自体が疑わしい所。
4.Loadクラスが本当に必要なのか?と言う点。
オブジェクトして考えた時に画像ハンドルの保持はどのクラスがすべきなのか?
Loadクラスは何をするためのオブジェクトなのか?
Re: Dxライブラリについて
Posted: 2013年6月14日(金) 19:38
by mi_l
返信ありがとうございます。
>>KORYUOHさん
mainにはループ処理(その他描画などの処理)が入っているメソッドを渡すってことですか?
例えば、Backの描画処理(Draw)はRunnerクラスのrunの中のループ内に実装するってことでしょうか?
runの中にwhile文(骨格で記述さているループ文)を書き、その中に描画などの処理を書いて、最後にmainに持ってきて・・・という感じなのでしょうか?
>>softya(ソフト屋) さん
一応Back.cppを直してみました
コード:
#include"Back.h"
#include"DxLib.h"
Back::Back(void)
{
posX = 100;
posY = 100;
count = 0;
}
Back::~Back(void)
{
}
void Back::Draw()
{
DrawGraph( posX , posY+count , b_img , FALSE );
count++;
}
そして、Loadクラスは、すべての画像、音楽などのファイルをロードして、そこからそれぞれのクラスが必要なのをとっていく・・というような感じです・・
Re: Dxライブラリについて
Posted: 2013年6月14日(金) 19:54
by mi_l
>>KORYUOHさん
KORYUOHさんのおっしゃっていることは、
main
コード:
#include <DxLib.h>
#include "SystemMgr.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
CSystemMgr SystemMgr;
if( SystemMgr.Initialize() == false ){
goto FIN;
}
SystemMgr.MainLoop();
FIN:
SystemMgr.Finalize();
return 0;
}
Runnerがいわゆる↓
コード:
#include <DxLib.h>
#include "Key.h"
#include "SystemMgr.h"
#include "Macro.h"
#include "CommonDefine.h"
#define WINDOW_TITLE "東方龍神録"
/*
* @brief コンストラクタ
*/
CSystemMgr::CSystemMgr(){
m_pGameMgr = NULL;
m_pFpsCtrl = NULL;
SetGraphMode( WIN_W, WIN_H, WIN_BITS ) ; //解像度設定
SetMainWindowText(WINDOW_TITLE); //ウィンドウタイトルをセット
ChangeWindowMode( TRUE ); //ウィンドウモードに変更
DxLib_Init(); //DXライブラリ初期化
SetDrawScreen( DX_SCREEN_BACK ); //描画先を裏画面に設定
SetOutApplicationLogValidFlag(FALSE); //ログ出力しない
SetAlwaysRunFlag(TRUE); //ウィンドウがノンアクティブでも実行
SetWindowSizeChangeEnableFlag(TRUE); //ウィンドウサイズを自由に変更できる
}
/*
* @brief デストラクタ
*/
CSystemMgr::~CSystemMgr(){
delete m_pGameMgr; m_pGameMgr=NULL;
delete m_pFpsCtrl; m_pFpsCtrl=NULL;
DxLib_End(); //DXライブラリ終了処理
}
/*
* @brief 初期化
*/
bool CSystemMgr::Initialize(){
if( m_pGameMgr == NULL ){
m_pGameMgr = new CGameMgr();
}
if( m_pFpsCtrl == NULL ){
m_pFpsCtrl = new CFpsCtrl();
}
m_pGameMgr->Initialize();
return true;
}
void CSystemMgr::Finalize(){
m_pGameMgr->Finalize();
}
/*
* @brief ゲームのメインループ部
*/
void CSystemMgr::MainLoop(){
int t=0;
while( !ScreenFlip() && !ProcessMessage() && !ClearDrawScreen() && !clsDx() ){
CKey::Inst()->Update(); //UIの状態更新
if( m_pGameMgr->Process() == false ){ //ゲーム処理
break;
}
m_pGameMgr->Draw(); //ゲーム描画
m_pFpsCtrl->Draw(); //FPS表示
m_pFpsCtrl->Wait(); //指定FSPを保つための待機
printfDx("Totl %2d[ms]\n", GetNowCount() - t ); t=GetNowCount();//1周の時間を処理表示
}
}
の役割をしているということです・・よね・・?
上記コードは竜神録C++版のダウンロードしたものです。
Re: Dxライブラリについて
Posted: 2013年6月14日(金) 21:00
by softya(ソフト屋)
mainの構造は、龍神録の方法でも良いですし、KORYUOHさんの方法でも良いですし、どちらを選んでもの良いと思います。
>そして、Loadクラスは、すべての画像、音楽などのファイルをロードして、そこからそれぞれのクラスが必要なのをとっていく・・というような感じです・・
資源を管理するクラスを作ると言うことですね。
であれば、Loadクラスをシングルトンにしてどこからも見えるようにしてしまうのがひとつの手です。
龍神録C++は、画像管理クラスとサウンド管理クラスがシングルトンで公開されていたはずです。
BGクラスは、STGを本格的に作るのならステージ毎の背景を処理する必要が出てくるでしょうし、ステージごとに背景サイズが違うとか、3Dを扱うクラスに成るかもしれないとか色々と考えて設計しておいた方が良いと思います。あとボス時の背景のループとかメソッドは色々必要だと思われます。
Re: Dxライブラリについて
Posted: 2013年6月14日(金) 21:28
by peot
すみません、つまらない揚げ足とりかもしれないのですが、
こういうものだと定型で覚えてしまうとまずいのではないかと
思うので書き込ませてください。
エラーを出すことはほぼないとはいえ、DXライブラリの初期化を
コンストラクタ内で行うのはよくないです。
最低限、 DxLib_Init()だけでもエラーチェックは行っておいたほうが
よいと思います。
ですから、もしmain.cppつくるのであれば
コード:
class Main
{
public:
Main();
~Main();
int run;//又はRunnerでもmainLoopでもスキに
private:
Back bg;
void calc();
void draw();
};
/////////////////////////////////////////////////////////////////////
Main::Main()
{
//エラーチェックをしないならこっちでもいい
ChangeWindowMode( TRUE );
}
Main::~Main(){ DxLib_End(); }
int Main::run()
{
//DXライブラリ初期化
if( DxLib_Init() == -1 ){ return -1; }// ここ重要!
//描画先を裏画面に設定
SetDrawScreen( DX_SCREEN_BACK );
while(
!ScreenFlip() &&
!ProcessMessage() &&
!ClearDrawScreen() )
{
calc();
draw();
}
return 0;
}
void Main::calc(){}
void Main::draw(){ bg.Draw(); }
このようなカタチにしたほうがよいのではないでしょうか。
そんな細かいこと気にしねーわーと言うならば、忘れてもらって結構ですが・・・。
Re: Dxライブラリについて
Posted: 2013年6月14日(金) 21:42
by softya(ソフト屋)
異常処理なら、龍神録C++でデストラクタが呼ばれない問題を適切に処理した上でですが、コンストラクタであるCSystemMgr::CSystemMgr(){から、throwしても良い気がします。
当然、インスタンス生成元であるWinMainでtry~catchしないとダメですけど。
Re: Dxライブラリについて
Posted: 2013年6月17日(月) 17:02
by mi_l
皆様、返信ありがとうございます。
また、ほかのやり方も教えていただき、ありがとうございます
Re: Dxライブラリについて
Posted: 2013年6月17日(月) 19:01
by softya(ソフト屋)
良かったら、背景を動かすところまでは続けてはどうでしょうか?
ここで終わるのは中途半端な気がするのですが。
Re: Dxライブラリについて
Posted: 2013年6月18日(火) 14:36
by mi_l
解決後なのに返信ありがとうございます。
もちろんそのつもりです。
背景をスクロールさせて、キャラを出すところまでとりあえずやるつもりです!
おそらくそのことで新たなトピックを立てるとは思います・・・・自分の書いたコードをどれだけきれいにできるかとかで・・・