スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

タスクシステムでゲームを製作して気づいた事

前まで、下記のようにしてゲームを製作してたんですが、


~基底となるクラスの定義~ (純粋仮想関数を定義。)
class CCharaBase{
//略
};

~各クラスを定義~
class CPlayer : public CCharaBase{
//略

};

class CEnemy : public CCharaBase{
//略
};

~ゲームのメインの部分~
void GameMain(){
m_Player->Move();
m_Enemy->Move();

m_Player->Draw();
m_Enemy->Draw();
}


とても固定されたプログラムになってました。
(描画の順番変更できない。
   というか、クラスが増えたらGameMainがとても冗長な事になる。)

【冗長になっている例】
    m_Player->Move();
m_Enemy->Move();
m_Boss->Move();
m_Block->Move();
m_Bullet->Move();
     :
   //以下略



で、タスクシステム + 仕事の種類ごとにクラスを分割した結果、
ある事が分かりました。

CPlayerとか、CEnemyとか、
そういうクラスが一切要らない。


どういう事なのか、図に描いて説明してみます。

まず、上記の状態の修正版として、
CMoveManagerクラスと、CDrawManagerクラスを作りました。

それぞれ、CCharaBase*型のリストを持っており、
リストに登録されたオブジェクトのMove()とDraw()を呼び出します。

【参考画像】
tasksystem.jpg
※MoverManagerとか描いてありますが、CMoverManagerの間違いです。
(先頭の大文字Cが抜けてる。 あまり気にしないでください。)


これでメインの部分(Run関数)の内部が、
------------------------------
m_Player->Move();
m_Enemy->Move();
m_Boss->Move();

------------------------------
↑このように冗長になる事は無くなりました。
各マネージャの関数を一回呼び出して終わりです。

この段階では、まだそれぞれのクラス(CPlayerとか)は必要です。
基底のクラスを継承して、派生クラスで定義した純粋仮想関数を呼び出す方式のため。)

では次に、クラスが要らなくなってしまう瞬間をご覧下さい。
(CCharaBaseや派生クラス群のCPlayer,CEnemy,CBlock等が消える。)


-基底および派生クラス消滅までの軌跡-
まず、こう考えました。
Move関数は要らないんじゃない?と。

何故かというと、例えばアクションゲームとかでは
-----------
・重力
・強風
・バネ

-----------
このように色んな要素でプレイヤーの座標が変化します。
その色んな要素を、CPlayerのMove関数の中に詰め込んでしまうと、
Move関数の中身が汚くなるんです。

