ページ 11

classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 09:59
by 史上最悪のデスペナ
VC++&DXライブラリ使用です

以下のようなコードでは変数「count」がちゃんと1ループごとに増えていきます。
(class内の関数であれば値が保持されることを確認するためにDraw関数にもcountの値を表示させています)

コード:


//main.cpp

#include "DxLib.h"
#include "test.h"

C_Test Test;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

	{
		ChangeWindowMode(TRUE);
		if(DxLib_Init() == -1) return -1;
		if(SetDrawScreen(DX_SCREEN_BACK) != 0) return -1;

	}


	//メインループ(ESCで終了)
    while(ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0)
	{

		//画面の初期化
		ClearDrawScreen();

		Test.Count();
		Test.Draw();

		//フリップ
        ScreenFlip();
    }

    DxLib_End();

    return 0;
}

コード:


//test.cpp

#include "test.h"

void C_Test::Count()
{
	count++;
	DrawFormatString(0,0,GetColor(255,0,0),"%d",count);
}

void C_Test::Draw()
{
	DrawFormatString(0,20,GetColor(255,0,0),"%d",count);
}

コード:


//test.h

#include "DxLib.h"

class C_Test
{

	int count;
    int OpacityRate;

public:

	void Count(void);
	void Draw(void);
};
コードが少し長くなるので下に移ります。

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 10:07
by 史上最悪のデスペナ
しかし、自作ゲームにおいて以下のようなプログラムでは変数「OpacityRate」が0.01fづつ増えません
やりたいことは
「DeathFlag」が0なら普通に敵を描画
         1なら敵モデルを徐々に透明に、ラグドール(死体のモデル)を徐々に不透明にする(OpacityRateが1.0になったら敵モデル破棄してDeathFlagを2にする)
         2ならラグドールを徐々に透明にする
OpacityRateを敵モデルの保持する構造体の中に入れてa->OpacityRateで処理すればちゃんと動きます
どこがいけないのでしょうか?

コード:


	switch( a->DeathFlag )
	{
		case 0:

			MV1DrawModel( a->ModelHandle );

			break;
		case 1:

			OpacityRate += 0.01f;
			if(OpacityRate >= 1.0f)
			{
				MV1DeleteModel( a->ModelHandle );
				MV1DeleteModel( a->ColiCheckHandle );
				OpacityRate = 1.0f;
				a->DeathFlag = 2;
			}
			MV1SetOpacityRate( a->ModelHandle, 1 - OpacityRate );
			MV1DrawModel( a->ModelHandle );

			MV1SetOpacityRate( a->DeathHandle, OpacityRate );
			MV1DrawModel( a->DeathHandle );

			break;
		case 2:

			OpacityRate -= 0.01f;
			if(OpacityRate <= 0.0f)
			{
				MV1DeleteModel( a->DeathHandle );
				OpacityRate = 0.0f;
				a->DeathFlag = 0;
			}
			MV1SetOpacityRate( a->DeathHandle, OpacityRate );
			MV1DrawModel( a->DeathHandle );

			break;
	}


Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 10:40
by bitter_fox
史上最悪のデスペナ さんが書きました:しかし、自作ゲームにおいて以下のようなプログラムでは変数「OpacityRate」が0.01fづつ増えません
やりたいことは
「DeathFlag」が0なら普通に敵を描画
         1なら敵モデルを徐々に透明に、ラグドール(死体のモデル)を徐々に不透明にする(OpacityRateが1.0になったら敵モデル破棄してDeathFlagを2にする)
         2ならラグドールを徐々に透明にする
OpacityRateを敵モデルの保持する構造体の中に入れてa->OpacityRateで処理すればちゃんと動きます
どこがいけないのでしょうか?
case 0, 1, 2においてDeathFlagとOpacityRateをプリントデバッグ等で確認するとどのようになりますか?

「OpacityRateを敵モデルの保持する構造体の中に入れてa->OpacityRateで処理すればちゃんと動きます」
とありますが、このシチュエーションにおいてOpacityRateというのはどのような変数なのでしょうか?
関数内変数?クラス内変数?また、それらにおいてどのような修飾がされているのでしょうか?

