一つの関数から複数のオブジェクトへのアクセス

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
華風えくれあ
記事: 25
登録日時: 13年前
住所: 岐阜県大垣市
連絡を取る:

一つの関数から複数のオブジェクトへのアクセス

#1

投稿記事 by 華風えくれあ » 13年前

現在、ローグライク型のゲームを作成しております。
そこで、ある問題にぶつかりました。

あるオブジェクトをsoftyaさんのRPG作成講座を参考にしながら制作しました。

コード:

// アクターのパラメータ一式
struct tag_ActorParamObject
{
	int hp,hp_max;			// 体力
	int mp,mp_max;			// 魔力
	int pow,def,mag,sec;	// 攻撃力,防御力,魔法攻撃力,魔法防御力
	int State;				// 状態異常
	int ItemStack;			// アイテムスタック+1

	int ActPos_x,ActPos_y;	// アクターマップ座標
	int GHandle;			// グラフィックハンドル

};
このオブジェクトを敵も使うためmalloc関数を使い複数作成できるようにして、
HPが0などのフラグがたったらfreeで消滅させるプログラムを書いています。

そしてこれらのオブジェクトを表示させようとします。
ですが、このオブジェクトはグローバルでもないですし、
引数に全部書く・・・というのもオブジェクトの数は一定ではないので良いとも思えません。

この場合、どのようにすべてのオブジェクトのメンバActPosにアクセスできるようにすればよいのでしょうか。
ご教授をよろしくお願いします。

マップ描画にはこちらで作ったクラスClassDungeon::DrawMapにて
マップのメタ情報の入っている2次元配列をfor分で読みだす構造にしてます。

コード:

int ClassDungeon::map_data[10][10]	=  {{0,0,0,0,0,0,0,0,0,0},
										{0,0,0,1,1,1,0,0,0,0},
										{0,0,0,1,3,1,0,0,0,0},
										{0,0,0,1,1,1,0,0,0,0},
										{0,0,0,0,2,0,0,0,0,0},
										{0,0,0,0,2,0,0,0,0,0},
										{0,0,0,0,2,0,0,0,0,0},
										{0,0,0,0,2,0,0,0,0,0},
										{0,0,0,0,2,0,0,0,0,0},
										{0,0,0,0,0,0,0,0,0,0}};				// テスト用マップデータ

/* 画像読み込み他無関係関数省略 */

int ClassDungeon::DrawMap( void )
{
	int i,j;
	for(j=0;j<10;j++)
	{
		for(i=0;i<10;i++)
		{
			DrawGraph(i*64,j*64,MapGraph[ map_data[j][i] ],TRUE);

		}
	}

	return 0;
}
i,jはマップデータを本格的に作るとき、その場その場で可変するように作ろうと考えています。

使用環境は、Win7 64bit ・ VS2010Express です。

追記:
書き忘れました、DXライブラリを使用しています。

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

Re: 一つの関数から複数のオブジェクトへのアクセス

#2

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

C++でやるならActorクラスのインスタンスとして生成してSTLのvectorで管理すれば良いのでは無いでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

華風えくれあ
記事: 25
登録日時: 13年前
住所: 岐阜県大垣市
連絡を取る:

Re: 一つの関数から複数のオブジェクトへのアクセス

#3

投稿記事 by 華風えくれあ » 13年前

softya(ソフト屋) さんが書きました:C++でやるならActorクラスのインスタンスとして生成してSTLのvectorで管理すれば良いのでは無いでしょうか?
と言いますと・・・、
構造体ActorParamObject(以下、APOと呼びます)を改めてクラスとして宣言し、
Vectorで可変できるクラスAPO配列を生成する。

という解釈で宜しいのでしょうか。
そのクラス配列ごとMapDrawに引数として渡し配列0からActorPosにアクセス…のような形になるわけですね。

コードの書き換え部分が多そうなので返信は昼ごろになると思います。
その時もよろしくお願いします。

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