void CPlayer::Move(){
switch(m_State){
//水中の場合は
case STATE_IN_WATER:
if(GetKeyState(VK_RIGHT) < 0){
//省略
}else if(//省略)
break;
//地上の場合は
case STATE_ON_THE_GROUND:
//省略
break;
//強風の場合は
case STATE_STRONG_WIND:
//省略
break;
//強重力の場合は
case STATE_STRONG_GRAVITY:
//省略
break;
default:break;
}
}


おまけに、プレイヤーだけでなく、
敵やアイテムなんかも同じ影響を受けるとなると、
上記のソースコードを毎回コピーして微妙に内容を変える羽目になります。

これは非常に良くない。

というより、
そもそも重力とかいうのは、プレイヤーが
「重力があるみたいだな。じゃあコレぐらいの移動をしよう」

という風に決めるもんじゃないんですよ。

プレイヤーが周りの状況を見て、動き方を変えるのではなく、
周りの外部要因がプレイヤーの動き方を変えさせる

考えた方が普通なのです。


なので、CCharaBaseの純粋仮想関数Move()を削除し、
CMoverクラス & CMoverManagerクラスを創設。

これらのクラスは、上記で出たCDrawManager等と同じ構造になります。
CMover*型のリストを持っており、
登録されたCMoverのMove関数を呼び出します。

【参考画像】
tasksystem2.jpg
(各CMoverクラスは、動かす対象のオブジェクト(CCharaBase型)のポインタを保持している。)


※細かい変更点※
今までCSceneGameクラスCPlayerとかのオブジェクトを持ってたんですが、
シーンをまたいでリソースを持っておきたい状況が出てきた為、
新たにオブジェクトの存在期間を管理する、CObjectManagerを作りました。
(上記画像の右側)

具体的に説明します。

class CSceneGame : public CSceneBase {
public:
CSceneGame();
~CSceneGame();
void Run();
private:
CCharaBase* m_Player;
CCharaBase* m_Enemy;
CCharaBase* m_Block;
};

以前は、大体 上記のようになってました。
(本当はスマートポインタです。簡略化してます。)

なので、例えばゲーム画面からステージ選択画面に移動するとなると、
上記のm_Player,m_Enemyなどは一旦deleteされます。
(CDrawManagerの描画リストからも外されるようにしている。)
---------------------------------
ゲーム画面← →ステージ選択画面
---------------------------------
↑このように、シーンを行き来する度に
毎回毎回、リソースを生成・削除・生成・削除とするのは良くないので、
----------------------------------------------------------------
(リソースが多かったら、毎回ロードで待たされる。
      まるでニコゲーのように。

※ニコゲーはReplayとかすると毎回データを読み込みなおしてます。
あの仕様どうにかならないのかな・・・。
----------------------------------------------------------------
CPlayerとかの管理は、CObjectManagerが引き受け、

CSceneGameとかのシーンクラスは、
CObjectManagerに「もう、あのシーンの時に生成したリソースは消していいよ」と、
指示を与えるだけ
にしました。

【参考画像】(今まで)
tasksystem3.jpg


【参考画像】(改良後)
tasksystem4.jpg
※上記の構造で重要なのは、CDrawManagerと連携を取る事です。
例えば、【1】から【2】へ移動したときに、
CPlayerなんかは、リソースは開放しないものの、描画リストからは外しておきます。

そうしないと、「あれ、ステージ選択画面に移動したのに、
主人公や敵キャラが描画されたままになってるよ?」
という状態になります。



そして、最終段階。(今後 改良する可能性もありますが)
自分が思ったのが、
-------------------------------------------------------------------
・CMoverクラスは「動かす座標だけ」を知っていれば良い
・CDrawManagerクラスでは、「何を描画するかだけ」を知っていれば良い

-------------------------------------------------------------------
この2点です。


なので、
位置情報専門のクラス CPosInfo と、
描画情報専門のクラス CDrawInfo を作りました。

そして、今までの構造を下記のように作り変えました。
-------------------------------------------------------------------
・CObjectManagerは、CPosInfoのリストを持つ。
・CMoverManagerの持つ各Moverは、動かす対象のCPosInfoへのポインタを保持。
・CDrawManagerは、CDrawInfoのリストを持つ。
・CPlayerなどは、CDrawInfoと、CPosInfoをメンバとして持つ。

-------------------------------------------------------------------
CCharaBase*型を保持してたのが無くなった訳です
4行になっていて分かり辛いですが、要は下記の画像になります。

【参考画像】
tasksystem5.jpg

上記の状態では、
CPlayer等のコンストラクタで初期化、登録を行っているのですが、

CPlayer::CPlayer(){
//初期化
m_PosInfo.SetPos(0,-30,0);
m_DrawInfo.LoadXFile("test.x");
m_DrawInfo.SetPos(&(m_PosInfo.GetPos()));
//各マネージャーのインスタンス取得
CDrawManager& t_DrawManager = CDrawManager::getinstance();
CObjectManager& t_ObjectManager = CObjectManager::getinstance();
//各マネージャーに登録
t_DrawManager.AddDrawObject(m_DrawInfo);
t_ObjectManager.AddObject(m_PosInfo);
}


初期化・登録した後は、
描画はCDrawManagerがやりますし、
座標の保持はCObjectManagerが担当するので、

その時点でCPlayerクラス等の存在が
要らなくなってる
事に気づきました。
(メンバを全部登録してしまうので、抜け殻みたいな状態になってる。)

【参考画像】
tasksystem6.jpg
(CPosInfoを登録してる方は、CObjectManagerの間違いです。すいません。)

だったら、初めから
----------------------------------------------
・CPosInfoを初期化して登録
・CDrawInfoを初期化して登録

----------------------------------------------
この2つの処理を行うクラスを定義すれば、

CCharaBaseとか、CEnemy、CPlayer、CBlockなど
全部要らなくなるじゃないかと。
(元々、移動と描画の呼び出しを統一するために純粋仮想関数でMove()とDraw()を
 定義していたのです。 その機能を外部に全部任せるので、基底クラスも派生クラスも
  要らなくなるのは 当然の理。)

結果、
キャラクタクラスは完膚なきまでに消滅
し、
代わりに、属性を表すIDが作られました。

属性IDは、下記の3つです。
-----------------------------------------------------------
・固有ID ・・・ オブジェクト毎に異なる固有の値。 (ハンドル)
・キャラID ・・・ キャラ毎(プレイヤ・アイテム・敵)に異なる値。
・シーンID ・・・ シーン毎に異なる値。

-----------------------------------------------------------

【参考画像】
tasksystem7.jpg

それぞれの使い道を書きます。

まず固有ID。
例えば、主人公が固有ID:4の敵を倒したとします。
その時は、CDrawManagerに「リストの中から固有IDが4のの奴を描画対象から外して」
指示を出すのです。

次にキャラID。
シューティングゲームとかでは、「ボム」とかいう敵キャラのみを消滅させたりする仕様
あったりします。
この時に、CObjectManagerに「キャラIDが2(敵)の奴をリストから探して!」と指示を出します。
で、キャラIDが2の奴があればそのオブジェクトの固有IDを調べ
CDrawManagerに、「固有ID:●の奴を描画リストから外して!」と命令する訳です。
(上記画像だと、固有ID:4と5が描画リストから外れる。)

最後にシーンID。
上の方で説明しましたが、特定のシーンで生成したオブジェクト
一斉に削除する際に使います。

CObjectManagerに「SceneID:4(ゲーム画面)で生成した奴を消して!」と指示を出すと、
CObjectManagerは固有ID:3,4,5のオブジェクトを見つけ、それらの描画は停止し、
確保していたリソースは破棄されます。


初期の状態より、かなり良くなったのではないでしょうか。

何が良いかというと、下記のような事が挙げられます。
--------------------------------------------------------
・リソース確保、開放が効率的に行える。
・描画する・しない、描画の優先順位などが柔軟に決定可能。
・基底-派生の関係を使わないので、newの回数が減る。

(CCharaBase* m_Player = new CPlayer(); みたいな)
--------------------------------------------------------

あと、FlyWeightパターンがうまく使えるというのがあります。

例えば弾管理クラスというのがあったとして、
-----------------------------------------------
std::list<CBulletBase*> m_BulletList;
-----------------------------------------------
内部ではこのようなリストを持っているとします。

で、「弾」の派生クラスの、「大きな弾」クラスを生成し、登録します。
CBulletBase* m_Bullet = new CBigBullet();
t_BulletManager.AddBullet(m_Bullet);


この、m_BulletListに登録された「大きな弾」クラスはゲーム画面外に出ても、
描画対象からは外すものの、deleteはしないでおきます。

すると、また「大きな弾」が発射される時に、
-------------------------------------------------
「既にnewされた「CBigBullet」クラスはない?
      またnewするのは面倒くさいんだけど。」

-------------------------------------------------
と問い合わせれば、弾管理クラスは既にnewされたCBigBulletへのポインタを返す
という事が出来るようになるのです。

この場合は、当然「弾管理」クラスな訳ですから、「弾の派生クラス」以外は登録できません。
敵を専門的に管理したいなら、「敵管理」クラスを作る必要があります。


しかし、ひとつ上の画像を見てください。
これは『座標』という単位にまで分解してしまってるのです。

なので、敵を削除した場合は、

敵の座標だったCPosInfoを、
アイテムのCPosInfoとして使っても良いですし、
主人公が発射する弾のCPosInfoとして使っても良いのです!
(何にでもなれるよ! CDrawInfoも同じく。)

実に素晴らしいですね。
とりあえず、現在はこんな感じで開発を続けてます(`・ω・´)
スポンサーサイト

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

コメント

途中ですが

> 各マネージャの関数を一回呼び出して終わり
 タスクシステムは多種多様で細かい違いはありますが、概ねここまでが一般的なタスクシステムじゃないかと思います。

 ここからどうクラスが無くなるのかちょっと想像できません。
 楽しみにしています。

No title

なるほどv-293
上記のManager自体が、一般的なタスクシステムの一種になっているという訳ですね!
とりあえず、タスクシステム&プログラム構造を変化させていく過程を
書いていきたいと思いますv-290
(現在 画像用意中)

ともかく、色々と考えた結果
基底クラス-派生クラス(CPlayer,CEnemy・・・)という構造が消滅してしまいました。
見事に全部消滅です。

※もちろん、それ以外のCDrawManager等のクラスは必要です。
全部消滅したらC言語になってしまう。

明日中(1月24日)には完成しますv-411

No title

 気合いが入った解説お疲れ様です。
 なるほど、こうきましたか。


>CMoverクラス & CMoverManagerクラスを創設
 面白い考え方ですね。

 重力や風などの細かいレベルで CMover派生クラス(以下 Mover)を用意していくと、中規模以上のゲームではだと何十個もの Moverが1つの CCharaBaseに適用されることにもなりかねないので、最終的には全ての共通用、プレイヤー用、エネミー共通用、エネミー種類毎といった具合にある程度グルーピングして Moverを用意することになるんでしょうね。

 ちなみに Moverの実行順(XXよりも前に処理したい、必ず全ての Moverの最後で処理したい、など)の制御も登録時に行う、といった感じでしょうか?



>キャラクタクラスは完膚なきまでに消滅
 なるほど、なんとなく理解しました。
 細かい問題点はいくつか思いつきましたが、ちょっとした工夫で十分切り抜けられそうなので、概ね問題はないと思います。

 ただ、懸念点があるとすれば

・ デバッグが大変?
 マネージャが複数有るので使われなくなったとき確実に各種マネージャから消し去る仕組みが必要かも。
 例えば CPosInfoを使いまわした結果、外し忘れた Moverがあったりするとそれを見つけるのが大変です。

 又、データが分散し個別に取り扱われるので、CPosInfoなど単体からどれとどれの Moverに登録されているのか、どの CDrawInfo(こちらも複数ある場合もありそう)と関連しているのか知ることができればいいのですが、出来ない場合デバッグが結構面倒なことになりそうです。

・ 特殊な処理を必要とするもの(特に描画)の扱いが大変なになるかも
 CPosInfoの方は Moverの方で個々にカスタマイズできるので、まだいいのですが。
 CDrawInfoの方は継承しないので、描画に絡む様々な情報を取り扱うことになります。
 ざっと挙げるだけで、ソート条件、複数のレンダーステートの変更・復帰、(テクスチャリスト、モデル、などの)リソース、使用するシェーダ、(モデル・エフェクト・2Dスプライトなど)描画タイプ、位置・姿勢(行列)とかでしょうか。
 
 これくらいの範囲で収まるものであればいいのですが、そのオブジェクトだけカメラ・ライトの情報を変更したいなどといった特殊な要求も入ってきますので、その手のカスタム処理もこの中に入れていかないといけなかったりしないでしょうか?(コールバックで対処?)


 ちなみに、
>シーンをまたいでリソースを持っておきたい状況
 うちの場合は、プレイヤーなどの個々のクラスとリソース管理を分離することで解決しました。
 なので、プレイヤーそのものはステージが変われば生成しなおしています。
(領域を使いまわすと、確実に完全に再初期化できるかの保証がないので)

No title

>細かいレベルで CMover派生クラス(以下 Mover)を用意していくと
今の所は問題ないですが、確かにそうなりますねv-293
(敵100体に対し、CMoverGravityを100個newするのは
非効率的)

普遍的に影響を与えるもの(Gravityなど)は、
1つだけnewして、後はそれが複数のオブジェクトの座標を変えさせる
という仕様にしていきたいと思います。
(ここら辺は、派生クラスの定義変更で 柔軟に対応可能ですので、
    開発しながら適宜 仕様を調整する事にします。)

それと優先順位についてですが、今の所は登録の際に優先順位も引数として渡して設定してます。


>デバッグ大変?
バグが発生した場合は、
確実に、そうなるでしょうねv-292

細かい単位(座標・矩形・描画・挙動など)で分割し、
それらがポインタなり、マネージャーに問い合わせたり等でやりとりを行うので、

特にCMoverの追加・削除、CPosInfoの追加・削除を複数回繰り返した後に発生するバグに関しては、
「いつ、どこで、どうなっていたから、こういうバグになった」と
突き止めるのは難しいかと思われます。

現在はCMover1つにつき、動かすCPosInfo1つなのでまだ分かりやすいですが、
CMover同士が干渉し合ったりするようになると大変になる事が予想されます。
----------------------------------------------------
例えば、アクションゲームで2段ジャンプしたい場合、
CMoverJumpクラスが、CMoverGravity関数に、
「2段ジャンプしたので、落下開始時刻(m_FallTime)を、
現在の時刻に修正して、落下後の位置を計算してください」
と指示を出したり。
----------------------------------------------------

とりあえず、ここら辺は、
各クラスの登録・削除・変更などの仕方を厳格に決めて
予めバグ(整合性が崩れたりとか)が発生しないような仕様にする事
対処しようと思います。
(万一、バグが発生したときの為に、
固有ハンドルとかで、調べられるような仕組みも作っておこうと思います。)

>特殊な処理を必要とするもの(特に描画)の扱い
描画は厄介なんですよねv-404

何を描画するかによって、描画方法が全然違いますし、
操作(ライト・透過度変更・レンダーステートetc・・・)も
違います。

現状は、最初にリソースをロードする関数内で、
「どんな描画対象をロードしたのか?」を内部変数に覚えさせてます。
---------------------------------------------------
・LoadXFile(std::string t_XFileName);
・LoadTexture(std::string t_TextureName);

int LoadXFile(std::string t_XFileName){
m_DrawType = DRAW_TYPE_XFILE;
//略
}

---------------------------------------------------

で、例えば
XFileに固有の処理(関数の呼び出し)をした場合、
内部変数がDRAW_TYPE_XFILEなら実行、それ以外はエラー(無効)として返すようにしてます。

>その手のカスタム処理もこの中に入れていかないといけなかったりしないでしょうか?
そうなってしまいますねv-404

Textureを読み込んだ場合、
Textureに対しては全然使わない関数
CDrawInfoはいっぱい持っていたりとか、
そういう状態になります。
(コールバック形式は、今の所 考えてない状況です。)

んー・・・。

「座標」はいいとしても、
「描画」に関しては、ちょっと色々と考えた方がいいかもしれませんねv-292
(一纏めにする単位としては大きすぎるかも)

>プレイヤーなどの個々のクラスとリソース管理を分離
なるほど!
プレイヤークラスは座標周りの初期化をして、
リソースは、リソース管理クラスに「"player.x"ある?無かったら生成して!」という風に指示を出す形式にすれば、
いちいちリソースを削除・生成する自体には陥らないですねv-290

ともかく、全体的に問題が起きたら起きたで対処し、
改良法が見つかれば、また何らかの形で報告しようと思いますe-257

No title

>敵100体に対し、CMoverGravityを100個newするのは 非効率的
 たしかにそれはちょっと微妙ですよね。
 このレベルで細分化されていると1つのオブジェクトに一体いくつの Moverがつくのやら……。


>1つだけnewして、後はそれが複数のオブジェクトの座標を変えさせる
 それはいいですね。


>優先順位~登録の際に優先順位も引数として渡して設定
 なるほど。


>デバッグが大変?
>CMoverの追加・削除、CPosInfoの追加・削除を複数回繰り返した後に発生するバグ
 使用状況がどういう変遷を辿ったか、ログをとる仕組みがあるだけでも大夫違ってくるとは思いますが、システム的に人為的ミスが発生しない何か仕組みを追加した方がいいんじゃないかと。

No title

◆Moverに関して
基底-派生の関係は、色々と柔軟性はあるのですが、
newの回数が増えるのが嫌なんですよねv-292
ですからMoverに関しては、可能な限りnewを減らせるような仕組みを整えたいようにします。

あと、CDrawInfoに関してですが、
------------------------------------------
・CDrawXFileInfo
・CDrawTextureInfo

------------------------------------------
こんな感じで、リソースの種類ごとにクラスを分けて、
それらを各マネージャーで管理
してみようかなと思いました。
(マネージャーの数は増えますが、それでもnewしまくりよりかはマシと判断。)

Moverと違って、クラスの種類も限られてくるので、(テクスチャ・シェーダ・Xファイルetc・・・)
これでいいかな、と。
(CDrawManagerを、 CDrawXFileManager、CDrawTextureManagerなどに分離。)


>システム的に人為的ミスが発生しない何か仕組み
そうですねv-293
シングルトンの、インスタンスを1つに強制させる仕様のごとく
何か、「絶対にこういう事は出来ない」みたいな仕組みを作ろうと思います。
(出来る事を制限すれば、訳の分からないバグも減るでしょうし。)

まぁ、今の所は全体の仕様自体が追加・修正されたりといった状況なので、
仕様が大方固まり次第、その仕様に合わせて「どうすればバグが減らせるか?」といった仕組みも考えていこうと思いますv-290

No title

>newの回数
 これは断片化とかそのあたりを心配されているのですか?


>リソースの種類ごとにクラスを分けて、 それらを各マネージャーで管理
 それって描画順制御に影響でませんか?

No title

newの回数を減らす理由は、
断片化・速度低下・メモリリーク・メモリ確保エラーを懸念している為です。
(あまり無い方がいいかな?と。)


あと、描画に関してなんですが、
下記のようにしようかなと思ってます。
(まだ詳しい仕様を考えてなかったので、
           実際にコードにしてみました。)

元々、CDrawInfoは内部でDirectXのデバイスを保持しているクラスに、
ハンドル(int型の変数)と必要な情報(座標とか)を渡す
仲介のような役割を果たすクラスでした。
-----------------------------------------------------
void CDrawInfo::Draw(){
  CDirectXDevice& t d= CDirectXDevice::getinstance();
  td.DrawXFile(m_Handle, m_pMat);
}

-----------------------------------------------------
なので、「描画する」という機能はCDrawInfoが持っていて、
「テクスチャを重ねる」とか、
「ボーンの情報を更新する」とか、
そういうリソース特有の処理をする部分だけ、別クラスが対応するという形に
したいと思ってます。

長くなりましたが、以下ソースです。
(実際に使用を固めていく中で、色々と修正が入ると思います。)
-----------------------------------------------------
//テクスチャ・Xファイル等の描画を、Draw()で統一して
描画順位を制御できるようにするクラス。
class CDrawInfo {
public:
  CDrawInfo(){};
  ~CDrawInfo(){};

  enum DrawType{
    DRAW_UNKNOWN,
    DRAW_XFILE,
    DRAW_TEXTURE
  };

  void Draw(){
    //CDirectXCommand& t = CDirectXCommand::getinstance();
    switch(m_Type){
            case DRAW_XFILE:
                //t.DrawXFile(m_Handle, m_pMat);
                break;
            case DRAW_TEXTURE:
                //t.DrawXTexture(m_Handle, m_pMat);
                break;
            default:break;
        }
    };
private:
  int m_Handle;
  DrawType m_Type;
  D3DXMATRIX* m_pMat;
};

//テクスチャ特有の処理関数を担当するクラス。
(CTextureFuncという名称の方が良かったかも知れない。)
class CDrawTexture{
public:
  CDrawTexture(){};
  ~CDrawTexture(){};
  void TextureFuncA(){};
  void TextureFuncB(){};
  void TextureFuncC(){};
private:
  CDrawInfo m_DrawInfo;
};

//Xファイル特有の処理関数を担当するクラス。
(CXFileFuncという名称の方が良かったかも知れない。)
class CDrawXFile {
public:
  CDrawXFile(){};
  ~CDrawXFile(){};
  void XFileFuncA(){};
  void XFileFuncB(){};
  void XFileFuncC(){};
private:
  CDrawInfo m_DrawInfo;
};

//CDrawInfoの順番を制御するクラス。
class CDrawInfoManager {
public:
  CDrawInfoManager(){};
  ~CDrawInfoManager(){};
private:
  std::list<CDrawInfo> m_DrawInfoList;
};
-----------------------------------------------------
※CDirectXCommandクラスは、面倒くさい処理を隠蔽するクラス。
DXライブラリがクラスになった、みたいなもの。


・・・今思ったんですが、
処理だけをさせたいなら、
直接CDirectXCommandクラスを呼び出せばいいだけかもしれない・・・。
(CDrawTextureクラスとかは要らないかも。)

馬鹿なやり方をしてたのかもしれないので、
もう一回 よく考えて見ますv-292
(ちゃんとコードにしたり、書いてみたりしてみないと、やっぱ駄目ですね。
   考えが上手くまとまらない。)

No title

>断片化・速度低下・メモリリーク・メモリ確保エラーを懸念している
 あんまり気にしなくてもいいかと。

 DirectX/WinAPIを使っている段階で内部で newではないにしてもアロケートしまくりですし、この程度の newでは速度は落ちないです。落ちたとしても瞬間的なもので
それよりも DirectXの描画の方が遥かに重いです。
 仮にアロケートが重かったとしても、それはそれでいろいろ回避手段もありますしね。

 リークはスマートポインタで可能な限り防ぎ、アロケート状況を監視できるシステムを構築すれば仮にあってもリークを検知することができます。
 
 エラーは……どうしようもないですね。Windowsとかなら最初に?MBまでしか使わないと決めてそれを守るくらいでしょうか。


>描画
 うーん、そうですね、もうちょっと考えた方がいいかもしれませんね。

No title

なるほど!そうでしたか!v-291
やりすぎで致命的な速度低下が引き起こされたりする事は無いわけですね。

では、とりあえず、従来どおりスマートポインタでメモリリークを防ぎ、
あと、newが増えすぎないようなやり方
を考えたりして、
製作に当たってみますv-411
(なるべく、使用するメモリを抑える)

エラーに関しては、んー発生したら仕方が無いですね。
一応、エラーを出にくいようにして、もし発生した場合は
例外処理をして終わらせるようにしておこうと思いますv-293
コメントの投稿
管理者にだけ表示を許可する



上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。