分割コンパイルを詳しく教えてください!!

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Brail

分割コンパイルを詳しく教えてください!!

#1

投稿記事 by Brail » 12年前

DXライブラリを利用したゲーム作成の勉強をしています!!
http://dixq.net/g/index.html
http://homepage2.nifty.com/natupaji/DxLib/
ここのサイトを参考に勉強しています。
で、ここのサイトにある画像を使った簡単なゲーム?を作っています。


・スペースボタンで弾を発射します。
・W・A・S・Dキーあるいは↑・←・↓・→キーで自機の移動です
・敵はドラゴンの画像を使わせていただいてます。ドラゴンは波みたいに揺れて移動します。弾は発射しません。
・自機は新・ゲームプログラミングの館さんのキャラクタ00をGIMPの練習で背景を透過させたキャラクタ01とまったく同じものをしようさせていただいてます。

みたいな内容です

コードは

コード:

 


#include "DxLib.h"
#define SHOT 20


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

		if(DxLib_Init()==-1)return -1;

		//////////////////////////////////////////////宣言
		int DX=320,DY=70,DM1=1,DM2=1,Dragon=LoadGraph("ドラゴン.png");
		int PX=320,PY=400,Player=LoadGraph("キャラクタ.png");
		int SX[SHOT],SY[SHOT],SF[SHOT],Shot=LoadGraph("弾.png");
		int SBF=0,a=0;
		int DW,DH,SW,SH;
		int Back=LoadGraph("背景.png");
		int Blue=GetColor(0,255,255),Green=GetColor(0,255,0),GreenYello=GetColor(150,255,0);
		int Black=LoadGraph("Black.png");
		int Font1=CreateFontToHandle(NULL,64,3);
		int Font2=CreateFontToHandle(NULL,32,2);

		
		for(int i=0;i<SHOT;i++){
			SF[i]=0;
		}
		GetGraphSize(Shot  ,&SW,&SH);
		GetGraphSize(Dragon,&DW,&DH);

		////////////////////////////////////////////////////////////////////
		////////////////      
		/////////////////////                  ///メインコード///
		//////////////////////////
		////////////////////////////////////////////////////////////////////

        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){

			//////////////////////////////背景、文字、自機、敵の読み込み
			DrawGraph(0,45,Back,TRUE);
			DrawFormatStringToHandle(500,400,Blue,Font1,"%03d",a);
			DrawRotaGraph(PX,PY,0.8,0.0,Player,TRUE);
			DrawRotaGraph(DX,DY,1.2,0.0,Dragon,TRUE);

			///////自機の操作
			if(CheckHitKey(KEY_INPUT_RIGHT)==1 || CheckHitKey(KEY_INPUT_D)==1){
				PX+=3;
			}
			if(CheckHitKey(KEY_INPUT_LEFT)==1  || CheckHitKey(KEY_INPUT_A)==1){
				PX-=3;
			}
			if(CheckHitKey(KEY_INPUT_UP)==1    || CheckHitKey(KEY_INPUT_W)==1){
				PY-=3;
			}
			if(CheckHitKey(KEY_INPUT_DOWN)==1  || CheckHitKey(KEY_INPUT_S)==1){
				PY+=3;
			}
			
			//////////////////////////////////////自機の弾
			if(CheckHitKey(KEY_INPUT_SPACE)|| CheckHitKey(KEY_INPUT_E) || CheckHitKey(KEY_INPUT_R)){
				if(SBF==0){
					for(int i=0;i<SHOT;i++){
						if(SF[i]==0){
							SX[i]=PX;
							SY[i]=PY;
							SF[i]=1;

							break;
						}
					}
				}
				SBF=1;
			}else{
				SBF=0;
			}

			////////////////////////////////自機の発射した弾を移動させる
			for(int i=0;i<SHOT;i++){
				if(SF[i]==1){
					SY[i]-=16;
					if(SY[i]<-80){
						SF[i]=0;
					}
					DrawRotaGraph(SX[i],SY[i],0.3,0.0,Shot,TRUE);
				}
			}

			///////////////////////////////////////自機を画面から出さない
			if(PX>=640){
				PX=640;
			}else if(PX<=0){
				PX=0;
			}else if(PY>=480){
				PY=480;
			}else if(PY<=0){
				PY=0;
			}

			/////////////////////////////////////////////////敵機を動かす
			//////////////////////////////////////////////////////横移動
			if(DM1==1){DX+=2;}
			if(DM1==0){DX-=2;}

			if(DX>600){
				DX=600;
				DM1=0;
			}
			if(DX<40){
				DX=40;
				DM1=1;
			}
			///////////////////////////////////////////////////////縦移動
			if(DM2==1){DY+=1;}
			if(DM2==0){DY-=1;}

			if(DY>100){
				DY=100;
				DM2=0;
			}
			if(DY<45){
				DY=45;
				DM2=1;
			}

			///////////////////////////////////////////////当たり判定
			for(int i=0;i<SHOT;i++){
				
				if( SF[i]==1 ){
					if( ( ( SX[i] > DX && SX[i] < DX + DW ) ||
						( DX > SX[i] && DX < SX[i] + SW ) ) &&
						( ( SY[i] > DY && SY[i] < DY + DH ) ||
						( DY > SY[i] && DY < SY[i] + SH ) ) ){
							SF[i]=0;
							a+=1;
					}
				}
			}
			////////////////////////////////////////////////閉じる
			if(CheckHitKey(KEY_INPUT_ESCAPE)==1 || CheckHitKey(KEY_INPUT_RETURN)==1){
				break;
			}
			if(a>5){
				WaitTimer(200);
				DrawGraph(0,0,Black,FALSE);
				DrawStringToHandle(30,220,"C o m p l e t e d !!",Green,Font1);
             DrawStringToHandle(80,280,"Push!EnterKey!!",GreenYello,Font2);
			}
		}
		DxLib_End(); ///////////////////////////////// DXライブラリ終了処理
        return 0;
}  

初めてなのでテンプレート失礼します。
[1] 質問文
 [1.1] 自分が今行いたい事は何か
>>先ほど言ったとおり簡単な内容のゲームの作成です。

 [1.2] どのように取り組んだか(プログラムコードがある場合記載)
