ゲームにおけるデータ構造・クラス設計・パターン
■ このスレッドは過去ログ倉庫に格納されています
0001名前は開発中のものです。
2006/08/10(木) 20:27:06ID:BnvyxuCBどのようにクラス設計をすればよいか、
継承・委譲関係はどのようにすればよいか、
使えそうなパターンは何かなど語るのもよし。
自作ゲームの内容とクラス図を書いて
改善案を聞くもよし。
設計に関して困ったことを質問するもよし。
関数の具体的な実装内容やゲーム内容に関しては他スレに譲る。
大いに語れ。
0784名前は開発中のものです。
2008/02/27(水) 23:19:17ID:9e3rMNMJC++ なら、せっかくだから関数テンプレートにしとこうか。
0785761
2008/02/28(木) 00:50:13ID:fsbSiynpCからC++に移行したばかりで手間取りそうですが…
>>783の条件分岐の記述はもうちょっとスマートに処理できそうな気がするんですが
良い方法が思いつかず…
0786名前は開発中のものです。
2008/02/28(木) 00:53:56ID:aMmxfMJe要するに本来はデバッグ検出用の関数なのね
0787名前は開発中のものです。
2008/02/28(木) 00:56:28ID:gTDbrfGi将来のための勉強にはなるかな
0788名前は開発中のものです。
2008/02/28(木) 02:04:32ID:UDo8JFjd0789名前は開発中のものです。
2008/02/28(木) 02:06:57ID:gTDbrfGiMOTHER2みたいにダメージ受けても減少するまで時間がかかるとか……
0790名前は開発中のものです。
2008/02/28(木) 02:44:14ID:fsbSiynpドラクエとかって最初から整数なのかな…
1ポイント前後のダメージって強制的に1ポイントダメージに補正されている感じだし
内部的に実数で0.1fずつ喰らったダメージが蓄積して1ポイントダメージになったりはしてなさそう
0791名前は開発中のものです。
2008/02/28(木) 07:23:54ID:71Ai97aI俺は assert() が入っていおらず、かつ UnitTest も書かれていない関数は
信用しない。
0792名前は開発中のものです。
2008/02/28(木) 07:41:00ID:cET+1oWo0793名前は開発中のものです。
2008/02/28(木) 08:43:52ID:TTiCigMJ固定小数でググれ
0794名前は開発中のものです。
2008/02/28(木) 09:17:18ID:payXug970795名前は開発中のものです。
2008/02/28(木) 14:13:32ID:gTDbrfGi今どき固定少数で処理するのってメリット少なくない?
処理速度の面でも遜色ないし使用するメモリも
そこまでケチる時代じゃないしコードも固定少数の
ほうがいくらか読みづらくなるでしょ
0796名前は開発中のものです。
2008/02/28(木) 16:35:34ID:cET+1oWofloatなら何も考えなくていいってのは違うので気をつけよう
値の比較や、演算誤差・丸め込みに注意を払う必要がある
int main() {
float a = 0.0f;
for (int i = 0; i < 100; ++i) {
a += 0.01f;
}
std::cout << a << std::endl;
return 0;
}
手元の環境だと結果は0.999999になる
あとゲームではよく使う % での剰余も出来ないので、代わりにfmod()を使う必要がある
例がFAQすぎてすまん
0797名前は開発中のものです。
2008/02/28(木) 18:26:26ID:TilB203vゲーム以前に計算機リテラシー欠乏者なのでこのスレでは無視していい存在では?
0798名前は開発中のものです。
2008/02/28(木) 18:46:41ID:C0ktJ0ww質問しようと思ったけど出直すわ
0799名前は開発中のものです。
2008/02/28(木) 19:23:14ID:TilB203v別にそんな鈍器を買わんでも、その辺の理工学書コーナーに売ってる
薄っぺらい数値計算法の初歩本(教科書)を一冊借りて読んどけばいいよ
情報工学系大学1年次の基礎教養レベルの話なんだからさ
0800名前は開発中のものです。
2008/02/28(木) 21:18:29ID:gTDbrfGi>>796の問題でバグ出すケースも少ないだろうな……
ステータスアップや次のレベルに必要な経験値テーブルなんかに
アクセスすることが多いLVは整数型にするだろうけど、
その場合は値を丸める処理がHPと同じじゃまずいし
0801名前は開発中のものです。
2008/02/28(木) 21:56:42ID:u9i/69wo0802名前は開発中のものです。
2008/02/29(金) 00:50:23ID:scJliyMvすまん
単にMOTHER2だとかドラクエだとか
DC/PS2以前のゲーム機で浮動小数なんて使わないよということが
言いたかっただけなんだw
何でもかんでもfloatにしたら配列の添え字にも使えないわ、単純な比較は出来ないわ
論理演算は出来ないわ
余計に面倒な気がするけど。
0803名前は開発中のものです。
2008/02/29(金) 00:55:40ID:pZqyzh8sHPを配列の添え字には使わんでしょう。ま、どっちでも良いんじゃない?
0804名前は開発中のものです。
2008/02/29(金) 01:11:33ID:1a1vCA3eおよそ3とか。
0805名前は開発中のものです。
2008/02/29(金) 01:20:16ID:mi6een0V0806名前は開発中のものです。
2008/02/29(金) 03:04:41ID:Su9zU3dq0807名前は開発中のものです。
2008/02/29(金) 03:05:47ID:Yy6nmC7D気をつけないといけない年齢だぜ。。。
0808名前は開発中のものです。
2008/02/29(金) 03:44:01ID:4Kq/g52z0809名前は開発中のものです。
2008/02/29(金) 13:05:12ID:MAKYfqWfこんなのダメ?
float a = val + add;
float b = val;
if ( a >= val_max ) {
val = val_max;
if ( b < val_max ) return MOMENT_FULL;
return ALREADY_FULL;
}
略
ところで>>789みたいな例ってブレゼンハムぽいことすれば固定少数必要ないんじゃない?
浮動少数も>>796を理解しててもついうっかりってのがあるしかもしれないし
0810名前は開発中のものです。
2008/02/29(金) 13:16:40ID:s07vVVTE別にタイマーでも持った方がいいと思う
0811名前は開発中のものです。
2008/02/29(金) 13:35:10ID:er34P6sc0812名前は開発中のものです。
2008/02/29(金) 14:40:49ID:dte27yiX合計10減らしたはずなのに9.999999しか減ってないとかな。
ま、このスレでは無視していい存在らしいしどうでもいいんじゃね?
0813名前は開発中のものです。
2008/02/29(金) 15:47:54ID:Yy6nmC7D0814名前は開発中のものです。
2008/02/29(金) 17:28:29ID:JGbETmbf有難うございます。
かなりスマートになりました。
ローカル変数に退避させておけばよかったんですね。
0815名前は開発中のものです。
2008/03/01(土) 20:59:06ID:ESvEWD62Delphiとか?C++Builderは言語仕様つーより、独自拡張ですね
>>802
も前のマシンはいつからDSに?
>>796-797
その後、「なんで、0.999999になるの?」って質問が出てこないから大丈夫かとw
0816名前は開発中のものです。
2008/03/01(土) 21:19:01ID:dqQWYIvh0817名前は開発中のものです。
2008/03/01(土) 21:58:24ID:sBXIWwoHもう3月だし、さすがにそれはないかw
0818名前は開発中のものです。
2008/03/02(日) 03:32:21ID:LsA47iDE0819名前は開発中のものです。
2008/03/02(日) 21:49:31ID:Hbr0sFHK0820名前は開発中のものです。
2008/03/07(金) 18:18:38ID:1kJAWqPNこの溜めている量は
自機クラスのメンバ変数に持たすべきでしょうか?
それともキー管理クラスを作って
jiki.shot2 ( joypad1.getCharge ( BTN2 ) )
みたいな感じで処理すべきでしょうか?
0821名前は開発中のものです。
2008/03/07(金) 18:25:22ID:cRszUD3e理由は、機体クラスの派生クラスで敵機クラスを作れば、
敵機の溜めショットの実装が楽になる。
0822名前は開発中のものです。
2008/03/07(金) 19:30:11ID:ZcSmZqCn溜めショット以外にも使うこと多そうだし。
カーソルとか、ポンと押した場合は1つ進むだけだけど、押しっぱなしにすると自動的にカーソルが動くとか、
そんな類の処理に流用できそう。
0823名前は開発中のものです。
2008/03/07(金) 19:36:59ID:i2RlFGNSvoid 機体クラス::update()
{
if (joypad1.getOnf() & BTN2) // getOnf() はボタン押し下げてれば真
m_shot2.Charge();
}
俺なら、こうするかなぁ。機体クラスのメンバ変数に溜めショット用の
メンバ変数を持たせる。
キー管理クラスというのが何を意図してるのかわからんけど、汎用の
パッド入力処理関数として
enum { BTN1 = 0x1, BTN2 = 0x2, BTN3 = 0x4, BTN4 = 0x8, ... };
getOnf(); // 押し下げボタンの論理和が返る
getTrg(); // 直前まで放されてて、このフレームに初めて押し下げられたボタンの論理和
getRep(); // 一定時間以上押しっぱなしのボタンの論理和
ぐらいは用意しておいた方が便利だよ。
0825820
2008/03/07(金) 23:26:54ID:1kJAWqPNちょっと出来に難があります。
1回のメインループで2回使用、例えばKEY_DOWNとKEY_UPの2種類を検出しようと
したりすると1種類目の呼び出ししか有効でなかったり。
enum BTN_STATE{ NO_PUSH, KEY_DOWN, KEY_PUSH, KEY_UP };
//「押されていない」「押下げた瞬間」「押されている状態」「押上げた瞬間」
class JoyPad{
int isPushDown[2][8];//[パッド1P、2P][ボタン数] (各ボタン押されているか否か)
public:
BTN_STATE getBtnState(int pad_num, int btn_num );
}
BTN_STATE JoyPad::getBtnState (int pad_num, int btn_num ){
int btn = ボタンが押されているか?関数( pad_num, btn_num );
if ( btn == 1 ) {//ボタンが押されていたら
if ( isPushDown[pad_num][btn_num] == 0){
isPushDown[pad_num][btn_num] = 1;
return KEY_DOWN;//「押下げた瞬間」
}else{
return KEY_PUSH;//「押されている状態」
}
}
if ( btn == 0 ) {//ボタンが押されてなければ
if(isPushDown[pad_num][btn_num] != 0){
isPushDown[pad_num][btn_num] = 0;
return KEY_UP;//「押上げた瞬間」
}
}
return NO_PUSH; //「押されていない
}
0826名前は開発中のものです。
2008/03/07(金) 23:36:57ID:6HaqHq5U0827名前は開発中のものです。
2008/03/07(金) 23:39:41ID:cRszUD3e0828名前は開発中のものです。
2008/03/07(金) 23:54:13ID:2OqKUBaL>>826も言ってるが
それぞれの状態について保存しておいて、それを参照すればいいじゃん
現在の状態をcurrentに0,1で保存するとして
押下した瞬間 on_trigger = (on_trigger ^ current) & ~current
離した瞬間 off_trigger = off_trigger ^ (^current & last)
過去の状態 last = current
0829820
2008/03/07(金) 23:56:56ID:1kJAWqPNちょっと考えて見ます
>>827
使っているのが「DXライブラリ」というDirectX用ライブラリなんですが押している状態しか
チェックできなくて難儀しています。
直接DirectXガリガリした経験がないのでわかりませんがWindowメッセージの
WM_KEYDOWN, WM_KEYUPに相当するものがあればその方が楽できそうですね…
0830名前は開発中のものです。
2008/03/08(土) 00:15:59ID:XxYr3Sol1フレーム内にon/offがあった場合検知できないのかねぇ?
(FPSを上げれば解決できそうな問題だと思うけど)
DirectXは(デバッガで止めるなどして)1フレーム内に複数の入力あっても、
全部取得できると思った。でもDirectXはその性質上最低レベルAPIだから、
DXで済ませるならDXでやったほうがいいんじゃないかな…
0831名前は開発中のものです。
2008/03/08(土) 08:33:18ID:L6W8V7J10832名前は開発中のものです。
2008/03/08(土) 09:13:25ID:S4+z8pGt低レベルな部分を隠すだけ、って割り切っちゃう。
0833名前は開発中のものです。
2008/03/13(木) 01:35:23ID:+x1fkFDE横レスすまん。
たぶん俺が根本的に何かを勘違いしているんだろうけど、
どう考えても意図がわからない。
押下した瞬間 on_trigger = current & ~last
離した瞬間 off_trigger = ~current & last
ほんとはこう?
「C,C++じゃねーよ」ってのならごめん。他の言語はわからない。
0834名前は開発中のものです。
2008/03/13(木) 10:23:04ID:QxqUuAIc0835名前は開発中のものです。
2008/03/13(木) 22:39:59ID:Bu/r75Um0836名前は開発中のものです。
2008/03/17(月) 12:58:49ID:bgIcAWWooopのコンポジション集約と、デザインパターンのコンポジットは全然別なことと、
デザインパターンのファザードがコンポジション集約と似た効果/構造してて戸惑った。
この違和感は普通にそのうち無くなるもの?
0837名前は開発中のものです。
2008/03/17(月) 14:16:30ID:hf8pDjO+そろそろ俺も覚えないと不味いな
0838名前は開発中のものです。
2008/03/17(月) 21:06:48ID:I1kfClSUストラテジー・コマンド・ステートパターンはよく使うが。
デザインパターンって言ってもgofやgof以外やマルチスレッドなやつとかwebアプリケーション用とかいろいろあるよ。
0839名前は開発中のものです。
2008/03/17(月) 21:46:13ID:6v9SY+1bあと、これも多少使うかなぁ。
・シングルトン ファイル I/O を一括管理するときとか
・オブザーバー 関連するゲームオブジェクト同士の管理(プレイヤーと、それに張り付くエフェクトとか)
実際のコードは、GoF のサンプルとはだいぶ違う形になってるけど、
まぁデザパタは設計のカタログなんで、実装の見た目が乖離する
ことはよくある。
0840名前は開発中のものです。
2008/03/17(月) 23:00:08ID:81oeEqxB0841名前は開発中のものです。
2008/03/17(月) 23:20:40ID:hf8pDjO+勉強になるよthx
まだGOF読んでないから今の段階ではさっぱりわからんけど
読むときに思い出すようにするよ
0842名前は開発中のものです。
2008/03/22(土) 13:55:51ID:bw12F9FG0843名前は開発中のものです。
2008/03/22(土) 20:22:05ID:gzkziAGJ0844名前は開発中のものです。
2008/03/22(土) 21:20:08ID:DCoIdvPZ0845名前は開発中のものです。
2008/03/22(土) 21:55:21ID:qUFi6y55でしょ
0846名前は開発中のものです。
2008/03/22(土) 22:34:31ID:bw12F9FGo がいっこ足らんぞ
Groove on Fightは名作
0847名前は開発中のものです。
2008/03/23(日) 01:18:27ID:Dg07h3ZN0848名前は開発中のものです。
2008/03/23(日) 11:58:11ID:3+fyKl7y0849名前は開発中のものです。
2008/03/23(日) 12:20:13ID:GdFVK2/80850名前は開発中のものです。
2008/03/23(日) 12:56:06ID:2zNLBPZ30851名前は開発中のものです。
2008/03/23(日) 18:28:12ID:4ckcNna2Groove on Fight・・・豪血寺3のサブタイトル
Grove On Fight・・・俺のミスタイプ
0852名前は開発中のものです。
2008/03/23(日) 20:57:34ID:dUwevhCK0853名前は開発中のものです。
2008/03/23(日) 21:19:48ID:PfMuEor50854名前は開発中のものです。
2008/03/23(日) 21:23:02ID:QBAbg4unと思う俺はたぶんまだまだ
0855名前は開発中のものです。
2008/03/23(日) 22:08:36ID:oa0oVRXo0856名前は開発中のものです。
2008/03/23(日) 22:14:12ID:t1TOnFxg基本クラス変数に派生クラス実体が入ってる時に関数を呼ぶと、
もし派生クラスがその関数をoverrideしてたら派生クラスの関数が呼ばれるんだぜ。
便利だと思わん?
0857名前は開発中のものです。
2008/03/23(日) 22:22:19ID:Oei8nD2Z0858名前は開発中のものです。
2008/03/23(日) 22:28:35ID:UjPr9gEx上に出たとおりだと、
いくつかのパターンは使ってる
ただし実装は書籍と違うけど
だと思うんだが。読み間違い?
0859名前は開発中のものです。
2008/03/23(日) 22:51:49ID:t1TOnFxg自分の中で、仮想でないメンバの上書きはシャドウで、オーバーライド=仮想メンバの上書きだと思ってた
0860名前は開発中のものです。
2008/03/23(日) 23:11:46ID:QBAbg4unそういうことができるのは知識としては持っているんだけど
例えば
モンスタークラスの派生でスライムクラス、ドラゴンクラスがあって…
とやらないで
モンスタークラスだけがあって
モンスタータイプっていうenumメンバ変数があってそれによって処理が変わる…
みたいに書いちゃうのね
まだまだスクリプト言語のときの癖が抜け切らないというか
たぶん継承をうまいこと使った方が生産性上がるんだろうけど
0861名前は開発中のものです。
2008/03/23(日) 23:22:02ID:2zNLBPZ3外部ファイル読み込み(ハードコーティングでもいいけどさ)を考えると面倒じゃない?
0862名前は開発中のものです。
2008/03/23(日) 23:40:01ID:QBAbg4unごめん。今の自分のレベルでは
継承だと外部ファイル読み込みが楽になる理由がよくわからない。
0863名前は開発中のものです。
2008/03/23(日) 23:42:50ID:/kBQhQQwノウハウとか捨てずに大事にするよろし
C++だのJavaだのC#だの使っても
最終的にはスクリプトなりテーブルなりで
キャラデータを管理することになるから
そんときに経験は生きるぜ
継承大好きっ子にありがちなハマリ道は
何でもかんでもソースに(ハードコーディングで)
記述してみたりクラス分けしてみたりして
結果として異様に複雑で深い継承木を
こさえて、仕様変更時の手間の多さに
戦慄して初心に返ること
0864名前は開発中のものです。
2008/03/23(日) 23:58:07ID:VUhk8OhJそういう使い方をするものだと思っていた。
今は>>860のスライムクラスみたいな継承の使い方をするの?
データに当たるような部分をコードに絡ませるのはなんか抵抗があるんだが。
0865861
2008/03/24(月) 00:07:17ID:tkEWMZpB言語仕様には開発者の哲学が詰まってるからなあ。
>864
俺の分かりづらい文章(>861)の翻訳dクス
0867862
2008/03/24(月) 00:21:04ID:KE3DiPkZやっぱわかんね。
>>856風の継承が>>860みたいな感じかと思っていたんだけど(違ってたらスマン)
そういう継承の仕方は主流じゃなくて
>>864風の継承(どういうクラス構成なのかはイメージがわかないけど)のが主流なのかな?
0868名前は開発中のものです。
2008/03/24(月) 00:21:28ID:uZDK8kFU実装継承を適当に使うと、そうなりがち。
インターフェース継承は、設計しっかりしてれば問題ないでしょ。
0869名前は開発中のものです。
2008/03/24(月) 00:22:39ID:Yr94LLRUいや、リア厨のときに俺はそれ(>>863)やって
ゲロ吐いたの
でも継承木ビューワの眺めは壮観だったよ
オナニープログラミング
0870861
2008/03/24(月) 00:35:53ID:tkEWMZpBあくまで、RPGっぽい敵のデータを例として挙げたから、それに対してのツッコミってことね。
他のところで使う分には知らん。
で、だ。
RPGを作ったことがないアマチュアの意見なんで、聞き流すだけでいいんだが。
敵データを外部ファイル読み込みで作るとする。
敵の動きを変更したり、敵の種類を増やしたいと思った時は、当然そのデータを弄ることで対応するわけだ。
敵のデータを変えるたびに、ソースコードの中のクラスを書き換えるのか?
敵の種類を増やしたら、派生クラスを動的に生成するのか?
そういうこと。
0871名前は開発中のものです。
2008/03/24(月) 00:42:36ID:nPahSoi8まあ多くても3回以上は継承したくはないよな
キャラ>モンスター>種族特性>個々のモンスター は既になんとやら
>>870
外部ファイルを作らず未だにステータスの固有値を派生クラスに直接書き込んでる俺はどうすrb・・・
0872名前は開発中のものです。
2008/03/24(月) 00:46:42ID:uZDK8kFURPGだと、
struct IEnemy;
class EnemyBase : public IEnemy {};
class EnemyBase : public EnemyBase {}; // 敵ザコクラス
class EnemyBoss1 : public EnemyBase {}; // 敵ボス1
class EnemyBoss2 : public EnemyBase {}; // 敵ボス2
って感じにするな。
ザコは全部一つのクラスで、データファイルとスクリプトで駆動。ボスは
プログラムでの特殊処理が必要なら、個別で作る。
0873名前は開発中のものです。
2008/03/24(月) 00:59:42ID:tkEWMZpBその辺は柔軟に、ってことね
0874862
2008/03/24(月) 01:09:59ID:KE3DiPkZえーと…
ごめん。なんか混乱してきた。
自分が何か読み違えているのかもしれないけど
>>864が>>861の翻訳であるとあったので
>>864に書いてあることを
「モンスター の 派生で スライム みたいな(哺乳類 の 派生で 犬 みたいな)
クラスの構成は間違っている。
外部データを読み込む際に便利なるような継承の仕方が実はあるよん。」
―と解釈したんだけど誤解している?
で、>>870を読むと「継承なんて使わずにデータを弄ることで挙動を変えるんだ」
と解釈したんだけど、それだと>>864の主張と矛盾するのでアレ??と思った。
どっちを勘違いしているんだろう俺は。
0875名前は開発中のものです。
2008/03/24(月) 01:23:08ID:tkEWMZpB0876名前は開発中のものです。
2008/03/24(月) 01:33:58ID:KE3DiPkZ読み違えてはいないけど矛盾もしていない?
余計にわからなくなって混乱してきたので一晩寝て考えてみる。
色々有難う。
0877名前は開発中のものです。
2008/03/24(月) 01:41:01ID:tkEWMZpB>864氏の主張を僕なりに解釈
●前半
敵データを記述するにしても、
テキストファイル(CSV)の場合もあれば、バイナリデータの場合もある。
ゲームによっては、ネット越しにデータベースへアクセスするかもしれない。
そういう部分を汎用的に書くのに継承は有効。
●後半
スライムとスライムベスとホイミスライムとドラゴンとオオアリクイと彷徨う鎧とで
いちいちクラス作ってたら一生終わんなくね?
0878名前は開発中のものです。
2008/03/24(月) 08:29:41ID:lmwW1pW4自分自身の意見としては>>877の通りなんだが、
種類ごとにクラスを作るような継承の使い方が全く見当がつかなかったので質問させてもらった。
本気で全種類分クラスを作るのか、
それともスライムとスライムベスはスライムクラスにまとめてしまうのか、
その場合出現テーブルなど外から参照するときはどうするんだ(クラス名?)とか、興味が尽きない。
実際どうやるんだ?
>>872のはどちらかというと戦闘時イベント(HP半減で台詞とか死亡エフェクトとか)など特殊処理を意識したものだと思うので
>>869の話を聞いてみたい。
0879名前は開発中のものです。
2008/03/24(月) 12:03:07ID:nPahSoi8と869ではないが予想
0880名前は開発中のものです。
2008/03/24(月) 14:53:51ID:GL5PdgnZクラス分けして幾つもの「科」を作り、何十もの「目」を作った
そして何百もの「種」を作ろうとしたとき、僕は秀丸のマクロで
大量のクラス(hpp、cpp)を作っていた
何かを間違えていることに気付き始めたのはその時だった
あれは14歳の夏休みでした
0881名前は開発中のものです。
2008/03/24(月) 14:58:03ID:kALgXEvY0882名前は開発中のものです。
2008/03/24(月) 15:00:11ID:GL5PdgnZ本気で作ったよ。リビルドにかかる時間の長さに興奮した
0883名前は開発中のものです。
2008/03/24(月) 15:00:26ID:T1jBR36AIronPythonでスライムクラスとか全部継承で作ったら面白いかも
■ このスレッドは過去ログ倉庫に格納されています