OpacityRateが関数内変数でもってstatic修飾されていないと二度目以降の呼び出しで値が保持されませんよ。

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 10:45
by softya(ソフト屋)
これだけのコードだと何とも言えませんね。変数の定義、インスタンスの生成、呼び出し部分も見てみないことには。

ちなみに、この方法を使って狙った動作をしているか確認できますよ。お試し下さい。
「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&b=982

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 10:48
by 史上最悪のデスペナ
プリントデバッグなるものが分かりませんがゲーム画面上に値を表示すると
HPが0より大きい時は
OpacityRate = 0.0f
DeathFlag = 0
ですが0以下になると
OpacityRate = 0.01f
DeathFlag = 1

のまま変化しません
bitter_fox さんが書きました:このシチュエーションにおいてOpacityRateというのはどのような変数なのでしょうか?
関数内変数?クラス内変数?また、それらにおいてどのような修飾がされているのでしょうか?
あ、ごめんなさい。ここでの表記忘れです。
正しくは

コード:


//test.h
 
#include "DxLib.h"
 
class C_Test
{
 
    int count;
    int OpacityRate;

public:
 
    void Count(void);
    void Draw(void);
};
です

修飾なるものが分かりません。

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 10:55
by 史上最悪のデスペナ
softya(ソフト屋) さんが書きました:ちなみに、この方法を使って狙った動作をしているか確認できますよ。お試し下さい。
「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
blog.php?u=114&b=982
一応、似たような(?)方法として
ゲーム画面上に自分が今追跡しようとしてる変数を表示したり無理やりキーで値を変更するようにしてifやswitch内を通るかVC++のブレークポイントとかいうのを作成してやっていますがどうでしょう?


softya(ソフト屋) さんが書きました:これだけのコードだと何とも言えませんね。変数の定義、インスタンスの生成、呼び出し部分も見てみないことには。
現在編集中

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 11:02
by softya(ソフト屋)
史上最悪のデスペナ さんが書きました:
softya(ソフト屋) さんが書きました:ちなみに、この方法を使って狙った動作をしているか確認できますよ。お試し下さい。
「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
blog.php?u=114&b=982
一応、似たような(?)方法として
ゲーム画面上に自分が今追跡しようとしてる変数を表示したり無理やりキーで値を変更するようにしてifやswitch内を通るかVC++のブレークポイントとかいうのを作成してやっていますがどうでしょう?
画面表示と違い連続した変化を見れるのでコンソール画面を推奨します。まぁ無理に使わなくて良いんですけどね。
あと、ブレークポイントは流れが止まるので使い方次第です。

とりあえず、OpacityRate の値を変化させている部分全部にprintを埋め込んで調べてみてください。どこの部分か区別が付くように表示の仕方は分けてくださいね。

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 11:04
by bitter_fox
史上最悪のデスペナ さんが書きました:プリントデバッグなるものが分かりませんがゲーム画面上に表示すると
HPが0より大きい時は
OpacityRate = 0.0f
DeathFlag = 0
ですが0以下になると
OpacityRate = 0.01f
DeathFlag = 1

のまま変化しません
デバッグプリントが正しかったですかね。
デバッグプリント・printfデバッグというのは値を画面等に出力してそれが正常な値かどうかを確認してデバッグするという手法のことを言います。

どこか別のところでOpacityRateが常に0になるような操作を行ってるのではないかと思います。
史上最悪のデスペナ さんが書きました: あ、ごめんなさい。ここでの表記忘れです。
正しくは

コード:


//test.h
 
#include "DxLib.h"
 
class C_Test
{
 
    int count;
    int OpacityRate;

public:
 
    void Count(void);
    void Draw(void);
};
です

修飾なるものが分かりません。
なるほど、これだったら常に値は保持されてるはずですね。

修飾というのはprivateやstaticと言った変数等の性質を決定することです。
C++だとprivateとかはアクセス指定とかって言うのかな?

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 11:12
by 史上最悪のデスペナ
bitter_fox さんが書きました:修飾というのはprivateやstaticと言った変数等の性質を決定することです。
C++だとprivateとかはアクセス指定とかって言うのかな?
用語をまともに知らないのです^^;
とりあえずコードを見てまねて無理やりゴリゴリ動かすという手法の独学でしたから・・・・・