>>コード自体に一切のエラーはありません。

 [1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
>>分割コンパイルというのをやろうと思ったのですが変数について不明です。

 [1.4] 今何がわからないのか、知りたいのか
>>1.3と同じです

[2] 環境  
 [2.1] OS : Windows, Linux等々
>>Windows7 HomePremium 64bit

 [2.2] コンパイラ名 : VC++ 2008EE, Borand C++, gcc等々
>>VisualStudioExpress 2012 for WindowsDesktop
というのですか?です!

[3] その他
 ・どの程度C言語を理解しているか
>>さらっと入門書に書いてあるようなことは勉強しました。理解といわれると怪しいですがその都度調べればそれなりに理解はできると思います。

 ・ライブラリを使っている場合は何を使っているか
>>DXライブラリはライブラリですよね・・・はい!DXライブラリ使ってます!

<<<<<<<重要なところ>>>>>>>>
分割コンパイルをさせたいのですがうまくいきません。
具体的に言うと
上記のコードをMain.cppとすると
敵が移動する処理のコードを
Enemymove.cpp と Enemymove.h
に作るのはよいのですが
ファイル間での変数(例:DX DY )をどうすればよいのかがわかりません。
Main.cppで宣言するとEnemymove.cppの方では使えませんし
その逆も同じようなことが起こります。
両方で宣言すると動かなくなります。

分割コンパイルでの変数の扱い方を詳しく教えてください!
長々とすいません!回答お願いします!!

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#2

投稿記事 by usao » 12年前

分割コンパイル以前に,まず,
各々の処理(自機を動かすとか敵が動くとか)を関数化するところから開始しましょう.
仮に「そんなことはできる,やりたいのは分割コンパイルだ」というのであれば
とりあえず各処理を関数化した状態のコードを作って,それを提示された方が話が早いはずです.

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#3

投稿記事 by softya(ソフト屋) » 12年前

ゲームプログラミングの館を読勉強されているのなら、「ゲームプログラミング設計」の章は読まれましたか?
あれを読んで分からない事を聞いていただいたほうが良いと思います。変数についても詳しく書かれています。

書いてる途中でしたが、 usaoさんの意見をまず実行したほうがよさそうです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Brail

Re: 分割コンパイルを詳しく教えてください!!

#4

投稿記事 by Brail » 12年前

返信ありがとうございます!!
分割コンパイルも関数化もやり方はわかります。
分割コンパイルは ヘッダーファイルでプロトタイプ宣言?などをして
cppファイルで処理を書くというのですね
関数化は分割せずにひとつのファイルに上のやり方をするのですよね?

それをやりたいのですが変数の扱いがわかりません;;

グローバル変数ってわたしのMain.cppのコードで使うにはどうすればよいですか?
ただ、int WINAPI WinMain(・・・・・の前で宣言すればよいだけですか?
それでstatic はそのやり方でやるとMain.cppだけで扱う変数になるってことですか?

あと!あと!
それができて分割コンパイル出来るようにはならないと思いました。
(わたしに知識不足ですが)

とりあえずですがグローバル変数のやり方は上記のであってるのか教えてください。また、その後の関数化の手順も教えてください。

回答よろしくお願いいたします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#5

投稿記事 by softya(ソフト屋) » 12年前

慌てずに行きましょう。
その前にC言語の勉強はどうされていますか? サイトで勉強したり、参考書はお持ちでしょうか。そういう部分がすごく足りない気がしますので、どう勉強されてきたか教えてください。 → サイトURLや参考書名など。
グローバル変数とか大抵は説明されていると思います。staticについてもです。

>グローバル変数ってわたしのMain.cppのコードで使うにはどうすればよいですか?
>ただ、int WINAPI WinMain(・・・・・の前で宣言すればよいだけですか?
>それでstatic はそのやり方でやるとMain.cppだけで扱う変数になるってことですか?

今までやってきたのなら分かると思いますが、試行錯誤が大事です。
とりあえず、今ある知識でやってみてください。
あとグローバル変数を無闇に使うなとも書いてあるのは読んだと思いますが違いますか?

staticに付いては、ここで説明されていますよね。
「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」
http://dixq.net/g/d_03.html
他の関数に渡す方法は、ここに書いてあります。
「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」
http://dixq.net/g/d_05.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Brail

Re: 分割コンパイルを詳しく教えてください!!

#6

投稿記事 by Brail » 12年前

そうですね。ちょっと落ち着きます。

整理していきます。

C言語の勉強は苦しんで覚えるC言語さんというサイト
http://9cguide.appspot.com
本は猫でもわかるC言語プログラミング
を持っています。

関数についてはサイトを見ながら出なければ使えませんが
頭の中での抽象的な理解は出来ているつもりです。

===========================

今はhttp://dixq.net/g/d_01.html
ここを読みながら理解に苦しんでいるところです。

コード:

#include "DxLib.h"

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen( DX_SCREEN_BACK );

        Player_Initialize();    //プレイヤー初期化
        SEnemy_Initialize();    //雑魚的初期化
        Effect_Initialize();    //エフェクト初期化

        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){

                Player_Update();  //プレイヤー計算
                SEnemy_Update();  //雑魚的計算
                Effect_Update();  //エフェクト計算

                Player_Draw();  //プレイヤー描画
                SEnemy_Draw();  //雑魚的描画
                Effect_Draw();  //エフェクト描画

        }

        DxLib_End();
        return 0;
}
ここで実際の処理はされていないことはわかります。

Player_Initialize();
Player_Update();
Player_Draw();

これらは見やすくするための名前であって
a();
b();
c();
でもよいのですよね?

あと、このコードに付け足していくとしたら
int WINAPI WinMain(・・・・
の前の部分に
void Player_Initialize(){
・・・・・・・・・・・・・・・・・・・
・・・・・・・・・・・・・・・
・・・・・・・・・・
・・・・・・・

などをしていくのですよね?

回答よろしくお願いいたします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#7

投稿記事 by softya(ソフト屋) » 12年前

Brail さんが書きました:これらは見やすくするための名前であって
a();
b();
c();
でもよいのですよね?
良いですが私はそのコードは読みたくないですね。
Brail さんが書きました:あと、このコードに付け足していくとしたら
int WINAPI WinMain(・・・・
の前の部分に
void Player_Initialize(){
・・・・・・・・・・・・・・・・・・・
・・・・・・・・・・・・・・・
・・・・・・・・・・
・・・・・・・

などをしていくのですよね?
そういう事ですね。

【補足】
まず、uasoさんい言うように関数分割だけをしてみてください。
よく分からなければ、エラーがあっても構いません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Brail

Re: 分割コンパイルを詳しく教えてください!!

#8

投稿記事 by Brail » 12年前

申し訳ございません・・・
エラーが出るのは承知ですが訂正はいまのわたしには出来ません;;

コード:



#include "DxLib.h"
#define SHOT 20

/////////////////////////////////////////////////
///////////////////   関数
/////////////////////////////////////////////////
void Playermove();
void Playershot();
void Playershotmove();
void Playermovecontrol();
void Dragonmove();
void Dragondamage();
////////////////////////////////////////////////
///////////////////    関数
////////////////////////////////////////////////


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

		if(DxLib_Init()==-1)return -1;

//////////////////////////////////////////////////
///////////////////    宣言
//////////////////////////////////////////////////
	
		int DX=320,DY=70,DM1=1,DM2=1,Dragon=LoadGraph("ドラゴン.png");
		int PX=320,PY=400,Player=LoadGraph("キャラクタ.png");
		int SX[SHOT],SY[SHOT],SF[SHOT],Shot=LoadGraph("弾.png");
		int SBF=0,a=0;
		int DW,DH,SW,SH;
		int Back=LoadGraph("背景.png");
		int Blue=GetColor(0,255,255),Green=GetColor(0,255,0),GreenYello=GetColor(150,255,0);
		int Black=LoadGraph("Black.png");
		int Font1=CreateFontToHandle(NULL,64,3);
		int Font2=CreateFontToHandle(NULL,32,2);

		
		for(int i=0;i<SHOT;i++){
			SF[i]=0;
		}
		GetGraphSize(Shot  ,&SW,&SH);
		GetGraphSize(Dragon,&DW,&DH);

		////////////////////////////////////////////////////////////////////
		////////////////      
		/////////////////////                  ///メインコード///
		//////////////////////////
		////////////////////////////////////////////////////////////////////

        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){

			//////////////////////////////背景、文字、自機、敵の読み込み
			DrawGraph(0,45,Back,TRUE);
			DrawFormatStringToHandle(500,400,Blue,Font1,"%03d",a);
			DrawRotaGraph(PX,PY,0.8,0.0,Player,TRUE);
			DrawRotaGraph(DX,DY,1.2,0.0,Dragon,TRUE);
        	
        	
        	
        	Playermove();//////////////自機の移動
        	Playershot();//////////////自機の弾
        	Playershotmove();////////自機の発射した弾の移動
        	Playermovecontrol();//////自機を画面外に出さない
        	Dragonmove();/////////////敵機の移動
        	Dragondamage();////////////敵機の当たり判定
			

        	
			////////////////////////////////////////////////閉じる
			if(CheckHitKey(KEY_INPUT_ESCAPE)==1 || CheckHitKey(KEY_INPUT_RETURN)==1){
				break;
			}
			if(a>5){
				WaitTimer(200);
				DrawGraph(0,0,Black,FALSE);
				DrawStringToHandle(25,220,"C o m p l e t e d !!",Green,Font1);
				DrawStringToHandle(80,280,"Push!EnterKey!!",GreenYello,Font2);
			}

		}
		DxLib_End(); ///////////////////////////////// DXライブラリ終了処理
        return 0;
}  


void Playermove(){
	///////自機の操作
			if(CheckHitKey(KEY_INPUT_RIGHT)==1 || CheckHitKey(KEY_INPUT_D)==1){
				PX+=3;
			}
			if(CheckHitKey(KEY_INPUT_LEFT)==1  || CheckHitKey(KEY_INPUT_A)==1){
				PX-=3;
			}
			if(CheckHitKey(KEY_INPUT_UP)==1    || CheckHitKey(KEY_INPUT_W)==1){
				PY-=3;
			}
			if(CheckHitKey(KEY_INPUT_DOWN)==1  || CheckHitKey(KEY_INPUT_S)==1){
				PY+=3;
			}
}


void Playershot(){
	//////////////////////////////////////自機の弾
			if(CheckHitKey(KEY_INPUT_SPACE)|| CheckHitKey(KEY_INPUT_E) || CheckHitKey(KEY_INPUT_R)){
				if(SBF==0){
					for(int i=0;i<SHOT;i++){
						if(SF[i]==0){
							SX[i]=PX;
							SY[i]=PY;
							SF[i]=1;

							break;
						}
					}
				}
				SBF=1;
			}else{
				SBF=0;
			}
}


void Playershotmove(){
	////////////////////////////////自機の発射した弾を移動させる
			for(int i=0;i<SHOT;i++){
				if(SF[i]==1){
					SY[i]-=16;
					if(SY[i]<-80){
						SF[i]=0;
					}
					DrawRotaGraph(SX[i],SY[i],0.3,0.0,Shot,TRUE);
				}
			}
}


void Playermovecontrol(){
	
			///////////////////////////////////////自機を画面から出さない
			if(PX>=640){
				PX=640;
			}else if(PX<=0){
				PX=0;
			}else if(PY>=480){
				PY=480;
			}else if(PY<=0){
				PY=0;
			}
}


void Dragonmove(){
	
			/////////////////////////////////////////////////敵機を動かす
			//////////////////////////////////////////////////////横移動
			if(DM1==1){DX+=2;}
			if(DM1==0){DX-=2;}

			if(DX>600){
				DX=600;
				DM1=0;
			}
			if(DX<40){
				DX=40;
				DM1=1;
			}
			///////////////////////////////////////////////////////縦移動
			if(DM2==1){DY+=1;}
			if(DM2==0){DY-=1;}

			if(DY>100){
				DY=100;
				DM2=0;
			}
			if(DY<45){
				DY=45;
				DM2=1;
			}
}


void Dragondamage(){
	///////////////////////////////////////////////当たり判定
			for(int i=0;i<SHOT;i++){
				
				if( SF[i]==1 ){
					if( ( ( SX[i] > DX && SX[i] < DX + DW ) ||
						( DX > SX[i] && DX < SX[i] + SW ) ) &&
						( ( SY[i] > DY && SY[i] < DY + DH ) ||
						( DY > SY[i] && DY < SY[i] + SH ) ) ){
							SF[i]=0;
							a+=1;
					}
				}
			}
}



すいません変数のところはまったくどうしていいかわかりませんでしたが
一気に理解しようとせずまずは関数化だけをしてみました。
変数はどうすればよいのでしょうか?

***************************
・各関数で使おうとしている変数を使用できるようにする
・最終的にはこれをファイルとして整理する
です!
何度も申し訳ございません。
回答よろしくお願いいたします。

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#9

投稿記事 by usao » 12年前

コード:

void PrintValue( int v )
{    printf( "%d\n", v );    }

void ChangeValueTo200( int *p )
{
    if( p ){  *p = 200;  }
}

int Add( int a, int b )
{    return a + b;    }

int main()
{
    int a = 800;
    int b = 100;

    PrintValue( a );
    ChangeValueTo200( &b );
    a = Add( a, b );
    PrintValue( a );
    PrintValue( b );

    return 0;
}
うーん,このくらいわかってれば変数のことはかなり解決するんじゃないでしょうか.

簡単に言うと,
関数は自身の処理に必要なデータを引数で受け取り,処理をして,必要ならば戻り値で情報を返す.

上記コード(特にChangeValueTo200()の意味とか)が難なくわかるのであればよいのですが,
そうでないならば分割コンパイル以前の段階をいろいろと学ばないときついかもしれません.

Brail

Re: 分割コンパイルを詳しく教えてください!!

#10

投稿記事 by Brail » 12年前

PrintValue( a );
ChangeValueTo200( &b );
a = Add( a, b );
PrintValue( a );
PrintValue( b );

最初のは aがそのままなので800
つぎのチェンジなんとかのときに200の値が入っているpをbに参照しているので
a=a+bの関数のAddでは
a=800+200
a=1000
となり

4行目のは1000
最後のは200

ですよね?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#11

投稿記事 by softya(ソフト屋) » 12年前

ソースコードを見ましたが、エラーは置いておいておきますが初期化、移動と描画などが分離できていません。
d.3章 ゲームの設計と分割コンパイル(1)
http://dixq.net/g/d_03.html
にかかれていることは意味が有るので、これをマネしてください。

あと変数は、代入を除いて変数定義をWinMainより上に追い出せばエラーが取れると思います。
※ あくまで仮の処理です。
aとか意味不明の変数名もなんとかして欲しい所です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Brail

Re: 分割コンパイルを詳しく教えてください!!

#12

投稿記事 by Brail » 12年前

softya(ソフト屋) さんが書きました:ソースコードを見ましたが、エラーは置いておいておきますが初期化、移動と描画などが分離できていません。
d.3章 ゲームの設計と分割コンパイル(1)
http://dixq.net/g/d_03.html
にかかれていることは意味が有るので、これをマネしてください。

あと変数は、代入を除いて変数定義をWinMainより上に追い出せばエラーが取れると思います。
※ あくまで仮の処理です。
aとか意味不明の変数名もなんとかして欲しい所です。
やってみます!!
すいません学生なものでこれから勉強時間なので
また、次の日などにでも試行錯誤しておきます!!!
回答ありがとうございました!!たぶん、明日やります!!

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#13

投稿記事 by usao » 12年前

>ですよね?
はい.(pとbの文章がすこし怪しいですが)結果としては合っています.
そこまでわかっているのであれば,
あなたの各関数でも同じようにデータを引き渡したり値をreturnしたりするようにすれば良いわけです.
(個々の変数をどこで定義するかは別の話ですが,例えばとりあえずWinMainにある変数を使うとして
 引数や戻り値で各関数とやりとりすればよい.)

この状態で無事に動作したならば,あとは分割コンパイルは悩むことはありませんよね.
ある関数の実装を別のソースファイルに移動したとしても,
それを利用するWinMain側からその関数の宣言が(例えば宣言が書かれたヘッダincludeして)みえてさえいればよいです.

Brail

Re: 分割コンパイルを詳しく教えてください!!

#14

投稿記事 by Brail » 12年前

コード:


#include "DxLib.h"
#define SHOT 20

/////////////////////////////////////////////////
///////////////////   プロトタイプ宣言
/////////////////////////////////////////////////
void Load();
void Playermove();
void Playershot();
void Playershotmove();
void Playermovecontrol();
void Dragonmove();
void Dragondamage();
void Complete();
////////////////////////////////////////////////
///////////////////    プロトタイプ宣言終了
////////////////////////////////////////////////


//////////////////////////////////////////////////
///////////////////    宣言
//////////////////////////////////////////////////
	
		int DragonX,DragonY,DragonM1,DragonM2,Dragon;
		int PlayerX,PlayerY,Player;
		int ShotX[SHOT],ShotY[SHOT],ShotFlag[SHOT],Shot;
		int ShotBackFlag,DragonHP,Damage;
		int DragonW,DragonH,ShotW,ShotH;
		int Back;
		int Blue,Green,GreenYello;
		int Black;
		int Font1;
		int Font2;


//////////////////////////////////////////////////
///////////////////    宣言終了
//////////////////////////////////////////////////


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

		if(DxLib_Init()==-1)return -1;


///////////////////////////////////////////////////////
/////////////////     代入
//////////////////////////////////////////////////////
	///////キャラクタ/////
		DragonX=320,DragonY=70,DragonM1=1,DragonM2=1,Dragon=LoadGraph("ドラゴン.png");
		PlayerX=320,PlayerY=400,Player=LoadGraph("キャラクタ.png");
		Shot=LoadGraph("弾.png");
		ShotBackFlag=0,DragonHP=5,Damage=0;
	//////////////////↑↑↑↑↑↑/////////////ここ変更でドラゴンの体力変更
	
	////////画面///////
		Back=LoadGraph("背景.png");
		Blue=GetColor(0,255,255),Green=GetColor(0,255,0),GreenYello=GetColor(150,255,0);
		Black=LoadGraph("Black.png");
		Font1=CreateFontToHandle(NULL,64,3);
		Font2=CreateFontToHandle(NULL,32,2);
		
		for(int i=0;i<SHOT;i++){
			ShotFlag[i]=0;
		}
		GetGraphSize(Shot  ,&ShotW  ,&ShotH);
		GetGraphSize(Dragon,&DragonW,&DragonH);

	
////////////////////////////////////////////////////////////////////
////////////////      
/////////////////////                    ///メインコード///
//////////////////////////
////////////////////////////////////////////////////////////////////

        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
        	
        	
        	Load();/////////////////////画像などの読み込み
        	
        	Playermove();///////////////自機の移動
        	Playershot();///////////////自機の弾
        	Playershotmove();///////////自機の発射した弾の移動
        	Playermovecontrol();////////自機を画面外に出さない
        	
        	Dragonmove();///////////////敵機の移動
        	Dragondamage();/////////////敵機の当たり判定
        	
			Complete();/////////////////倒したときの処理
        	
        		
			////////////////////////////////////////////////閉じる
			if(CheckHitKey(KEY_INPUT_ESCAPE)==1 || CheckHitKey(KEY_INPUT_RETURN)==1){
				break;
			}
        	
        	
		}
		DxLib_End(); ///////////////////////////////// DXライブラリ終了処理
        return 0;
}  

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////
//////////////////////////////////
////////////////////////                      ////****関数****////


////////////////******************読み込む関数********************
void Load(){
	//////////////////////////////背景、文字、自機、敵の読み込み
			DrawGraph(0,45,Back,TRUE);
			DrawFormatStringToHandle(500,400,Blue,Font1,"%03d",DragonHP-Damage);
			DrawRotaGraph(PlayerX,PlayerY,0.8,0.0,Player,TRUE);
			DrawRotaGraph(DragonX,DragonY,1.2,0.0,Dragon,TRUE);
}

///////////////******************自機の操作関数********************
void Playermove(){
	///////自機の操作
			if(CheckHitKey(KEY_INPUT_RIGHT)==1 || CheckHitKey(KEY_INPUT_D)==1){
				PlayerX+=3;
			}
			if(CheckHitKey(KEY_INPUT_LEFT)==1  || CheckHitKey(KEY_INPUT_A)==1){
				PlayerX-=3;
			}
			if(CheckHitKey(KEY_INPUT_UP)==1    || CheckHitKey(KEY_INPUT_W)==1){
				PlayerY-=3;
			}
			if(CheckHitKey(KEY_INPUT_DOWN)==1  || CheckHitKey(KEY_INPUT_S)==1){
				PlayerY+=3;
			}
}

/////////////*******************自機の弾関数**************************
void Playershot(){
	//////////////////////////////////////自機の弾
			if(CheckHitKey(KEY_INPUT_SPACE)|| CheckHitKey(KEY_INPUT_E) || CheckHitKey(KEY_INPUT_R)){
				if(ShotBackFlag==0){
					for(int i=0;i<SHOT;i++){
						if(ShotFlag[i]==0){
							ShotX[i]=PlayerX;
							ShotY[i]=PlayerY;
							ShotFlag[i]=1;

							break;
						}
					}
				}
				ShotBackFlag=1;
			}else{
				ShotBackFlag=0;
			}
}

/////////////********************自機の発射した弾の移動関数************
void Playershotmove(){
	////////////////////////////////自機の発射した弾を移動させる
			for(int i=0;i<SHOT;i++){
				if(ShotFlag[i]==1){
					ShotY[i]-=16;
					if(ShotY[i]<-80){
						ShotFlag[i]=0;
					}
					DrawRotaGraph(ShotX[i],ShotY[i],0.3,0.0,Shot,TRUE);
				}
			}
}

///////////*********************自機を画面から出さない制御関数**********
void Playermovecontrol(){
	
			///////////////////////////////////////自機を画面から出さない
			if(PlayerX>=640){
				PlayerX=640;
			}else if(PlayerX<=0){
				PlayerX=0;
			}else if(PlayerY>=480){
				PlayerY=480;
			}else if(PlayerY<=0){
				PlayerY=0;
			}
}

/////////////**************************ドラゴンの移動関数*****************
void Dragonmove(){
	
			/////////////////////////////////////////////////敵機を動かす
			//////////////////////////////////////////////////////横移動
			if(DragonM1==1){DragonX+=2;}
			if(DragonM1==0){DragonX-=2;}

			if(DragonX>600){
				DragonX=600;
				DragonM1=0;
			}
			if(DragonX<40){
				DragonX=40;
				DragonM1=1;
			}
			///////////////////////////////////////////////////////縦移動
			if(DragonM2==1){DragonY+=1;}
			if(DragonM2==0){DragonY-=1;}

			if(DragonY>100){
				DragonY=100;
				DragonM2=0;
			}
			if(DragonY<45){
				DragonY=45;
				DragonM2=1;
			}
}

////////////********************当たりの判定関数***************************
void Dragondamage(){
	///////////////////////////////////////////////当たり判定
			for(int i=0;i<SHOT;i++){
				
				if( ShotFlag[i]==1 ){
					if( ( ( ShotX[i] > DragonX && ShotX[i] < DragonX + DragonW ) ||
						( DragonX > ShotX[i] && DragonX < ShotX[i] + ShotW ) ) &&
						( ( ShotY[i] > DragonY && ShotY[i] < DragonY + DragonH ) ||
						( DragonY > ShotY[i] && DragonY < ShotY[i] + ShotH ) ) ){
							ShotFlag[i]=0;
							Damage+=1;
					}
				}
			}
}

////////////*********************倒した後の処理関数************************
void Complete(){
	/////////////////////////////////////////////倒した後の処理
	if(DragonHP=0){
				WaitTimer(200);
				DrawGraph(0,0,Black,FALSE);
				DrawStringToHandle(25,220,"C o m p l e t e d !!",Green,Font1);
				DrawStringToHandle(80,280,"Push!EnterKey!!",GreenYello,Font2);
	}
}


こんな感じにしてみました。
関数化は一応成功したみたいで、正常に動きました!!
usao さんが書きました:>ですよね?
はい.(pとbの文章がすこし怪しいですが)結果としては合っています.
pは200という値をbに参照しているということですか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#15

投稿記事 by softya(ソフト屋) » 12年前

関数名と内容が相変わらずズレていますので、見なおしてください。
あと引数化が残っていますね。この特にグローバルな変数(関数外の変数)を無くしてください。

それとそれと、
softya(ソフト屋) さんが書きました:ソースコードを見ましたが、エラーは置いておいておきますが初期化、移動と描画などが分離できていません。
d.3章 ゲームの設計と分割コンパイル(1)
http://dixq.net/g/d_03.html
にかかれていることは意味が有るので、これをマネしてください。
についてよく考えてみてください。
※ 全然、真似ができてないと言うことです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Brail

Re: 分割コンパイルを詳しく教えてください!!

#16

投稿記事 by Brail » 12年前

質問1.
void 終了処理(){
///////////////////
}
これで
break;
をするとエラーが出るのですがどうするのでしょうか?

質問2.
void 初期化(){
}
これは変数に値を代入する関数ということでしょうか?

質問3.
関数名と内容がズレているとはどういうことですか?

何度も申し訳ございません、駆け足でここまで勉強したので
本当に抽象的なものしかわからないです;;
お願いします!!

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#17

投稿記事 by usao » 12年前

>pは200という値をbに参照しているということですか?

うーん,何というか,主語と述語がどうなっているのかよくわからない…というか.

(0)int b = 100; → 最初,main()のローカル変数bの値は100です
(1)ChangeValueTo200( &b ); → 変数bのアドレス値 が引数として渡される
(2)void ChangeValueTo200( int *p ) に処理が移るとき:
 関数は値渡しなので,関数ChangeValueTo200()内のローカル変数であるpの値が(1)で渡された値で初期化される.
 (すなわち,ポインタ型変数 p の値は main()側のローカル変数であるbのアドレス値 になっている)
(3)*p = 200; → 【 {pの値(すなわちbのアドレス値)} によって指し示される場所(すなわち変数bの領域だ) 】 に 値200 を代入.
 (結果だけ言えば b=200; )

以上によって,関数ChangeValueTo200()を用いることによって,main()側のローカル変数の値を変更することができた.


…と,文章に書くと超長いんですけど,こういう意味でおっしゃられているのならばOKです.
最後に編集したユーザー usao on 2013年8月21日(水) 11:36 [ 編集 1 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#18

投稿記事 by softya(ソフト屋) » 12年前

>break;をするとエラーが出るのですがどうするのでしょうか?
break;出来るのは、switch文やfor,whileループ中だけです。
関数から抜けるのはreturn;を使います。

>これは変数に値を代入する関数ということでしょうか?
変数を初期化する処理を集めます。
ただし、関数名と関係のあるものだけを集めてください。

> 関数名と内容がズレているとはどういうことですか?
例えばLoad()がありますが、中身が描画というのはズレと言えます。
関数名で受ける印象と実際の動作が違うのはバグの元なので、やってはいけないことの筆頭です。
関数名としては動詞+名詞などの統一性のある名前が最終的にバグを生み出さない良いプログラムです。
そうですね、例えば本があったとして目次や章のタイトルと書かれている内容が激しくかけ離れていたら読みやすい本とは思えませんよね?
誤認する可能性は極力低くしないと良いプログラムは書けません。

【補足】
ファイル分割や関数分割もそうですが、大きなプログラムを書くために分かりやすくしてバグを減らすのが目的です。
そのためには、ちゃんとやるべき事やらないと元のプログラムよりも分かり辛い事が起きます。
これでは本末転倒で、目的と手段が逆になっていると言ってよいでしょう。
本来の目的であるプログラムを分かりやすくすると言う目的を忘れないでください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Brail

Re: 分割コンパイルを詳しく教えてください!!

#19

投稿記事 by Brail » 12年前

ありがとうございます!!
void Draw();
などに変更します!!

自分で見てわかるだけじゃだめなんですよね。。。
ほかの方の意見が聞けてよかったです!!

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#20

投稿記事 by softya(ソフト屋) » 12年前

Brail さんが書きました:ありがとうございます!!
void Draw();
などに変更します!!

自分で見てわかるだけじゃだめなんですよね。。。
ほかの方の意見が聞けてよかったです!!
自分で分かれば良いのなら、勢いだけで作れる小さなプログラムなら関数分解もファイル分割も言ってみれば必要ないです。
ただし、大きなプログラムなら作るのに半年とか平気で掛かるので、半年前に組んだ部分は自分で大抵は覚えていないのです。
なので、どこを直すのか自分で探しまわることになりますし、修正時に間違ってバグを埋め込む可能性も高いです。
これを他人にも分かるように組めれば、自分でも直すのは容易になるので自分のために行うって事です。
あと何となく組んでいるプログラムが整理されるので、プログラムの設計について考えるように成るというメリットも有ります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Brail

Re: 分割コンパイルを詳しく教えてください!!

#21

投稿記事 by Brail » 12年前

何度も申し訳ございません!!
今日はもうちょっとでまた勉強時間に入ってしまうので(夜はネット環境がないですし;;)
先に質問しておきます!!

質問1.わたしのこのコードで
Playermove や Playershot Dragonmove Dragondamage
などではなく
player
dragon
shot
damage

などに分けた方がよいでしょうか?
今はひとつのファイルに書いているのですが
いずれはファイルを何個も作るので
あくまで分割コンパイルとしてです!!

質問2.わたしのこのコードは変数が多いですか?
それとも適当ですか?少ないですか?

回答お願いします!!

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#22

投稿記事 by softya(ソフト屋) » 12年前

質問1.
更にplayerなどもinitializeやupdateやdrawに分けてください。
真似してくださいと書いたはずですが、一向に真似されないのが気になっています。

質問2.
単体の変数が多いです。構造体でまとめる必要があります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Brail

Re: 分割コンパイルを詳しく教えてください!!

#23

投稿記事 by Brail » 12年前

softya(ソフト屋) さんが書きました:質問1.
更にplayerなどもinitializeやupdateやdrawに分けてください。
真似してくださいと書いたはずですが、一向に真似されないのが気になっています。

質問2.
単体の変数が多いです。構造体でまとめる必要があります。
返信ありがとうございます!!

真似のほうは一応しているんですがエラーを取り除くために踏む手順が多かったのでとりあえず頭の中では出来てます。
すいません。書くのを忘れてました。

構造体はstruct ですね!
使ってみます!!
ありがとうございました!!

Brail

Re: 分割コンパイルを詳しく教えてください!!

#24

投稿記事 by Brail » 12年前

まだ、グローバル変数や構造体などは勉強中なのですが一応関数化をしてみましたので報告的な感じです。

コード:



#include "DxLib.h"
#define SHOT 20

	int DragonX,DragonY,DragonM1,DragonM2;
	int PlayerX,PlayerY;
	int ShotX[SHOT],ShotY[SHOT],ShotFlag[SHOT];
	int ShotBackFlag,DragonHP;
	int DragonW,DragonH,ShotW,ShotH;
	int BackGround;
	int Blue,Green,GreenYello;
	int Black;
	int Font1;
	int Font2;
	int Dragon,Player,Shot;
/////////////////////////////////////////////*******************
//////////////////////////////////**********
////////////////////////*********             ////**関数**////



////////////////////////////*********初期化関数**********//////////////////////////////////////
void Monitor_Initialize();
void Player_Initialize();
void Dragon_Initialize();
void Shot_Initialize();


///////////////////////////**********更新関数***********////////////////////////////////////
void Player_Update();
void Dragon_Update();
void Shot_Update();


//////////////////////////***********描画関数**********//////////////////////////////////////
void Monitor_Draw();
void Player_Draw();
void Dragon_Draw();
void Shot_Draw();


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

		if(DxLib_Init()==-1)return -1;
	

	//************初期化**************//
	
	Monitor_Initialize();
	Player_Initialize();
	Dragon_Initialize();
	Shot_Initialize();
	

		////////////////////////////////////////////////////////////////////
		////////////////      
		/////////////////////                  ///メインコード///
		//////////////////////////
		////////////////////////////////////////////////////////////////////

        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){


			//***************描画**************//
        	
        	Monitor_Draw();
        	Dragon_Draw();
        	Player_Draw();
        	Shot_Draw();
        	
        	
        	//***************計算*************//
        	
        	Player_Update();
        	Dragon_Update();
        	Shot_Update();
        	
        	
			///////////////////////////////////////////////当たり判定
			for(int i=0;i<SHOT;i++){
				
				if( ShotFlag[i]==1 ){
					if( ( ( ShotX[i] > DragonX && ShotX[i] < DragonX + DragonW ) ||
						( DragonX > ShotX[i] && DragonX < ShotX[i] + ShotW ) ) &&
						( ( ShotY[i] > DragonY && ShotY[i] < DragonY + DragonH ) ||
						( DragonY > ShotY[i] && DragonY < ShotY[i] + ShotH ) ) ){
							ShotFlag[i]=0;
							DragonHP-=1;
					}
				}
			}
			////////////////////////////////////////////////閉じる
			if(CheckHitKey(KEY_INPUT_ESCAPE)==1 || CheckHitKey(KEY_INPUT_RETURN)==1){
				break;
			}
			if(DragonHP<0){
				WaitTimer(200);
				DrawGraph(0,0,Black,FALSE);
				DrawStringToHandle(30,220,"C o m p l e t e d !!",Green,Font1);
				DrawStringToHandle(80,280,"Push!EnterKey!!",GreenYello,Font2);
			}

		}
		DxLib_End(); ///////////////////////////////// DXライブラリ終了処理
        return 0;
}  

		///////////////////////////////////////////////////////////////////////////////////////////
		////////////////////////////////////
		////////////////////////////                  ////////*****メインコード終了*****//////
		////////////////////
		////////////////////////////////////////////////////////////////////////////////////////////



