2DRPG作成中です。
分割コンパイル3の説明が分からないから分割しないままmain.cに書き続けてきたんですが、
main.cがもう2000行以上あって、どこに何があるかこんがらがってきたのでもう一回分割に挑戦しました。
ですが、やはりサイトの説明の意味がよく分からないので質問します・・・。
質問が2点あります。
1.
#include A.hと書けば、A.hの中身を最初に書いたことと同じって説明がありましたよね。
なので、例えばmain.cとA.hとA.cってファイルを作ったとして、
A.h-----------------
#ifndef DEF_LOAD_H
#define DEF_LOAD_H
int Box1;
Box1 = LoadGraph(~~)
void Test_Graph();
#endif
---------------------
とか書いておいて、A.cに
A.cpp-----------------
#include "DxLib.h"
#include "A.h"
void Test_Graph(){
DrawGraph(x座標,y座標, Box1 , TRUE);
}
---------------------
としておき、最後にmain.cに
main.cpp-------------
#include "DxLib.h"
#include "A.h"
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen( DX_SCREEN_BACK );
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
Test_Graph();
};
DxLib_End();
return 0;
}
---------------------
としておくと、「:\documents and settings\kk2\my documents\visual studio 2008\projects\gameprog\player.cpp(11) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
c:\documents and settings\kk2\my documents\visual studio 2008\projects\gameprog\player.cpp(11) : error C2086: 'int Box1' : 再定義されました。
c:\documents and settings\kk2\my documents\visual studio 2008\projects\gameprog\load.h(7) : 'Box1' の宣言を確認してください。」
と表示されます。再定義で調べてみると、二重インクルードのせいというのがよく見つかりましたが、
そう思って紹介されていたA.hに二重インクルード防止の定義を足してもこのようにエラーします。
どこがおかしいのでしょうか?
2.
上の例で、main.cの最初のwhileループを抜けるのに、A.cppにおいた関数の計算結果を使いたいです。
main.cで、
while(~~){
Aにおいてる関数
if( Aにおいてる関数で得た値 > ~~){
break;
}
}
として、whileループを抜けるためにAで計算した結果を判断材料にしたいのですがよく分かりません。
試してみたのは、そのif~を関数にしたんですが、A.cppで「break;」って書いてもエラーするだけでした。
どうしたらよいでしょうか。
分かりにくくてごめんなさい。片方だけでもいいのでお願いします。
分割コンパイルについて
Re: 分割コンパイルについて
1.について
A.h の中に
Box1 = LoadGraph(~~)
とありますが、関数の外で変数に対する代入はできません。
2.について
意味がよくわからないので具体的なコードを書いて下さい。
A.h の中に
Box1 = LoadGraph(~~)
とありますが、関数の外で変数に対する代入はできません。
2.について
意味がよくわからないので具体的なコードを書いて下さい。
Re: 分割コンパイルについて
正確には,かと。きずなん さんが書きました:#include A.hと書けば、A.hの中身を最初に書いたことと同じって説明がありましたよね。
player.cppって何でしょうか。きずなん さんが書きました:としておくと、「:\documents and settings\kk2\my documents\visual studio 2008\projects\gameprog\player.cpp(11) : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
c:\documents and settings\kk2\my documents\visual studio 2008\projects\gameprog\player.cpp(11) : error C2086: 'int Box1' : 再定義されました。
c:\documents and settings\kk2\my documents\visual studio 2008\projects\gameprog\load.h(7) : 'Box1' の宣言を確認してください。」
player.cppの11行目に,Box1の定義がありませんか。きずなん さんが書きました:と表示されます。再定義で調べてみると、二重インクルードのせいというのがよく見つかりましたが、
そう思って紹介されていたA.hに二重インクルード防止の定義を足してもこのようにエラーします。
どこがおかしいのでしょうか?
# A.hのコードを見る限り,関数に属さない式文を書いている気がしますが……。
二重インクルードというのは,というような場合のことです。
で,インクルードガードは,二度目のインクルードをしてもエラーが起きないようにするための物です。
# 上記のコード片は極端ですが,インクルードファイル経由で多重インクルードすることは多々あります。
今回の場合,エラーメッセージを見るとplayer.cppの11行目とload.hの7行目で別々にBox1を定義しているようです。
このため,インクルードガードでは対処することが出来ません。
main.c (main.cpp?) にその関数がある場合に,計算結果はどのように使うか,を考えてみて下さい。きずなん さんが書きました:上の例で、main.cの最初のwhileループを抜けるのに、A.cppにおいた関数の計算結果を使いたいです。
それと同じ方法になります。
なので,基本的には関数の戻り値として計算結果を返すことになるでしょう。
「ループからの脱出」自体を関数に含めることは出来ません。きずなん さんが書きました:として、whileループを抜けるためにAで計算した結果を判断材料にしたいのですがよく分かりません。
試してみたのは、そのif~を関数にしたんですが、A.cppで「break;」って書いてもエラーするだけでした。
どうしたらよいでしょうか。
なので,例えば,のようになると思います。
-
きずなん
Re: 分割コンパイルについて
>関数の外で変数に対する代入はできない
A.cppの上らへんに書けば代入できるんですけど、これって関数の中にある扱いなんですか?
2.
例えばmain.cの本編ループ部分のコードが
として、この最初の開始画面ループからセカンドループに行きたいんですよ。
そしたら~~~~~~~の部分に、break;を入れる必要があるじゃないですか。
この~~~~~~~の部分に、
if( A.cppの関数で計算した値 > ある値){ break; }
を入れたいんです。
例えば歩数の計算をA.cppでして、歩数の合計をSUM(これもA.cppの関数で求める)とすると
if(SUM > 5){ break;} としたいわけです。
でも、SUMはmainじゃなくてA.cppのほうで求めた値だから、エラーが起きるじゃないですか。
このSUM(A.cで求めた値)をmainで使いたいということです。
A.cppの上らへんに書けば代入できるんですけど、これって関数の中にある扱いなんですか?
#include "DxLib.h"
#include "Keyboard.h"
#include "Load.h"
static int x,y,muki,walking_flag,char00;
static int SelectNum;
static int IM_flag;
int f1= 10;
int a = 20;
int Cr = GetColor(255,255,255);
int Box1 = LoadGraph("画像/四角2.png");
//テスト
void Test_Graph(){
DrawFormatString(20,20,GetColor(255,255,255),"%d",f1+a);
}
// 初期化
void Player_Initialize(){
IM_flag = 0;
x = 320;
y = 224;
muki = 2;
walking_flag = 0;
char00 = LoadGraph("画像/キャラクタ10.png");
SelectNum = 0;
}
// 進入判定
void INorOUT(){
if(IM_flag = 1){
int f1 = 2;
}
}
// 動きを計算する
void Player_Calc(){
if(x%32==0 && y%32==0){
walking_flag=1;
if ( Keyboard_Get( KEY_INPUT_UP ) == 1 ){
muki=0;
} else if( Keyboard_Get( KEY_INPUT_LEFT ) == 1 ){
muki=1;
} else if( Keyboard_Get( KEY_INPUT_DOWN ) == 1 ){
muki=2;
} else if( Keyboard_Get( KEY_INPUT_RIGHT ) == 1){
muki=3;
} else {
walking_flag=0;
}
}
if(walking_flag==1){
if (muki==0)
y--;
else if(muki==1)
x--;
else if(muki==2)
y++;
else if(muki==3)
x++;
}
}
// 描画する
void Player_Graph(){
DrawGraph( x, y, char00, TRUE );
}
// 終了処理をする
void Player_Finalize(){
DeleteGraph( char00 );
}
// メニュー表示処理
void I_Menu_Calc(){
if ( Keyboard_Get( KEY_INPUT_DOWN ) == 1 ){
SelectNum = ( SelectNum + 5 )%4;
} else if( Keyboard_Get( KEY_INPUT_UP ) == 1 ){
SelectNum = ( SelectNum + 3 )%4;
}
}
void I_Menu_Graph(){
DrawRotaGraph( 320, 240, 2, 0 , LoadGraph("画像/title01.png") , TRUE );
SetDrawBlendMode( DX_BLENDMODE_ALPHA, 150 );
DrawGraph( M1, M2, LoadGraph("画像/四角2.png"),TRUE);
SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0 );
DrawFormatString(100,100,Cr,"M1の値は%d",M1);
}
2.
例えばmain.cの本編ループ部分のコードが
//本編ループ
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
//開始画面ループ
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
Keyboard_Update();
Keyboard_Update();
I_Menu_Calc(); //メニュー計算
I_Menu_Graph(); //メニュー描画
Test_Graph();
DrawFormatString(200,200,GetColor(255,0,0),"脱出成功。");
~~~~~~~~~~~~
}//開始画面判定終わり
//セカンドループ
while(~~){~~
}//セカンドループ終わり
}//本編ループ終わり
そしたら~~~~~~~の部分に、break;を入れる必要があるじゃないですか。
この~~~~~~~の部分に、
if( A.cppの関数で計算した値 > ある値){ break; }
を入れたいんです。
例えば歩数の計算をA.cppでして、歩数の合計をSUM(これもA.cppの関数で求める)とすると
if(SUM > 5){ break;} としたいわけです。
でも、SUMはmainじゃなくてA.cppのほうで求めた値だから、エラーが起きるじゃないですか。
このSUM(A.cで求めた値)をmainで使いたいということです。
-
きずなん
Re: 分割コンパイルについて
追記ですが、1の方試してみると原因が分かりました。
//A.h--------------
int Box1;
Box1 = LoadGraph("画像/四角2.png");
//------------------
と書いてincludeするとエラーしますが
//A.h--------------
int Box1 = LoadGraph("画像/四角2.png");
//------------------
と書くとエラーしませんでした。
上と下だと、上が「関数の外での定義」で下が「関数の中での定義」になるんでしょうか?
//A.h--------------
int Box1;
Box1 = LoadGraph("画像/四角2.png");
//------------------
と書いてincludeするとエラーしますが
//A.h--------------
int Box1 = LoadGraph("画像/四角2.png");
//------------------
と書くとエラーしませんでした。
上と下だと、上が「関数の外での定義」で下が「関数の中での定義」になるんでしょうか?
Re: 分割コンパイルについて
代入ではなく,初期化をしていますよね。きずなん さんが書きました:>関数の外で変数に対する代入はできない
A.cppの上らへんに書けば代入できるんですけど、これって関数の中にある扱いなんですか?
初期化は可能です。
初期化と代入は異なります。
# 特に,C++の場合。
SUMっていうのは,グローバル変数ですか。きずなん さんが書きました:例えば歩数の計算をA.cppでして、歩数の合計をSUM(これもA.cppの関数で求める)とすると
if(SUM > 5){ break;} としたいわけです。
でも、SUMはmainじゃなくてA.cppのほうで求めた値だから、エラーが起きるじゃないですか。
このSUM(A.cで求めた値)をmainで使いたいということです。
そうであるならば,外部宣言をしてやればmain.cからも使えます。
# まあ,C++とCの違いがあるので,C++側でextern "C"の修飾が必要になりますが。
ただ,そもそも歩数の合計を計算する関数の戻り値じゃないの,という気はしますが。
-
きずなん
Re: 分割コンパイルについて
>Yuoさん
>ただ,そもそも歩数の合計を計算する関数の戻り値じゃないの,という気はしますが。
確かにその通りですね。・・・というか当たり前ですね。
なんかちょっと考えれば当たり前すぎることを質問してました。
疲れてるのか考えが狂ってました。
ご返答ありがとうございました。
>ただ,そもそも歩数の合計を計算する関数の戻り値じゃないの,という気はしますが。
確かにその通りですね。・・・というか当たり前ですね。
なんかちょっと考えれば当たり前すぎることを質問してました。
疲れてるのか考えが狂ってました。
ご返答ありがとうございました。
Re: 分割コンパイルについて
解決しちゃっていますが,気になる点をいくつか.
- ヘッダファイルの中で変数の「定義」をしている.ヘッダではextern宣言すべき.恐らくコンパイル・リンクの流れが分かっていない.
- どうしてCとC++のファイルを混ぜて開発しているのか.
- 本編ループの中に開始画面ループがある.これは書いてはいけない4つの処理に該当する.
- DxLib_Init()を呼び出すまえにLoadGraph()を呼び出している(DxLibに詳しくないため,これが本当にダメなのかは分からない).
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: 分割コンパイルについて
グローバル変数の初期化にDxLIB関係の命令は使ってはいけません。必ず問題を起こします。
ここに書かれていることは守りましょう。特に例あげたものは読んで下さい。
「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」
http://dixq.net/g/
h.11 書いてはいけない4つの処理
d.1 メイン関数の作り方
d.2 複数のファイルにわけてコンパイルする
d.3 ゲームの設計と分割コンパイル(1)
d.4 ゲームの設計と分割コンパイル(2)
d.5 ゲームの設計と分割コンパイル(3)
タイトル画面の作り方とかは私の講座で書いてあるんですが読まれてませんか?
ここに書かれていることは守りましょう。特に例あげたものは読んで下さい。
「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」
http://dixq.net/g/
h.11 書いてはいけない4つの処理
d.1 メイン関数の作り方
d.2 複数のファイルにわけてコンパイルする
d.3 ゲームの設計と分割コンパイル(1)
d.4 ゲームの設計と分割コンパイル(2)
d.5 ゲームの設計と分割コンパイル(3)
タイトル画面の作り方とかは私の講座で書いてあるんですが読まれてませんか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。