OpacityRateの値に関してですが、プロジェクト内の全てのファイルを走査しましたがここに貼り付けたコード以外の部分にはなかったので
多分常に0にするようなとこはないんじゃないかと思います。

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 11:25
by 史上最悪のデスペナ
史上最悪のデスペナ さんが書きました:OpacityRateの値に関してですが、プロジェクト内の全てのファイルを走査しましたがここに貼り付けたコード以外の部分にはなかったので
多分常に0にするようなとこはないんじゃないかと思います。
(switch前 - case 1:内のbreak前 - switch後)という形でOpacityRateの値をコンソール出力したところ
(0.00000 - 0.01000 - 0.01000)の繰り返しになったのでどうやらどこかで常に0にされてるようです。引き続き追跡します

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 11:28
by bitter_fox
史上最悪のデスペナ さんが書きました:
史上最悪のデスペナ さんが書きました:OpacityRateの値に関してですが、プロジェクト内の全てのファイルを走査しましたがここに貼り付けたコード以外の部分にはなかったので
多分常に0にするようなとこはないんじゃないかと思います。
(switch前 - case 1:内のbreak前 - switch後)という形でOpacityRateの値をコンソール出力したところ
(0.00000 - 0.01000 - 0.01000)の繰り返しになったのでどうやらどこかで常に0にされてるようです。引き続き追跡します
とするとC_Testのインスタンスが毎回作成されているという可能性はありませんか?
C_Testのコンストラクタでデバッグプリントをしてみてください。

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 11:38
by 史上最悪のデスペナ
bitter_fox さんが書きました:C_Testのインスタンスが毎回作成されているという可能性はありませんか?
C_Testのコンストラクタでデバッグプリントをしてみてください。
count++;はちゃんと一個ずつ足されていくのでインスタンス毎回作成はないと思ったのですが・・・・・・
ちなみに、クラス内の関数全てにprintfして追跡しても見つかりませんでした・・・・・・


コンストラクタでデバッグプリントを考え中

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 11:40
by beatle
僕はデスペナさんが示されたC_Testクラスの中のOpacityRateがint型なのが非常に気になるのですが。
int型変数に0.01fを加算しても意味ありませんよ。

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 11:42
by softya(ソフト屋)
あとインスタンスのコピーとか、常に同じインスタンスなのかも心配。

コード:

printf( "this=%p\n", this );
これも加えてみてください。

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 11:49
by 史上最悪のデスペナ
beatle さんが書きました:int型変数に0.01fを加算しても意味ありませんよ。
ごめんなさい。これも間違いです^^;

コード:

float OpacityRate;
です。

ちなみに、実はC_Testと例のswitch文とは何の関係もないのです^^;勘違いさせるような書き方して申し訳ありません。直すのも面倒なのでC_Test内に(これ上で)書きこんでるのでミスがあることも・・・・・

実際には例のswitch文はclassの一つであるC_MOB内の関数の一部で、float OpacityRate;もC_MOBに宣言されてます。

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 11:51
by beatle
全体のソースをお示しになられると混乱もなくなり、みなさんハッピーかと思います。
長いならspoilタグで囲むか、zipして添付ですかね。

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 11:59
by 史上最悪のデスペナ
beatle さんが書きました:全体のソースをお示しになられると混乱もなくなり、みなさんハッピーかと思います。
長いならspoilタグで囲むか、zipして添付ですかね。
それはzip添付は考えたのですが3DRPGを作ろうとしてるのでコードが(自分にとって)かなり多いうえ、コメントとかほとんど書き込んでませんし、
特に、softya(ソフト屋)さんにこちらのトピックNo5で
ご指摘いただいたのがまだ全部直せてないので申し訳ないというのもありますので・・・・・・

thisの値ですが全て009469C8という値でしたので同じインスタンスという解釈でいいですよね?

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 12:37
by softya(ソフト屋)
史上最悪のデスペナ さんが書きました: thisの値ですが全て009469C8という値でしたので同じインスタンスという解釈でいいですよね?
たぶん大丈夫です。
コンパクトな再現コードは作れませんか?
本物として分離して実験したほうがよさそうです。

Re: classにおけるprivate変数に関して

Posted: 2011年11月28日(月) 12:41
by 史上最悪のデスペナ
とりあえずzipを添付しようとしたらなぜか出来ないようです・・・・・・・