/////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////****初期化****
void Monitor_Initialize(){
	BackGround=LoadGraph("背景.png");
	Black=LoadGraph("Black.png");
	Blue=GetColor(0,255,255),Green=GetColor(0,255,0),GreenYello=GetColor(150,255,0);
	Font1=CreateFontToHandle(NULL,64,3);
	Font2=CreateFontToHandle(NULL,32,2);
}


void Player_Initialize(){
	PlayerX=320,PlayerY=400;
	
	Player=LoadGraph("キャラクタ.png");
}


void Dragon_Initialize(){
	DragonX=320,DragonY=70,DragonM1=1,DragonM2=1;
	
	GetGraphSize(Dragon,&DragonW,&DragonH);
	Dragon=LoadGraph("ドラゴン.png");
}


void Shot_Initialize(){
	ShotBackFlag=0,DragonHP=5;
	
	GetGraphSize(Shot  ,&ShotW,&ShotH);
	Shot=LoadGraph("弾.png");
	
	for(int i=0;i<SHOT;i++){
		ShotFlag[i]=0;
	}
}


//////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
////////////////////////////////////////*****計算*****

void Player_Update(){
	////////////////////////////////////////////////////自機の操作
	if(CheckHitKey(KEY_INPUT_RIGHT)==1 || CheckHitKey(KEY_INPUT_D)==1){
		PlayerX+=3;
	}
	if(CheckHitKey(KEY_INPUT_LEFT)==1  || CheckHitKey(KEY_INPUT_A)==1){
		PlayerX-=3;
	}
	if(CheckHitKey(KEY_INPUT_UP)==1    || CheckHitKey(KEY_INPUT_W)==1){
		PlayerY-=3;
	}
	if(CheckHitKey(KEY_INPUT_DOWN)==1  || CheckHitKey(KEY_INPUT_S)==1){
		PlayerY+=3;
	}
	
	///////////////////////////////////////自機を画面から出さない
	if(PlayerX>=640){
		PlayerX=640;
	}else if(PlayerX<=0){
		PlayerX=0;
	}else if(PlayerY>=480){
		PlayerY=480;
	}else if(PlayerY<=0){
		PlayerY=0;
	}
}


