ページ 11

ヘッダファイルから2つのソースへの流用ってできないんでしょうか

Posted: 2010年12月12日(日) 14:06
by マグロ丼
またご教授承りに参りました。
今横スクロールのシューティングゲームを製作しているのですが、少し詰まってしまいました。
struct.hを読み込んだGV.hから二つのソースファイルにch_tを呼び出したんですが、多重定義のエラーがでてしまいました。
かといって、GLOBALをつけると今度は未解決のエラーがでてしまいました。
未解決が出たときのソースを張ります・゚・(つД`)・゚・

コード:

#ifndef __STRUCT_H__
#define __STRUCT_H__
struct shot{
    int x,y;
    int flag;
};
typedef struct{
        int x,y,img,muki,walking_flag,attack_flag;
}ch_t;
GLOBAL ch_t ch;//キャラクターの位置
typedef struct{
        int x,y,img,muki,flag,attack_flag,hp;
}enemy_t;
GLOBAL enemy_t en;
GLOBAL struct shot tama[50];

#endif

コード:

#ifndef __GV_H__
#define __GV_H__
#include "DxLib.h"
#include "math.h"

#ifdef GLOBAL_INSTANCE
#define GLOBAL
#else
#define GLOBAL extern 
#endif
#include "struct.h"

//画像用変数宣言部
GLOBAL int image[12];	//キャラクタ画像12枚分 X2(変身用)
GLOBAL int img_enemy[1];	//敵画像9枚
GLOBAL int image_tama;
GLOBAL char Key[256] ;
      //発射してからのカウントをする変数。
GLOBAL int counter=0;

//フラグ・ステータス変数
GLOBAL int func_state,stage_count;	//関数制御用変数
#endif
[player]

コード:

#include "GV.h"
   
 void chara_move(){   if(ch.x%30==0){         //座標が30で割り切れたら入力可能          
        ch.walking_flag=1;//歩くフラグを立てる。
        
        if( Key[ KEY_INPUT_RIGHT   ]  == 1 )  //→ボタンが押されたら                     
            ch.muki=1;         //右向きフラグを立てる
		else if( Key[ KEY_INPUT_LEFT   ]  == 1 )  //→ボタンが押されたら                     
            ch.muki=2;         //←向きフラグを立てる
        else                                    
            //何のボタンも押されてなかったら
            ch.walking_flag=0; //歩かないフラグを立てる

        if( Key[ KEY_INPUT_SPACE   ]  == 1 )
            ch.attack_flag=1;//攻撃フラグをタテル。    
    }
    if(ch.walking_flag==1){        //歩くフラグが立っていたら    
        if(ch.muki==1){        //→向きならch.x座標を増やす        
			ch.x++;
			ch.img=image[(ch.x%30)/5 +6]; }
		
		else if(ch.muki==2){        //←向きならch.x座標を減らす       
			ch.x--;
		    ch.img=image[(ch.x%30)/5 +6]; }}

    else if(ch.walking_flag==0){
        ch.img=image[(ch.x%30)/2+0];
	}}
[main]

コード:

#include"GV.h"

#define STAGE1_END_X 1920
int White;
char Key[256] ;
void chara_move();
//場面処理用
int function_status;
//カメラ
int camerax=0,cameray=0; 
//キャラクターシート
int image[12];
int image_enemy;
int image_op;

//弾画像
int image_tama;

//背景画像
int image_stage;

//始まった時間
int StartTime;

void op0(){
    DrawGraph( 0 , 0 , image_op , TRUE ) ;//画像を描画
    
    //Xキーが押されてたら
    if(Key[KEY_INPUT_RETURN]==1)           
        function_status=1;}

void main1(){
    
	int i;
    
    if((GetNowCount() - StartTime) > 60000){    //1ステージの制限時間は6秒
        function_status=2;
    }
chara_move();

    if(ch.attack_flag==1){
        ch.img=image[(ch.x%10)/5+2];
        ch.attack_flag=0;
    }
    if(counter<5)                        //前にエンターを押してから5カウント未満なら              
        counter++;                       //カウントアップ 
    else if( Key[ KEY_INPUT_SPACE]  == 1 ){//5カウント以上たっていたら
        counter=0;//カウンターを戻す

        for(i=0;i<50;i++){
            if(tama[i].flag==0){     //発射していない玉を探し、        
                tama[i].x=ch.x+100;
                tama[i].y=ch.y;
                tama[i].flag=1;  //発射フラグを立てる
                break;
            }
        }                           
    }
camerax=ch.x;
 if(camerax<0) camerax=0;
 if(camerax>1280) camerax=1280; 

DrawGraph( -camerax , -cameray ,image_stage, TRUE);//ステージを描画
DrawGraph( ch.x-camerax , ch.y-cameray , ch.img , TRUE ) ;//画像を描画
    
        for(i=0;i<50;i++){
        if(tama[i].flag==1){ //発射している玉なら
            tama[i].x+=5; //xをキャラ位置分増やす 
            DrawGraph( tama[i].x-camerax , tama[i].y-cameray , image_tama , TRUE );//玉を描画
            if(tama[i].x < -32+camerax || tama[i].x > 672+camerax){ //もし画面外まで来たら
                tama[i].flag=0; //発射フラグを戻す
            }
		}
	DrawGraph(en.x, en.y , image_enemy , TRUE ) ;//画像を描画
		}
	if(ch.x>STAGE1_END_X-150)
		function_status=2;
    if(Key[KEY_INPUT_X]==1)           
        function_status=2;
}


void boss(){
	  White   = GetColor( 255 , 255 , 255 ) ; // 白色の値を取得
	if(Key[KEY_INPUT_Z]==1){
      DrawString(0,0, "Zを押せ!" , White);;}           
        function_status=3;

}
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");
    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
    }
                  //初期化処理
        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:
                 main1();
		break;
            case 2:
	boss();
                break;
			default:       
                DxLib_End() ;                                // DXライブラリ使用の終了処理                
                return 0;                
                break;        
        }
        ScreenFlip();
    }
    DxLib_End();
    return 0;
}
エラーは
1>player.obj : error LNK2005: "int counter" (?counter@@3HA) は既に main.obj で定義されています。
1>main.obj : error LNK2001: 外部シンボル ""struct enemy_t en" (?en@@3Uenemy_t@@A)" は未解決です。
1>main.obj : error LNK2001: 外部シンボル ""struct shot * tama" (?tama@@3PAUshot@@A)" は未解決です。
1>main.obj : error LNK2001: 外部シンボル ""struct ch_t ch" (?ch@@3Uch_t@@A)" は未解決です。
1>player.obj : error LNK2001: 外部シンボル ""struct ch_t ch" (?ch@@3Uch_t@@A)" は未解決です。
1>C:\Users\maguro\Desktop\LeftMyHeart\Debug\LeftMyHeart.exe : fatal error LNK1120: 外部参照 3 が未解決です。
よろしくおねがいしますorz

Re: ヘッダファイルから2つのソースへの流用ってできないんでしょうか

Posted: 2010年12月12日(日) 14:18
by 紅葉
変数宣言の前にstaticを付けてみてください。
詳しくソースを見ていないので何とも言えませんが解決するかと思います。
例)int counter→static int counter等

又、AのソースからXという変数をBのソースでみたい場合はexternを使えば取得できます。
参考までに・・・

Re: ヘッダファイルから2つのソースへの流用ってできないんでしょうか

Posted: 2010年12月12日(日) 14:52
by マグロ丼
紅葉さんありがとうございましたヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノ
また一つ賢くなった気がします。

Re: ヘッダファイルから2つのソースへの流用ってできないんでしょうか

Posted: 2010年12月12日(日) 16:00
by Dixq (管理人)
グローバル変数を用いたくない場合は、用いなくても設計出来ます。
例えばGet関数等を使って値を返すなどすれば変数の値が参照出来ます。
また、値を変更したい時はSet関数等を通すことが出来ます。
ヘッダファイルには関数のプロトタイプ宣言さえすればいいのです。

後、最初がアンダーバー2つか、アンダーバーの後が大文字の変数は予約されているので、使ってはいけない決まりになっていますので、
違う名前にした方がいいかもしれません。

Re: ヘッダファイルから2つのソースへの流用ってできないんでしょうか

Posted: 2010年12月12日(日) 18:15
by マグロ丼
管理人様
了解です。もう頭が破裂しそうですがなんとか食い下がって行きます・・・