Re: 一つの関数から複数のオブジェクトへのアクセス

#4

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

EkLear さんが書きました:
softya(ソフト屋) さんが書きました:C++でやるならActorクラスのインスタンスとして生成してSTLのvectorで管理すれば良いのでは無いでしょうか?
と言いますと・・・、
構造体ActorParamObject(以下、APOと呼びます)を改めてクラスとして宣言し、
Vectorで可変できるクラスAPO配列を生成する。

という解釈で宜しいのでしょうか。
そのクラス配列ごとMapDrawに引数として渡し配列0からActorPosにアクセス…のような形になるわけですね。

コードの書き換え部分が多そうなので返信は昼ごろになると思います。
その時もよろしくお願いします。
大体そのような感じになります。
手抜きとしては、そのまま構造体ActorParamObjectのポインタをvector配列にするだけでも良いと思いますが。
それでも不特定多数の処理は1つのvetor配列で可能になると思います。
ちなみにmallocよりもnewを使うこととスマートポインタの使用をおすすめします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

華風えくれあ
記事: 25
登録日時: 13年前
住所: 岐阜県大垣市
連絡を取る:

Re: 一つの関数から複数のオブジェクトへのアクセス

#5

投稿記事 by 華風えくれあ » 13年前

なるほど、ありがとうございます。
スマートポインタですか・・・、確かExpressでは類似している機能があったと聞いたような気がします。
ですが、まだ初心者を脱していないものでして・・・。

Professional版を買えたらすぐにもそちらへ書き換えたいんですけどね・・・、
参考までに、肝に銘じておきます。

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

Re: 一つの関数から複数のオブジェクトへのアクセス

#6

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

VC++のproを買わなくてもboost(オープンソース)を導入するとか色々手はあります。

たかぎさんのサイトから。
「3. スマートポインタ | 株式会社きじねこ」
http://www.kijineko.co.jp/tech/tr1/smart_pointers

std::tr1::shared_ptrはVC++2010Expressから利用できるはずです。

[補足]
proが欲しくなるのは、MFCを使う時ぐらいでしょうか。
でも、Windows8のMETOR UIではMFCは見捨てられるので、それこそ意味が無いかもしれません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: 一つの関数から複数のオブジェクトへのアクセス

#7

投稿記事 by beatle » 13年前

VC++2010 Expressでもstd::shared_ptrは使えます。

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: 一つの関数から複数のオブジェクトへのアクセス

#8

投稿記事 by beatle » 13年前

大体こんな感じになるでしょうか

コード:

#include <memory>
#include <vector>

// アクターのパラメータ一式
struct ActorParamObject // tag_を削除
{
    int hp,hp_max;          // 体力
    int mp,mp_max;          // 魔力
    int pow,def,mag,sec;    // 攻撃力,防御力,魔法攻撃力,魔法防御力
    int State;              // 状態異常
    int ItemStack;          // アイテムスタック+1

    int ActPos_x,ActPos_y;  // アクターマップ座標
    int GHandle;            // グラフィックハンドル
};

void bar(std::vector<std::shared_ptr<ActorParamObject>>& apobjects)
{
    // erase all objects with hp == 0
	for (auto it = apobjects.begin(); it != apobjects.end();)
    {
        if ((*it)->hp == 0)
        {
			it = apobjects.erase(it);
		}
		else
		{
			++it;
		}
    }
}

void foo()
{
    std::vector<std::shared_ptr<ActorParamObject>> apobjects;
    apobjects.reserve(100);
    for (size_t i = 0; i < 100; ++i)
    {
        auto apo = std::make_shared<ActorParamObject>();
        apobjects.push_back(apo);
    }
	bar(apobjects);
}

華風えくれあ
記事: 25
登録日時: 13年前
住所: 岐阜県大垣市
連絡を取る:

Re: 一つの関数から複数のオブジェクトへのアクセス

#9

投稿記事 by 華風えくれあ » 13年前