void Dragon_Update(){
	
	/////////////////////////////////////////////////敵機を動かす
	
	/////////////////////////////**************************横移動
	if(DragonM1==1){DragonX+=2;}
	if(DragonM1==0){DragonX-=2;}
	
	if(DragonX>600){
		DragonX=600;
		DragonM1=0;
	}
	if(DragonX<40){
		DragonX=40;
		DragonM1=1;
	}
	/////////////////////////////**************************縦移動
	if(DragonM2==1){DragonY+=1;}
	if(DragonM2==0){DragonY-=1;}

	if(DragonY>100){
		DragonY=100;
		DragonM2=0;
	}
	if(DragonY<45){
		DragonY=45;
		DragonM2=1;
	}
}


void Shot_Update(){
	//////////////////////////////////////自機の弾
	if(CheckHitKey(KEY_INPUT_SPACE)|| CheckHitKey(KEY_INPUT_E) || CheckHitKey(KEY_INPUT_R)){
		if(ShotBackFlag==0){
			for(int i=0;i<SHOT;i++){
				if(ShotFlag[i]==0){
					ShotX[i]=PlayerX;
					ShotY[i]=PlayerY;
					ShotFlag[i]=1;

					break;///連射させないためのbreak
				}
			}
		}
		ShotBackFlag=1;
	}else{
		ShotBackFlag=0;
	}

	////////////////////////////////自機の発射した弾を移動させる
	for(int i=0;i<SHOT;i++){
		if(ShotFlag[i]==1){
			ShotY[i]-=16;
			if(ShotY[i]<-80){
				ShotFlag[i]=0;
			}
			DrawRotaGraph(ShotX[i],ShotY[i],0.3,0.0,Shot,TRUE);
		}
	}
}


