ソースの読み込み。

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

ソースの読み込み。

#1

投稿記事 by マグロ丼 » 14年前

またご教示いただきに参りました。
ここでの回答を参考にしながらソースを組み分けることができました!
しかし、ソースファイルの読み込みかたが悪いのか、キャラクターが描画できなくなってしまいました。
背景は描画できたようなのですが、弾丸の描画はカクカクだし、キャラクターは動かないので困っています。
[graph]

コード:

#include "GV.h"
extern void chara_move();

void graph(){
	chara_move();
	LoadDivGraph( "chara_sheet.png" , 12 , 3 , 4 , 250 , 250 , image );//画像を分割してimage配列に保存
    image_stage = LoadGraph( "stage.png" ) ;//背景の読み込み
	DrawGraph( ch.x-camerax , ch.y-cameray , ch.img , TRUE ) ;//画像を描画
	DrawGraph( -camerax , -cameray ,image_stage, TRUE);//ステージを描画

}
[main]

コード:

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化
 
    function_status=0;

	image_enemy=LoadGraph("enemy.png");
	image_op=LoadGraph("op.png");
    image_tama = LoadGraph("tama.png");

    ch.x   =0;
    ch.y   =240;
    ch.muki=3;
    ch.attack_flag;
    ch.walking_flag=0;
    int i;
    extern void chara_move();
    extern void graph();
    for(i=0;i<50;i++){                  //初期化処理
        tama[i].x=640/2; tama[i].y=480; //座標代入
        tama[i].flag=0;                 //飛んでいない事を示すフラグ=0
    }
                  //初期化処理
        if(en.x=640/2,en.y=480)en.flag=0;
	StartTime = GetNowCount();
    while(ProcessMessage()==0 && ClearDrawScreen()==0 && !GetHitKeyStateAll(Key) && Key[KEY_INPUT_ESCAPE]==0){
          //↑メッセージ処理          ↑画面をクリア           ↑入力状態を保存       ↑ESCが押されていない       
        switch(function_status){                        
            case 0:
               op0();
                break;
            case 1: 
 			chara_move();
                 graph();
		main1();
				break;
            case 2:
				boss();
                break;
			default:       
                DxLib_End() ;                                // DXライブラリ使用の終了処理                
                return 0;                
                break;        
        }

        ScreenFlip();
    }
 
    DxLib_End();
    return 0;
}
どこにソースを読み込ますのが正解なんでしょうか。
もしくはどうやったらキャラが描画されるようになるのでしょうか。
ご教示よろしくお願いします。

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

Re: ソースの読み込み。

#2

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

ファイル分割の問題よりも関数の分け方の問題です。
while(ProcessMessage()==0
のループ内で
LoadGraph()
LoadDivGraph()
を呼び出せばすればロード時間分だけ確実に描画が遅くなります。
ロードは原則、ProcessMessageのループの前に終わらせてください。

それと
extern void chara_move();
extern void graph();
はfuntion.hに書くべきものだと思いますよ。

さいごにもう一つ、
>どこにソースを読み込ますのが正解なんでしょうか。
と言う言葉から、ソースは読み込むものと勘違いされてますが読み込むのはヘッダだけです。
cppはコンパイル後にそれぞれのオブジェクトファイルとなり、それがリンク(結合)されて実行ファイルとなります。
なので、ソースを読み込ますという行為そのものがありません。
ソースファイル内の関数であろうが、ソースファイル外の関数であろうが関数を呼び出したところで呼び出されますので、違いはないと思ってください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マグロ丼

Re: ソースの読み込み。

#3

投稿記事 by マグロ丼 » 14年前

そうだったんですか……
ヘッダと同列に考えてました。
イメージ的には

ヘッダファイル+ソースファイル[main.cpp]=プログラム
              ↑追加
        他のソースファイル[追加された後は用済み]

だと思っていたのですが違うんですねぇ。

ヘッダファイル+ソースファイル[main.cpp]=プログラム
              ||イコール
        他のソースファイル[追加された後も実行]
ということでいいんでしょうか…

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

Re: ソースの読み込み。

#4

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

コンパイルとリンクとは、マグロ丼さんのコードだと
main.cppはコンパイルされてmain.objになり、player.cppはコンパイルされてplayer.objになります。
それぞれmain.objはmain.cppソース内にある関数だけを含んでいて、player.objはplayer.cppソース内にある関数だけを全て含んでいます。
main.objとplayer.objはリンカが結合して実行ファイル(exe)となります。
結合ってのは、関数呼び出しやグローバル変数のアドレス解決するだけなので実体は移動しません。
って感じなのです。

関数の呼び出し順番は、ソースコードのmainに書かれた順番に従いますので、ファイル分割しているしていないはまったく関係ありませんし、ソースファイル内の順番やインクルードの順番、リンクの順番も関係ありません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マグロ丼

Re: ソースの読み込み。

#5

投稿記事 by マグロ丼 » 14年前

んん、なるほど。
疑問があるんですが、

コード:

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

    function_status=0;
   	image_op=LoadGraph("op.png");
    image_tama = LoadGraph("tama.png");
    LoadDivGraph( "chara_sheet.png" , 12 , 3 , 4 , 250 , 250 , image );//画像を分割してimage配列に保存
    image_stage = LoadGraph( "stage.png" ) ;//背景の読み込み
    ch.x   =0;
    ch.y   =240;
    ch.muki=3;
    ch.attack_flag;
    ch.walking_flag=0;
    int i;
    for(i=0;i<50;i++){                  //初期化処理
        tama[i].x=640/2; tama[i].y=480; //座標代入
        tama[i].flag=0;                 //飛んでいない事を示すフラグ=0
    }
    StartTime = GetNowCount();
    while(ProcessMessage()==0 && ClearDrawScreen()==0 && !GetHitKeyStateAll(Key) && Key[KEY_INPUT_ESCAPE]==0){
          //↑メッセージ処理          ↑画面をクリア           ↑入力状態を保存       ↑ESCが押されていない       
        switch(function_status){                        
            case 0:
                op();
                break;
            case 1:
				main1();
                break;
            case 2:
                break;
            default:       
                DxLib_End() ;                                // DXライブラリ使用の終了処理                
                return 0;                
                break;        
        }
        ScreenFlip();
    }
    DxLib_End();
    return 0;
}
↑のコードのLoadGraph関数を全てload.cppの中に入れて関数loadとして宣言した場合、

