DXライブラリでゲームを制作中で、Enemyクラスの”敵”を量産しようとしたときに、敵のパラメータがすべて同じで、どうやったら楽に変えれるのだろうと思い質問させていただきました。
コンストラクターに引数を持たせて外で定義してあげたらいいし、さらにはshared_ptr<>を使えばわかりやすくなるくらいの知識はあります。ですが、コンストラクターに引数を持たせずにしばらくやってきたし、とても分かりやすいと感じてます。なのでこの方法で敵のパラメータを変える方法があるのならぜひ知りたいです。
また、そのような方法があったとした場合に、それを使うメリットとデメリットも教えていただけたら幸いです。
C++ パラメータの異なった敵の複製
- Dixq (管理人)
- 管理人
- 記事: 1662
- 登録日時: 14年前
- 住所: 北海道札幌市
- 連絡を取る:
Re: C++ パラメータの異なった敵の複製
質問の内容が読んでてよく理解できないです。
読み直してから投稿されましたか?
> Enemyクラスの”敵”を量産しようとしたときに、敵のパラメータがすべて同じで、どうやったら楽に変えれるのだろうと思い
「どうやったら全て同じに出来るのだろう」ではなく「どうやったら楽に変えられるのだろう」という疑問なのですか?
それとも共通のパラメータを設定するようになっていて、一か所を変更したらその内容がすべてに適用されるようにしたいのでしょうか。
> コンストラクターに引数を持たせて外で定義してあげたらいいし、さらにはshared_ptr<>を使えばわかりやすくなるくらいの知識はあります
敵のパラメータとshared_ptrってどう関係あるのでしょうか?
> ですが、コンストラクターに引数を持たせずにしばらくやってきたし、とても分かりやすいと感じてます。なのでこの方法で敵のパラメータを変える方法があるのならぜひ知りたいです。
とても分かりやすいのは何がですか?要するにコンストラクタに引数を持たせないやり方を知りたいのでしょうか?
とりあえず私なりに解釈したのが
・敵のパラメータを同一にしたい
・簡単な変更で敵のパラメータを一括で変更したい
・コンストラクタの引数は利用したくない
・コンストラクタの引数で指定する場合とそうでない場合のメリットデメリットを知りたい
解決策の一つとして、まず敵クラスのオブジェクトが持つメンバ変数を全部同じにしたいのなら、コピーコンストラクタを定義して、オブジェクトをコピー可能にします。
https://goo.gl/RNsZEA
もし特定のパラメータだけ同じ物を指定したいのであればEnemyParamとでも名前を付けたパラメータクラスを定義し、それをセットすればよいでしょう。
イメージ的にはこんな感じです
この時、prmの値を変えてあげればセットするパラメータは全部変わります。
コンストラクタの引数を使うメリットデメリットを聞く前に、まず何故コンストラクタに引数を与えてはいけないのですか?
読み直してから投稿されましたか?
> Enemyクラスの”敵”を量産しようとしたときに、敵のパラメータがすべて同じで、どうやったら楽に変えれるのだろうと思い
「どうやったら全て同じに出来るのだろう」ではなく「どうやったら楽に変えられるのだろう」という疑問なのですか?
それとも共通のパラメータを設定するようになっていて、一か所を変更したらその内容がすべてに適用されるようにしたいのでしょうか。
> コンストラクターに引数を持たせて外で定義してあげたらいいし、さらにはshared_ptr<>を使えばわかりやすくなるくらいの知識はあります
敵のパラメータとshared_ptrってどう関係あるのでしょうか?
> ですが、コンストラクターに引数を持たせずにしばらくやってきたし、とても分かりやすいと感じてます。なのでこの方法で敵のパラメータを変える方法があるのならぜひ知りたいです。
とても分かりやすいのは何がですか?要するにコンストラクタに引数を持たせないやり方を知りたいのでしょうか?
とりあえず私なりに解釈したのが
・敵のパラメータを同一にしたい
・簡単な変更で敵のパラメータを一括で変更したい
・コンストラクタの引数は利用したくない
・コンストラクタの引数で指定する場合とそうでない場合のメリットデメリットを知りたい
解決策の一つとして、まず敵クラスのオブジェクトが持つメンバ変数を全部同じにしたいのなら、コピーコンストラクタを定義して、オブジェクトをコピー可能にします。
https://goo.gl/RNsZEA
もし特定のパラメータだけ同じ物を指定したいのであればEnemyParamとでも名前を付けたパラメータクラスを定義し、それをセットすればよいでしょう。
イメージ的にはこんな感じです
class EnemyParam {
public:
int a;
int b;
int c;
};
class Enemy {
private:
int a;
int b;
int c;
public:
void setParam(const EnemyParam& prm){
a = prm.a;
b = prm.b;
c = prm.c;
}
};
int main(){
Enemy enemy[100];
EnemyParam prm;
prm.a = 1;
prm.b = 2;
prm.c = 3;
for(int i=0; i<100; i++){
enemy[i].setParam(prm);
}
}
コンストラクタの引数を使うメリットデメリットを聞く前に、まず何故コンストラクタに引数を与えてはいけないのですか?
- Dixq (管理人)
- 管理人
- 記事: 1662
- 登録日時: 14年前
- 住所: 北海道札幌市
- 連絡を取る:
Re: C++ パラメータの異なった敵の複製
もしもっと賢くセットしたいなら、パラメータのセットにはデザインパターンBuilderパターンを利用したりメソッドチェーンを実装して設定する方法もあります。
メソッドチェーンはC#でよく使われる流行の方法で、C++でも似たような実装は可能です。
https://goo.gl/gPa83W
Builderパターンをメソッドチェーンで実装する方法はEffectiveJAVAに乗っていて、それをC++で実装する方法もあります。
https://goo.gl/tGaWjR
メソッドチェーンはC#でよく使われる流行の方法で、C++でも似たような実装は可能です。
https://goo.gl/gPa83W
Builderパターンをメソッドチェーンで実装する方法はEffectiveJAVAに乗っていて、それをC++で実装する方法もあります。
https://goo.gl/tGaWjR
Re: C++ パラメータの異なった敵の複製
「異なった」パラメータを持つ敵の複製です。
慣れている方にはもうわからないのかもしれないし、私だけなのかもしれませんが、コンストラクタに引数を持たせるこのような書き方だと、ここだけで完結(ほかで定義しない)ので非常にわかりや憂く感じます。
[code=Cpp]
#pragma once
class Enemy {
public:
std::string Name;
int Hp;
int Atk;
Enemy(std::string setname, int sethp, int setatk) {
Name = setname;
Hp = sethp;
Atk = setatk;
}
//↓Enemyクラスのcpp
#include"Enemy.h"
#include<iostream>
void Battle::EnemyStatus() {
std::shared_ptr<Enemy> Slime(new Enemy("スライム", 50, 10));
std::cout << slime->name << "が現れた" << std::endl;
[/code]
と書いてもわかりやすいと言えばわかりやすいのですが、現状では前者の書き方の方が慣れているので、その書き方をしてもエネミー1体ずつ別のステータスを設定することは可能なのかなと思いました。
ステータスの設定にshared_ptrというワードについてあまりピンと来ていないようですが、もしかしてあまり乱用しないほうが良かったりなどありますか?
便利だと思って使うことがしばしばあります。
慣れている方にはもうわからないのかもしれないし、私だけなのかもしれませんが、コンストラクタに引数を持たせるこのような書き方だと、ここだけで完結(ほかで定義しない)ので非常にわかりや憂く感じます。
#pragma once
#include<string>
class Enemy {
public:
std::string name;
int hp;
int atk;
Enemy() {
name = "案山子";
hp = 20;
atk = 10;
}
};
#pragma once
class Enemy {
public:
std::string Name;
int Hp;
int Atk;
Enemy(std::string setname, int sethp, int setatk) {
Name = setname;
Hp = sethp;
Atk = setatk;
}
//↓Enemyクラスのcpp
#include"Enemy.h"
#include<iostream>
void Battle::EnemyStatus() {
std::shared_ptr<Enemy> Slime(new Enemy("スライム", 50, 10));
std::cout << slime->name << "が現れた" << std::endl;
[/code]
と書いてもわかりやすいと言えばわかりやすいのですが、現状では前者の書き方の方が慣れているので、その書き方をしてもエネミー1体ずつ別のステータスを設定することは可能なのかなと思いました。
ステータスの設定にshared_ptrというワードについてあまりピンと来ていないようですが、もしかしてあまり乱用しないほうが良かったりなどありますか?
便利だと思って使うことがしばしばあります。
Re: C++ パラメータの異なった敵の複製
「異なった」パラメータを持つ敵の複製です。
慣れている方にはもうわからないのかもしれないし、私だけなのかもしれませんが、コンストラクタに引数を持たせない書き方だと、ここだけで完結する(ほかで定義しない)ので非常にわかりやすく感じます。
と書いてもわかりやすいと言えばわかりやすいのですが、現状では前者の書き方の方が慣れているので、その書き方をしてもエネミー1体ずつ別のステータスを設定することは可能なのかなと思いました。
ステータスの設定にshared_ptrというワードについてあまりピンと来ていないようですが、もしかしてあまり乱用しないほうが良かったりなどありますか?
便利だと思って使うことがしばしばあります。
プレビューする前に急いで送ってしまっていろいろと間違えて送ってしまったので再掲します。><
慣れている方にはもうわからないのかもしれないし、私だけなのかもしれませんが、コンストラクタに引数を持たせない書き方だと、ここだけで完結する(ほかで定義しない)ので非常にわかりやすく感じます。
#pragma once
#include<string>
class Enemy {
public:
std::string name;
int hp;
int atk;
Enemy() {
name = "案山子";
hp = 20;
atk = 10;
}
};
#pragma once
class Enemy {
public:
std::string Name;
int Hp;
int Atk;
Enemy(std::string setname, int sethp, int setatk) {
Name = setname;
Hp = sethp;
Atk = setatk;
}
//↓Enemyクラスのcpp
#include"Enemy.h"
#include<iostream>
void Battle::EnemyStatus() {
std::shared_ptr<Enemy> Slime(new Enemy("スライム", 50, 10));
std::cout << slime->name << "が現れた" << std::endl;
ステータスの設定にshared_ptrというワードについてあまりピンと来ていないようですが、もしかしてあまり乱用しないほうが良かったりなどありますか?
便利だと思って使うことがしばしばあります。
プレビューする前に急いで送ってしまっていろいろと間違えて送ってしまったので再掲します。><
Re: C++ パラメータの異なった敵の複製
呼び出し元から考えてみましょう。
std::shared_ptr<Enemy> Slime(new Enemy("スライム", 50, 10));
std::shared_ptr<Enemy> Drakee(new Enemy("ドラキー", 40, 15));
↑のようにすると別のステータスを設定できます。
std::shared_ptr<Enemy> Slime(new Enemy());
std::shared_ptr<Enemy> Drakee(new Enemy());
↑のようにすると同じステータスのEnemyになってしまいます。
ここまでは既にご承知でしょう。
誤字ラさんはどのように呼び出したいのですか?
std::shared_ptr<Enemy> Slime(new Enemy("スライム", 50, 10));
std::shared_ptr<Enemy> Drakee(new Enemy("ドラキー", 40, 15));
↑のようにすると別のステータスを設定できます。
std::shared_ptr<Enemy> Slime(new Enemy());
std::shared_ptr<Enemy> Drakee(new Enemy());
↑のようにすると同じステータスのEnemyになってしまいます。
ここまでは既にご承知でしょう。
誤字ラさんはどのように呼び出したいのですか?
- Dixq (管理人)
- 管理人
- 記事: 1662
- 登録日時: 14年前
- 住所: 北海道札幌市
- 連絡を取る:
Re: C++ パラメータの異なった敵の複製
たいちうさんの質問と並行してご回答頂けると幸いです。
コンストラクタで直に代入していたら、それは確かに変更が効きませんよね。
パラメータの定義を内部に持ちたいということであれば、このような実装はどうですか?
Enemyクラスの中にパラメータクラスを定義し、そのパラメータIDをセットするような実装です。
もし全てのパラメータをバラバラに設定したいのであれば、
Builderパターンを適用するか、それぞれのパラメータをセットするセッターを実装するしかないでしょう。
> ステータスの設定にshared_ptrというワードについてあまりピンと来ていないようですが
shared_ptrというのはメモリの解放を自動でやってくれるガベージコレクションのような機能であり、パラメータの設定とは話している次元が違うものです。
なお、shared_ptrにはnewではなくmake_sharedキーワードを利用します。
コンストラクタで直に代入していたら、それは確かに変更が効きませんよね。
パラメータの定義を内部に持ちたいということであれば、このような実装はどうですか?
Enemyクラスの中にパラメータクラスを定義し、そのパラメータIDをセットするような実装です。
class Enemy {
public:
class Param {
public:
int a, b, c;
};
Enemy(int id) {
_prm = _param[id];
}
private:
const static Param _param[10];
Param _prm;
};
Enemy::Param _param[10] = {
{ 1,2,3 },
{ 2,2,3 },//←これがセットされる
{ 3,2,3 },
{ 4,2,3 },
{ 5,2,3 },
{ 6,2,3 },
{ 7,2,3 },
{ 8,2,3 },
{ 9,2,3 },
{ 0,2,3 },
};
int main() {
Enemy enemy(1);
}
Builderパターンを適用するか、それぞれのパラメータをセットするセッターを実装するしかないでしょう。
> ステータスの設定にshared_ptrというワードについてあまりピンと来ていないようですが
shared_ptrというのはメモリの解放を自動でやってくれるガベージコレクションのような機能であり、パラメータの設定とは話している次元が違うものです。
なお、shared_ptrにはnewではなくmake_sharedキーワードを利用します。
Re: C++ パラメータの異なった敵の複製
メンバがわざわざpublicなのだから,変更手段は自明なわけで…
好きなタイミングで好きな値にすればよいだけでは?
「このコードは例示しただけで,本当はpublicではないのです」ということなのだとしても
【setterを書く】で終わる話なのでは?
趣向を凝らした書き方ではありませんが,最も
> 楽に
実現できると思いますが.
Re: C++ パラメータの異なった敵の複製
色々な回答ありがとうございました!
異なったパラーメータというところがどうにも伝わりづらいようで申し訳ございませんでした。
結果的には変に一つにまとめようとするよりは、素直に引数で与えてあげた方が分かりやすい。ということがわかりました。
またshared_ptrのの認識も甘かったようなので、適当なタイミングで勉強しようと思います。
異なったパラーメータというところがどうにも伝わりづらいようで申し訳ございませんでした。
結果的には変に一つにまとめようとするよりは、素直に引数で与えてあげた方が分かりやすい。ということがわかりました。
またshared_ptrのの認識も甘かったようなので、適当なタイミングで勉強しようと思います。