////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
///////////////////////////////////*****描画*****

void Monitor_Draw(){
	//////////////////////////////背景、文字の描画
	DrawGraph(0,45,BackGround,TRUE);
	DrawFormatStringToHandle(500,400,Blue,Font1,"%03d",DragonHP);
}


void Player_Draw(){
	/////////////////////////////プレイヤーの描画
	DrawRotaGraph(PlayerX,PlayerY,0.8,0.0,Player,TRUE);
}


void Dragon_Draw(){
	/////////////////////////////ドラゴンの描画
	DrawRotaGraph(DragonX,DragonY,1.2,0.0,Dragon,TRUE);
}


void Shot_Draw(){
	
}

void Shot_Draw
の中になにもかかれていなかったりなど訂正する必要はたくさんあると思いますがこんな感じでよかったでしょうか?

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#25

投稿記事 by usao » 12年前

現在どういう手順で進めている流れなのかちょっと把握できてないのですが,
最初はWinMain()内にあった変数群がいつのまにか外部変数になってしまっていますね.

「俺は全て外部変数でいくぜ!!」とかいう話でないのであれば,
「関数化」というのは処理コードを物理的(?)に関数にわければよいという話ではなく,
呼び出し側と必要なデータのやり取りできるように書かないとダメです.
(そのために 変数a,bの値が変遷していく小さいコード例を示したのですが)