beatle さんが書きました:大体こんな感じになるでしょうか
すいません、昨日操作を誤ってコード全部灰と化しました…ので絶賛書き直し中で遅れました。

なにやら初めて見る関数やらが・・・、
理解できた点を挙げると
  • 関数barでvectorで作ったapobject(以下オブジェクトテーブル)を受け取って、
    whileループ毎にHP0判定で消す作業を行う。
  • 関数FooでActorParamObjectのスマートポインタでオブジェクトテーブルの作成。
    その後テーブルを100まで伸ばす。
    forでi<要素数まで変数apoにActorParamObject分のメモリ確保、及び
    オブジェクトテーブルにプッシュバック。
ここからできることは、reserveに渡す数を変数で管理し、増減を行えること(減は無いか)。
apobjectごと渡すことでまとめて持っていくことができる。

疑問に思ったことは、erase処理をしたとき例えば49を破棄したとき、
50以降の配列は自動的に通し番号-1のような状態になるのでしょうか?

もう一つはオブジェクトにアクセスするときはapobject[N].setParam();のように
書けばよろしいのでしょうか?

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

Re: 一つの関数から複数のオブジェクトへのアクセス

#10

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

(1)vectorはeraseすれば要素数が-1されます。通し番号も同様です。iteratorはちょっと特殊ですけどね。

(2)iteratorを使わないのであれば、apobjects[]はポインタですので
struct ActorParamObjectにsetParam();メンバを追加したとして
apobjects[N]->setParam();でアクセス出来ます。

ソースコードはTortoiseSVNなどで世代管理することをおすすめします。
管理用のレポジトリはローカルレポジトリで十分です。
「TortoiseSVNの使い方」
http://www.gside.org/Gentoo/subversion/ ... ient2.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

華風えくれあ
記事: 25
登録日時: 13年前
住所: 岐阜県大垣市
連絡を取る:

Re: 一つの関数から複数のオブジェクトへのアクセス

#11

投稿記事 by 華風えくれあ » 13年前

また初歩的な部分で引っかかってしまったので質問します><

クラスClassDungeonのメンバ変数として
std::vector<std::shared_ptr<ActorParamObject>> ActObjを宣言し、

このオブジェクトテーブルにプッシュバックする時、例として関数ActorObjectAdd使うとします。

この場合、ActObjの宣言場所としては正しいのでしょうか?
また、味方用にオブジェクトテーブル0~10を確保したいのですがこの場合の管理方法としてはどうすれば適切なのでしょうか?

beatleさんが挙げてくれたコードでは

コード:

/* ActObj = apobject に置き換えるとする */
for (auto it = ActObj.begin(); it != ActObj.end();)
    {
        if ((*it)->hp == 0)
        {
            it = ActObj.erase(it);
        }
        else
        {
            ++it;
        }
}
とありますが、itに先頭アドレスを返してインクリメント後に、
空のオブジェクトにぶつかった場合11に飛べるのでしょうか?

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

Re: 一つの関数から複数のオブジェクトへのアクセス

#12

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

色々ややこしいので明日回答します。
vectorを予約するというのは主旨には反している気がするのでした。と言うかスマートポインタで空オブジェクトを管理させるんですか?
[訂正]スマートポインタの意味が無いような・・・。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: 一つの関数から複数のオブジェクトへのアクセス

#13

投稿記事 by beatle » 13年前

EkLear さんが書きました:また初歩的な部分で引っかかってしまったので質問します><

クラスClassDungeonのメンバ変数として
std::vector<std::shared_ptr<ActorParamObject>> ActObjを宣言し、

このオブジェクトテーブルにプッシュバックする時、例として関数ActorObjectAdd使うとします。

この場合、ActObjの宣言場所としては正しいのでしょうか?
また、味方用にオブジェクトテーブル0~10を確保したいのですがこの場合の管理方法としてはどうすれば適切なのでしょうか?
命名規則は僕の趣味ではないですが、宣言場所としてはよくある場所ですね。
vectorは可変長配列であることが特徴ですので、事前に決まった大きさに固定するという使い方はあまりしない気がします。