コンパクトな再現コードは多分可能だと思いますので明日こちらに投稿させていただきます。

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 08:37
by 史上最悪のデスペナ
おはようございます
やはりzip添付が出来ません
spoilだとバイナリデータを表すのは無理ですし・・・・・
どうしましょう?

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 08:42
by softya(ソフト屋)
ファイル添付できますよ。
試しにやってみました。

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 08:48
by 史上最悪のデスペナ
あれ~?なんででしょう?普通にファイル添付タブをクリックしてファイル選択してファイル追加するだけですよね?
ファイル追加するとChromeでは下のほうに何%済みみたいなのが出るのですが
それが100%になったとたん画面が更新されて
本文に打ち込んだのが全部消えた上、何処探しても正常にアップロードされました、とか添付ファイル名が現れたりとか
アップロードされたことが分かるような状況がないのですが・・・・・・

追記
2時間ほどインできませんのでまた後ほどよろしくお願いします

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 08:53
by softya(ソフト屋)
とりあえず私はfirefoxです。

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 09:08
by 史上最悪のデスペナ
なんででしょう?
古いPC(XPでWiMAX使用&Chrome)でも、新しいPC(7でstarcat&Chrome)でも、学校のPC(Vistaで回線不明&IE)でも出来ないのですが・・・・・
前は出来たのに。前の分を削除すればいいのですかね・・・・・?

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 09:17
by softya(ソフト屋)
ファイル名が禁止キーワードに引っかかってないですか?
英字にしてみる&名前を変えてみる
を試してみてください。

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 09:22
by bitter_fox
史上最悪のデスペナ さんが書きました:なんででしょう?
古いPC(XPでWiMAX使用&Chrome)でも、新しいPC(7でstarcat&Chrome)でも、学校のPC(Vistaで回線不明&IE)でも出来ないのですが・・・・・
前は出来たのに。前の分を削除すればいいのですかね・・・・・?
外部のアップローダ等を使用するのも一つの手ですね。

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 11:07
by beatle
僕は普段firestorageってところを使っています。参考にどうぞ。

追記:ファイル名の1文字目が全角文字だとダメかもしれません。http://support.hiikun.net/bbs/topic-559.html

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 11:25
by 史上最悪のデスペナ
VerEditing.zipに名前を変更してもダメでした・・・・・・orz

外部アップローダを使用します
こちらからよろしくお願いします。

ちなみにVerFullも一応Upしておきます→こちら

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 11:28
by beatle
50MB超えてますね。大きすぎるのが失敗要因じゃないでしょうか。

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 11:34
by 史上最悪のデスペナ
なるほど。確かに前は47Mでしたし・・・・・・・

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 11:36
by softya(ソフト屋)
VC++のプロジェクトは公開するには余分なものを含んでいるのでzipから削除して下さいね。
xxx.ncbとかxxxx.ipchとかxxxx.sdfとかです。消しても自動的に復元されます。

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 11:40
by 史上最悪のデスペナ
softya(ソフト屋) さんが書きました:VC++のプロジェクトは公開するには余分なものを含んでいるのでzipから削除して下さいね。
xxx.ncbとかxxxx.ipchとかxxxx.sdfとかです。消しても自動的に復元されます。
なるほど。知らなかったです。以後気をつけます

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 11:56
by softya(ソフト屋)
これ、どんな操作をすると再現するんでしょうか?

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 11:59
by 史上最悪のデスペナ
あ、そうでした。ファイル添付に失敗した時に書いたのでそれが消えちゃったんでした。すみません^^;