こういう形にするのは難しいですか?

コード:

int WINAPI WinMain( ... )
{
   int PlayerX=0, PlayerY=0;
   int Player=-1;  //※この変数名ではグラフィックハンドルだとわかりにくいね
   ...
   Player_Initialize( &PlayerX, &PlayerY, &Player );
   ...
   while( ... )
   {
      ...
      Player_Draw( PlayerX, PlayerY, Player );
      Player_Update( &PlayerX, &PlayerY );
      ...
   }
   ...
}
で,例えばプレイヤーに関する3つの変数を構造体にまとめるならこんな感じとか.

コード:

//座標(x,y)を表す
typedef struct Position
{
   int x, y;
} Position;

//プレイヤ用変数をまとめる
typedef struct PlayerData
{
   Position Pos;  //座標
   int hGraphic;  //グラフィックハンドル
} PlayerData;

//
int WINAPI WinMain( ... )
{
   PlayerData Player = { 0,0, -1 };
   ...
   Player_Initialize( &Player );
   ...
   while( ... )
   {
      ...
      Player_Draw( Player );  //※引数の型が const PlayerData * であれば &Player
      Player_Update( &(Player.Pos) );
      ...
   }
   ...
}
[追記]
あと,line181の

コード:

}else if(PlayerY>=480){
ここがelse if になってるのはバグなんじゃないかと思う.(xとyが同時に範囲外に出たとき,xだけしか調整されない)

Brail

Re: 分割コンパイルを詳しく教えてください!!

#26

投稿記事 by Brail » 12年前

丁寧にありがとうございます!!
試してみたら確かに同時に出たときがおかしかったです!!
X軸とY軸とでわけたら大丈夫になりました!!ありがとうございました!!
あと、PlayerなどはPlayerHandleのようにHandleをつけました!!


構造体とかのやりかたはわかるんですがどうやらポインタとかの参照について
もっと勉強というか理解を深める必要があるみたいです;;

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#27

投稿記事 by usao » 12年前

あ,現在,ここ↓の Player.cpp の書き方を目指しているということなのかな?
d.3章 ゲームの設計と分割コンパイル(1)
http://dixq.net/g/d_03.html
だとしたらちょっと余計なことを言ったかもしれませんね.
現在の方針とちょっと違うというか.

リンク先では以下のように書かれていますね.
私が言っている内容は(下記引用の)前半の段落で言っていることですね.
で,リンク先ページで実際にやっている話は後半の段落の内容なのですね.
大丈夫です。関数さえ呼べればそれでいいのです。
必要な情報は関数の引数で与えてやり、取得したい時は関数の返り値で得ればいいのです。
(ポインタを引数に持たせて入れて返す仕組みでもok)

本サイトでは、「ファイル内のみで使用できるグローバル変数」を使ってこれを実現します。
変数の前に static と付けてグローバル変数を定義すると、そのファイル内でのみ使用出来るグローバル変数になります。
#個人的には分割コンパイルとか言う前に「関数,ポインタ」あたりをしっかりやられたほうがよほど近道だとは思いますが.
 (今後もCで何かをやっていくなら,という意味で)

Brail

Re: 分割コンパイルを詳しく教えてください!!

#28

投稿記事 by Brail » 12年前

典型的な初心者なもので
自分でコードを書いていくというよりは
サンプルコードを模写し
それを元にどんどん増やしていくという形になってしまっていて

自作関数←わかる
ポインタ←わかる

自作関数とポインタをうまくつかう←???

になってしまっているので勉強しなおしてみようと思います

Brail

Re: 分割コンパイルを詳しく教えてください!!

#29

投稿記事 by Brail » 12年前

変数はまだ何にも変えていないのでエラーがでるのはわかってたのですが
これからどういう風にしていけばよいのかわからないのでお願いします!!

105 IntelliSense: 識別子 "Shot_Update" が定義されていません c:\Users\**\Documents\Visual Studio 2012\Projects\DivideTest\Main.cpp 72 10

のようなエラーがたくさんでました
内容は
・なんとかが定義されていません
・なんとか識別子が見つかりませんでした
・なんとか:定義されていない識別子です
でした
3番目は変数のやつなのでまだ何にもいじってないのでわかるのですが
なんとかが定義されていませんはどうも関数化させた
Player_Initialize
などが悪いようですがPlayerの関数はうまくできてます
それ以外のMonitorやDragon Shot関数がうまくできてません
何が原因かどう見分ければよいのですか???

2番目も同じ問題だと思います。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#30

投稿記事 by softya(ソフト屋) » 12年前

ソースコードを見せてもらえますか。それが早いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Brail

Re: 分割コンパイルを詳しく教えてください!!

#31

投稿記事 by Brail » 12年前

Main.cpp

コード:



#include "DxLib.h"
#define SHOT 20


//////////////////////////////////////分割したファイルを読み込む
#include"Player.h"
#include"Dragon.h"
#include"Shot.h"
#include"Monitor.h"


	int DragonX,DragonY,DragonM1,DragonM2;
	int PlayerX,PlayerY;
	int ShotX[SHOT],ShotY[SHOT],ShotFlag[SHOT];
	int ShotBackFlag,DragonHP;
	int DragonW,DragonH,ShotW,ShotH;
	int BackGround;
	int Blue,Green,GreenYello;
	int Black;
	int Font1;
	int Font2;
	int Dragon,Player,Shot;
	
/////////////////////////////////////////////*****************
//////////////////////////////////**********
////////////////////////*********        ////**関数の宣言**////

void Completed();
void Damage();


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

		if(DxLib_Init()==-1)return -1;
	

	//************初期化**************//
	
	Monitor_Initialize();
	Player_Initialize();
	Dragon_Initialize();
	Shot_Initialize();
	

		////////////////////////////////////////////////////////////////////
		////////////////      
		/////////////////////                  ///メインコード///
		//////////////////////////
		////////////////////////////////////////////////////////////////////

        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
        	
        	
        	Damage();///////////////当たり判定


			//***************描画**************//
        	
        	Monitor_Draw();
        	Dragon_Draw();
        	Player_Draw();
        	Shot_Draw();
        	
        	
        	//***************計算*************//
        	
        	Player_Update();
        	Dragon_Update();
        	Shot_Update();
        	
			
			////////////////////////////////////////////////閉じる
			if(CheckHitKey(KEY_INPUT_ESCAPE)==1 || CheckHitKey(KEY_INPUT_RETURN)==1){
				break;
			}
        	////////倒した後
        	Completed();
        }
	
		DxLib_End(); ///////////////////////////////// DXライブラリ終了処理
        return 0;
}

		/////////////////////////////////////////////////////////////////////////////
		/////////////////////////////////
		/////////////////////////           /////メインコード終了////
		/////////////////
		//////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////当たり判定