もしかしたら僕がvector::reserve関数を使ったのが混乱を招いているかもしれないのですが、vector::reserve関数は要素数を調整する関数ではありません。
vector::reserve関数を使ってもvector::size関数の戻り値は変化しません。
vector::reserve関数を呼び出す1行をなくしてもちゃんと動きます。
vector::push_backを大量に呼び出したりする場合、事前にvector::reserveで大体のサイズを指定しておくと速くなる、というだけです。
EkLear さんが書きました:とありますが、itに先頭アドレスを返してインクリメント後に、
空のオブジェクトにぶつかった場合11に飛べるのでしょうか?
この文の意味が良くわかりません。先頭アドレスを返す?11に飛ぶ?

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

Re: 一つの関数から複数のオブジェクトへのアクセス

#14

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

>この場合、ActObjの宣言場所としては正しいのでしょうか?

正しいとは思いますが、カプセル化がどの様に行われているかは気になります。

>また、味方用にオブジェクトテーブル0~10を確保したいのですがこの場合の管理方法としてはどうすれば適切なのでしょうか?

予約は不要でしょう。味方・敵はフラグで区別すれば良いのでは?

>とありますが、itに先頭アドレスを返してインクリメント後に、
>空のオブジェクトにぶつかった場合11に飛べるのでしょうか?

空のオブジェクトの定義が分かりません。
どういう状態のものを空のオブジェクトと呼ぶのですか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

華風えくれあ
記事: 25
登録日時: 13年前
住所: 岐阜県大垣市
連絡を取る:

Re: 一つの関数から複数のオブジェクトへのアクセス

#15

投稿記事 by 華風えくれあ » 13年前

不適切な発言、申し訳ありません。

いろいろとこちらの解釈で書いてしまいましたので説明足らずの部分もあったかと思います。
softya(ソフト屋) さんが書きました: >とありますが、itに先頭アドレスを返してインクリメント後に、
>空のオブジェクトにぶつかった場合11に飛べるのでしょうか?

空のオブジェクトの定義が分かりません。
どういう状態のものを空のオブジェクトと呼ぶのですか?
おそらく、push_backで要素を入れてないのを空、としていたと思います。
beatle さんが書きました: この文の意味が良くわかりません。先頭アドレスを返す?11に飛ぶ?
for文の変数指定部分で 「it = apobject.begin()」をapobjectの先頭のイテレーターを取得?
しているのと、else文に++itとしているので、真なら削除、偽ならインクリメントで次の要素へ、
という解釈をしていました。

ので、先ほどの空の意味で要素内に何も指定していない、という要素を見たときに、
飛ばしてit = 11とできますか、と聞いていたのだと思います。

今考えてみるとわけのわからない質問してましたね、申し訳ないです。
今持ってる書籍を見直したらvectorやiteratorについて乗っていたので勉強しなおしてみようかなと思います。

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

Re: 一つの関数から複数のオブジェクトへのアクセス

#16

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

とりあえずeraseすると削除した次の要素のイテレータが戻り値として返ると言うことを理解すれば分かるんじゃないでしょうか?
削除したイテレータは++itできませんからね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

華風えくれあ
記事: 25
登録日時: 13年前
住所: 岐阜県大垣市
連絡を取る:

Re: 一つの関数から複数のオブジェクトへのアクセス

#17

投稿記事 by 華風えくれあ » 13年前

教えていただいたことについて、ある程度理解はできました。

vector配列を(もしくはポインタ?)を渡してfor文で連続させることで表示できるということがわかりました。
ですが、肝心のオブジェクトテーブルの宣言・実体化場所に戸惑い続けてしまったので、
STL関連の書籍で勉強しなおそうと思います。

回答してくださりありがとうございます。
解決時にソースコードの提示が必要?とのことですが、現在手一杯でございまして、
後日公開したいと思います。

それでは、失礼しました。

閉鎖

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