コード:

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化
    function_status=0;
    load();
    ch.x   =0;
    ch.y   =240;
    ch.muki=3;
    ch.attack_flag;
    ch.walking_flag=0;
    int i;
    for(i=0;i<50;i++){                  //初期化処理
        tama[i].x=640/2; tama[i].y=480; //座標代入
        tama[i].flag=0;                 //飛んでいない事を示すフラグ=0
    }
    StartTime = GetNowCount();
    while(ProcessMessage()==0 && ClearDrawScreen()==0 && !GetHitKeyStateAll(Key) && Key[KEY_INPUT_ESCAPE]==0){
          //↑メッセージ処理          ↑画面をクリア           ↑入力状態を保存       ↑ESCが押されていない       
        switch(function_status){                        
            case 0:
                op();
                break;
            case 1:
	        main1();
                break;
            case 2:
                break;
            default:       
                DxLib_End() ;                                // DXライブラリ使用の終了処理                
                return 0;                
                break;        
        }
        ScreenFlip();
    }
    DxLib_End();
    return 0;
}
こうやると真っ暗になってしまうのですが、これはなんでなのでしょうか……

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

Re: ソースの読み込み。

#6

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

ちゃんとイメージデータの値が受け渡されているか、loadと描画時でimage_opの値等を比べてみてください。
どこかでデータを失うような行為をしているとしか思えません。

よく分からないなら、プロジェクト全体を何処かのアップローダに上げてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マグロ丼

Re: ソースの読み込み。

#7

投稿記事 by マグロ丼 » 14年前

http://upload.jpn.ph/50/bin/bin1201.zip.html
DLkey[maguro]
これを上記の変更してしまうと真っ暗になってしまいします。

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

Re: ソースの読み込み。

#8

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

gv.hなどでstaticと書いているのが原因ですね。
基本的にヘッダにstaticは書かないほうが良いです。
staticと書くと各objに同じ名前の変数が作られますが、externでは無いのでリンクされない別変数とみなされます。
つまり、main,load,graphで各々同じ名前の別の変数が作られることになります。そうするとloadで値を入れても参照できるのはload.cppのソースファイル内の関数だけとなります。

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

マグロ丼

Re: ソースの読み込み。

#9

投稿記事 by マグロ丼 » 14年前

なるほど……ヘッダ内にstaticを書かないほうがいいのですね。

>なぜGLOBALをやめたのでしょうか?
GLOBALだと多重定義や未解決のエラーがでてしまうのです……
その点をstaticにするとキチンと(?)デバッグできたのでGLOBALをやめることにしました。

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

Re: ソースの読み込み。

#10

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

マグロ丼 さんが書きました:なるほど……ヘッダ内にstaticを書かないほうがいいのですね。

>なぜGLOBALをやめたのでしょうか?
GLOBALだと多重定義や未解決のエラーがでてしまうのです……
その点をstaticにするとキチンと(?)デバッグできたのでGLOBALをやめることにしました。
それは問題点を握りつぶして問題の先送りをしただけですね。
ちゃんとGLOBALで通るプログラムを作りましょう。
staticは、大雑把に言うとソースファイル単位のローカル変数の様な働きをします(厳密には色々違います)。
例えば関数内のローカル変数は同じ名前でも別関数にあれば値はお互いに影響しませんよね。それと同じことがソースファイル単位で起こるわけです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マグロ丼

Re: ソースの読み込み。

#11

投稿記事 by マグロ丼 » 14年前

わかりました……
どうやったら多重定義や未解決をおこさないように分割できるのでしょうか。
元のソースだときちんとデバッグできるのに。
ヘッダ内にextern void load();
と打ってもなんの解決にもなりませんでしたし……
せめてヒントだけでもお教えくださいませんか。゚(゚´Д`゚)゚。

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

Re: ソースの読み込み。

#12

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

まず、gv.hにグローバル変数を集めると言う龍神録の手法で作るなら、各ソースファイル(以下cpp)にグローバル変数を書いてはいけません。
全てgv.hに書いてください。そして、各cpp内だけで使う変数はstaticを付けて各cppに書いてください。gb.hにstaticな変数を持ち込んではいけません。
それとmain.cpp先頭に#define GLOBAL_INSTANCEを書いてくだい。
これで解決するはずです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マグロ丼

Re: ソースの読み込み。

#13

投稿記事 by マグロ丼 » 14年前

解決しました!!!!!!
メチャクチャ嬉しいです!!!!
softyaさんありがとうございました!!!!!!ヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノ

閉鎖

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