void Damage(){        	
	
	for(int i=0;i<SHOT;i++){
		
		if( ShotFlag[i]==1 ){
			if( ( ( ShotX[i] > DragonX && ShotX[i] < DragonX + DragonW ) ||
				( DragonX > ShotX[i] && DragonX < ShotX[i] + ShotW ) ) &&
				( ( ShotY[i] > DragonY && ShotY[i] < DragonY + DragonH ) ||
				( DragonY > ShotY[i] && DragonY < ShotY[i] + ShotH ) ) ){
					ShotFlag[i]=0;
					DragonHP-=1;
			}
		}
	}
}
Player.cpp

コード:



#include "DxLib.h"


void Player_Initialize(){
	PlayerX=320,PlayerY=400;
	
	Player=LoadGraph("キャラクタ.png");
}

void Player_Update(){

	////////////////////////////////////////////////////自機の操作
	if(CheckHitKey(KEY_INPUT_RIGHT)==1 || CheckHitKey(KEY_INPUT_D)==1){
		PlayerX+=3;
	}
	if(CheckHitKey(KEY_INPUT_LEFT)==1  || CheckHitKey(KEY_INPUT_A)==1){
		PlayerX-=3;
	}
	if(CheckHitKey(KEY_INPUT_UP)==1    || CheckHitKey(KEY_INPUT_W)==1){
		PlayerY-=3;
	}
	if(CheckHitKey(KEY_INPUT_DOWN)==1  || CheckHitKey(KEY_INPUT_S)==1){
		PlayerY+=3;
	}
	
	///////////////////////////////////////自機を画面から出さない
	if(PlayerX>=640){
		PlayerX=640;
	}else if(PlayerX<=0){
		PlayerX=0;
	}
	if(PlayerY>=480){
		PlayerY=480;
	}else if(PlayerY<=0){
		PlayerY=0;
	}
}