「W」をしばらく押すとDeathFlagが1になるようにしました。
コンソールは
インスタンスの識別コードみたいなやつ--switch前のOpacityRateの値--cae 1:のbreak前の(ry--関数終了前の(ry
という風に表示しています

Full.verでは左クリックで袈裟切りモーションが発動します。剣と敵に当たり判定を行い、当たっていれば徐々にHPが減っていくはずです。
また、Full.verではOpacityRateを構造体内に入れているので、起こしたい現象がちゃんと起きています

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 12:15
by softya(ソフト屋)
メモリ破壊の様です。
次のようにしてデバッグしてみてください。

1.C_MOBのコンストラクタにブレークポイントを貼る。
2.デバッグ開始
3.OpacityRateを選択した上で、デバック→ブレークポイントの作成→新しいデータブレークポイント
4.アドレス&OpacityRate バイト数4としてOK。こうすると変数が書き変えられるとブレークします。
5. F5で再開。wを押す。一度ブレークするが更にF5。予想外の関数でブレークします。

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 12:22
by 史上最悪のデスペナ
何故メモリ破壊が起きたのでしょう・・・・・・
今日はもうインできませんが、教えていただいた方法でデバッグしてみます。

申し訳ありませんが、また明日もお付き合いください。

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 12:26
by softya(ソフト屋)
史上最悪のデスペナ さんが書きました:何故メモリ破壊が起きたのでしょう・・・・・・
今日はもうインできませんが、教えていただいた方法でデバッグしてみます。

申し訳ありませんが、また明日もお付き合いください。
ヒント:メモリ破壊の原因は配列の添字かポインタの操作ミスです。

Re: classにおけるprivate変数に関して

Posted: 2011年11月29日(火) 22:18
by ふりかけ
OpacityRate が float型なのは理由があるのですか?
誤差がでたりするので、物理演算ならともかく ゲーム的な処理では int型でできるだけ済ませるのが好きです。

Re: classにおけるprivate変数に関して

Posted: 2011年11月30日(水) 08:24
by 史上最悪のデスペナ
ふりかけ さんが書きました:OpacityRate が float型なのは理由があるのですか?
ただ単にDXLibの仕様が
int MV1SetOpacityRate( int MHandle, float Rate ) ;
のようにfloat(0.0f~1.0f)だからです。
softya(ソフト屋) さんが書きました:ヒント:メモリ破壊の原因は配列の添字かポインタの操作ミスです。
当たり判定での配列の添字が1つ足りなかったからでした。
OpacityRateを使ってるところだけを見てても分からないはずです^^;


お騒がせしました。皆さん、ありがとうございました

Re: classにおけるprivate変数に関して

Posted: 2011年11月30日(水) 08:47
by softya(ソフト屋)
史上最悪のデスペナ さんが書きました:当たり判定での配列の添字が1つ足りなかったからでした。
OpacityRateを使ってるところだけを見てても分からないはずです^^;
プロでもその手のバグが一番多いのです。
配列を使う時は出来るだけenumなど自動的に最大値を定義できるものはしたほうが良いです。
今回の場合
enum {Ground, Build, enemy};
があるので
enum {Ground, Build, enemy, MAP_HIT_MAX};
としておいて
MV1_COLL_RESULT_POLY MapHit[MAP_HIT_MAX]; //Map当たり判定
とすれば防げたでしょう。

あとミスをすること想定して
assert(Flag<MAP_HIT_MAX);
assert(Flag>=0);
も書いておくと完璧です。

解決マークをお願いしますね。

Re: classにおけるprivate変数に関して

Posted: 2011年11月30日(水) 09:02
by 史上最悪のデスペナ
softya(ソフト屋) さんが書きました:プロでもその手のバグが一番多いのです。
そうなんですか。
softya(ソフト屋) さんが書きました:enum {Ground, Build, enemy};
があるので
enum {Ground, Build, enemy, MAP_HIT_MAX};
としておいて
MV1_COLL_RESULT_POLY MapHit[MAP_HIT_MAX]; //Map当たり判定
とすれば防げたでしょう。
そういうテクニックって独学だと思いつきませんよね。なかなか。頭のいい人は思いつくんだろうけど・・・・
softya(ソフト屋) さんが書きました:あとミスをすること想定して
assert(Flag<MAP_HIT_MAX);
assert(Flag>=0);
も書いておくと完璧です。
これが何か分からないのでちょっと調べてみます
softya(ソフト屋) さんが書きました:解決マークをお願いしますね。
忘れてました^^;

Re: classにおけるprivate変数に関して

Posted: 2011年11月30日(水) 09:09
by softya(ソフト屋)
史上最悪のデスペナ さんが書きました: そういうテクニックって独学だと思いつきませんよね。なかなか。頭のいい人は思いつくんだろうけど・・・・
私も誰かの受け売りです。
そういうのを勉強するのはコードリーディングですね。つまり、人のプログラムを読むんです。
私のRPG講座のソースコード最終版とかも参考になるかも知れません。