void Player_Draw(){
	/////////////////////////////プレイヤーの描画
	DrawRotaGraph(PlayerX,PlayerY,0.8,0.0,Player,TRUE);
}
Player.h

コード:



#ifndef DEF_PLAYERMGR_H //二重include防止

#define DEF_PLAYERMGR_H


////////////////////////////*********Player関数**********//////////////////////////////////////
void Player_Initialize();
void Player_Update();
void Player_Draw();

#endif
Dragon.cpp

コード:



#include "DxLib.h"


void Dragon_Initialize(){
	DragonX=320,DragonY=70,DragonM1=1,DragonM2=1;
	
	Dragon=LoadGraph("ドラゴン.png");
	GetGraphSize(Dragon,&DragonW,&DragonH);
}


void Dragon_Update(){
	
	/////////////////////////////////////////////////敵機を動かす
	
	/////////////////////////////**************************横移動
	if(DragonM1==1){DragonX+=2;}
	if(DragonM1==0){DragonX-=2;}
	
	if(DragonX>600){
		DragonX=600;
		DragonM1=0;
	}
	if(DragonX<40){
		DragonX=40;
		DragonM1=1;
	}
	/////////////////////////////**************************縦移動
	if(DragonM2==1){DragonY+=1;}
	if(DragonM2==0){DragonY-=1;}

	if(DragonY>100){
		DragonY=100;
		DragonM2=0;
	}
	if(DragonY<45){
		DragonY=45;
		DragonM2=1;
	}
}


void Dragon_Draw(){
	/////////////////////////////ドラゴンの描画
	DrawRotaGraph(DragonX,DragonY,1.2,0.0,Dragon,TRUE);
}


Dragon.h

コード:



#ifndef DEF_PLAYERMGR_H //二重include防止

#define DEF_PLAYERMGR_H


///////////////////////////**********Dragon関数***********////////////////////////////////////
void Dragon_Initialize();
void Dragon_Update();
void Dragon_Draw();

#endif
Shot.cpp

コード:



#include "DxLib.h"

#define SHOT 20

void Shot_Initialize(){
	ShotBackFlag=0,DragonHP=5;
	
	Shot=LoadGraph("弾.png");
	GetGraphSize(Shot  ,&ShotW,&ShotH);
	for(int i=0;i<SHOT;i++){
		ShotFlag[i]=0;
	}
}


void Shot_Update(){

	//////////////////////////////////////自機の弾
	if(CheckHitKey(KEY_INPUT_SPACE)|| CheckHitKey(KEY_INPUT_E) || CheckHitKey(KEY_INPUT_R)){
		if(ShotBackFlag==0){
			for(int i=0;i<SHOT;i++){
				if(ShotFlag[i]==0){
					ShotX[i]=PlayerX;
					ShotY[i]=PlayerY;
					ShotFlag[i]=1;

					break;///連射させないためのbreak
				}
			}
		}
		ShotBackFlag=1;
	}else{
		ShotBackFlag=0;
	}

	////////////////////////////////自機の発射した弾を移動させる
	for(int i=0;i<SHOT;i++){
		if(ShotFlag[i]==1){
			ShotY[i]-=16;
			if(ShotY[i]<-80){
				ShotFlag[i]=0;
			}
			DrawRotaGraph(ShotX[i],ShotY[i],0.3,0.0,Shot,TRUE);
		}
	}
}


void Shot_Draw(){
	
}
Shot.h

コード:



#ifndef DEF_PLAYERMGR_H //二重include防止

#define DEF_PLAYERMGR_H


//////////////////////////***********Shot関数**********//////////////////////////////////////
void Shot_Initialize();
void Shot_Update();
void Shot_Draw();

#endif
Monitor.cpp

コード:



#include "DxLib.h"


void Monitor_Initialize(){

	BackGround=LoadGraph("背景.png");
	Black=LoadGraph("Black.png");
	Blue=GetColor(0,255,255),Green=GetColor(0,255,0),GreenYello=GetColor(150,255,0);
	Font1=CreateFontToHandle(NULL,64,3);
	Font2=CreateFontToHandle(NULL,32,2);
}


void Monitor_Draw(){

	//////////////////////////////背景、文字の描画
	DrawGraph(0,45,BackGround,TRUE);
	DrawFormatStringToHandle(500,400,Blue,Font1,"%03d",DragonHP);
}


void Completed(){
	if(DragonHP<0){
			WaitTimer(200);
			DrawGraph(0,0,Black,FALSE);
			DrawStringToHandle(30,220,"C o m p l e t e d !!",Green,Font1);
			DrawStringToHandle(80,280,"Push!EnterKey!!",GreenYello,Font2);
	}
}



Monitor.h

コード:



#ifndef DEF_PLAYERMGR_H //二重include防止

#define DEF_PLAYERMGR_H


///////////////////////************Monitor関数***********//////////////////////////////
void Monitor_Initialize();
void Monitor_Draw();
void Completed();

#endif

********************************************
変数をいじってないのはとりあえずこんな感じで分割したらいいのかなーっていうのをつくり
そのあとで変数をしっかり直そうと思っていたからです。

分割したあとにMain.cppをみたら関数の呼び出しのところに赤い波線があったので
質問させていただきました。

見づらいのは本当に申し訳ございません。

回答よろしくお願いいたします!!

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#32

投稿記事 by softya(ソフト屋) » 12年前

ファイルを分ける前に構造体にして引数化と言う流れだと思っていたのですが、全部いっぺんにやるにはBrailさんの理解度ではわけが分からなくなると思いますよ。
まぁ、グローバル変数化でコンパイルを通すことも出来ますが、私は次のよう流れで解決することをおすすめします。

1.構造体化
2.引数化
3.ファイル分割
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: 分割コンパイルを詳しく教えてください!!

#33

投稿記事 by ISLe » 12年前

翻訳単位に分けるのに、必ずしもインスタンスを意識する必要はないと思いますが。
むしろインスタンスを意識したコードに変更するのは段階的に早すぎる気がします。

閉鎖

“C言語何でも質問掲示板” へ戻る