ページ 1 / 1
タスクシステムの実装について
Posted: 2010年2月28日(日) 23:33
by koki
龍神録プログラミングの館の解説を参考に、STLのdequeとstack、
そしてplacement newを使ったタスクシステムを実装した形にアレンジしたいと思っています。
具体的には、弾クラスと同じサイズのchar配列を使う弾の数だけnewし、その先頭アドレスをstackに順次格納。
必要に応じて格納したアドレスをstackからdequeに持って行っていき、そのアドレスを使って
placement newして弾オブジェクトを生成、必要なくなればオブジェクトを破棄してdequeからstackに戻す、
という手順を踏んでいます。
自機とボスを作り、弾を打ち出すところまでは出来たのですが、
敵の打ち出す弾の数があまり多くない状態でも処理落ちが酷くなってしまいます。
以下がプロジェクトファイルです。
http://www1.axfc.net/uploader/H/so/100995&key=koki
何が原因なのか分からず困っています。
どなたか教えていただけないでしょうか。
宜しくお願いします。

Re:タスクシステムの実装について
Posted: 2010年3月01日(月) 02:26
by Justy
実際に計測したわけではないので確かではないですが、
bmanage変数で operator[/url]を使って多数のアクセスをしていますよね?
環境不明なので推測ですが、これは環境によってはデバッグビルドだと
ちょっと遅い処理になるかもしれません。
なので、これを止めてみる、或いは最小限にしてみてはどうでしょうか?
forなどによるループで使用するときには
for(int i = 0; i < (int)bmanage.size(); ++i)
{
Bullet *bullet = bmanage;
...
}
のように一旦 Bulletクラスのポインタで受け、以後はそのポインタを使ってアクセスをする、とか。
あぁ、operator[/url]ではなくイテレータを使うとやはり環境によっては更に少し速くなるかもしれません。
Re:タスクシステムの実装について
Posted: 2010年3月01日(月) 17:38
by dic
イテレータを使って実装してみました
もとのスピードが遅いので、早くなった感覚はあまりしませんが
改善はされてます
//ここで弾の移動処理を行う。
std::deque<Bullet*>::iterator p;
p = bmanage.begin();
while( p != bmanage.end() )
{
(*p)->x += cos((*p)->angle*(*p)->spd);
(*p)->y += sin((*p)->angle*(*p)->spd);
(*p)->cnt++;
if( (*p)->cnt > (*p)->till ){
if( (*p)->x < -50 || (*p)->x > FIELD_MAX_X+50 ||
(*p)->y < -50 || (*p)->y > FIELD_MAX_Y+50 ){
(*p)->flag = 0;
}
}
p++;
}
/*
for(int i = 0; i < (int)bmanage.size(); ++i) {
if(bmanage->flag > 0){ //その弾が登録されていたら
bmanage->x += cos(bmanage->angle)*bmanage->spd;
bmanage->y += sin(bmanage->angle)*bmanage->spd;
bmanage->cnt++;
if(bmanage->cnt>bmanage->till){
if(bmanage[i]->x<-50 || bmanage[i]->x>FIELD_MAX_X+50 ||
bmanage[i]->y<-50 || bmanage[i]->y>FIELD_MAX_Y+50){//画面から外れたら
bmanage[i]->flag=0;//消す
}
}
}
}
*/
//弾のflagが0なら登録を解除する
p = bmanage.begin();
while( p != bmanage.end() )
{
if( (*p)->flag == 0 )
{
(*p)->~Bullet();
p = bmanage.erase(p);
}
else
p++;
}
/*
for(int j = 0; j < (int)bmanage.size(); ++j) {
if((bmanage[j]->flag) == 0) {
bmanage[j]->~Bullet();
char* memory = (char*)bmanage[j];
//delete bmanage[j];
bmanage.erase(bmanage.begin() + j);
bmem.push(memory);
memory = 0;
--j;
}
}
*/
//ボスの弾幕描画
void Boss::DrawBossBullet(){
SetDrawMode( DX_DRAWMODE_BILINEAR ) ;//線形補完描画
std::deque<Bullet*>::iterator p;
p = bmanage.begin();
while( p != bmanage.end() )
{
DrawRotaGraphF(
(*p)->x+FIELD_X, (*p)->y+FIELD_Y,
1.0, (*p)->angle+PI/2,
img_bullet[(*p)->knd][(*p)->co[/url], TRUE );
if( (*p)->eff == 1 )
SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0 );
p++;
}
/*
for(int l = 0; l < (int)bmanage.size(); ++l) {
DrawRotaGraphF(
bmanage[[/url]->x + FIELD_X, bmanage[[/url]->y + FIELD_Y,
1.0, bmanage[[/url]->angle + PI/2,
img_bullet[bmanage[[/url]->knd][bmanage[[/url]->co[/url],TRUE);
if(bmanage[[/url]->eff==1)
SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0) ;
}
*/
SetDrawMode(DX_DRAWMODE_NEAREST);//描画形式を戻す
}
これで結構速くなったのですが、まだまだ改善するところはあるようです
boss->Move( stage_count, player );
のところです
Re:タスクシステムの実装について
Posted: 2010年3月01日(月) 18:05
by dic
>これで結構速くなったのですが、まだまだ改善するところはあるようです
>boss->Move( stage_count, player );
>のところです
おもいっきり同じところ言ってますねw
これ以上はアルゴリズムを考えるしか私には思いつきません
deque(STL)使わないとか
私もSTL使ってるんですが、結構重いですね
Re:タスクシステムの実装について
Posted: 2010年3月01日(月) 18:10
by Justy
>イテレータを使って実装してみました
イテレータから Bullet *に取り出してからアクセスすると
もう少し早くなるかもしれません。
とはいえ、Releaseで処理落ちなければ気にすることはないと思います。
Re:タスクシステムの実装について
Posted: 2010年3月01日(月) 19:05
by dic
たしかにReleaseでは処理落ちしないですね
私の実装したソースでは30秒くらいでバグが起きます
ってVCメモリ食いすぎ・・・
遅いのは私の環境のメモリ不足の可能性もあるかも
Re:タスクシステムの実装について
Posted: 2010年3月01日(月) 20:22
by koki
質問の際に環境を書いていなかったですね。申し訳ないです。
私はVisualC++2008を使っています。
operator[/url]を使って多数のアクセスをしていたことが原因だったのですね。
イテレータに関する理解が今一つ浅く、使用するのに不安があった事と、forループを回す際に
見た目に分かりやすいという理由から使っていたものだったのですが、それが仇になってしまっていたとは…。
とても勉強になりました。ご回答ありがとうございました。
Re:タスクシステムの実装について
Posted: 2010年3月01日(月) 23:53
by Justy
>dicさん
> たしかにReleaseでは処理落ちしないですね
デバッグビルドで処理落ちするのは、Windowsに限らずよくある話なんですよね。
デバッグビルドなのに自分の担当分のところだけ最適化を切ってそれ以外は最適化を
かけておくとか。
>kokiさん
> operator[/url]を使って多数のアクセスをしていたことが原因だったのですね
これは環境・状況次第なところもありますが、普通の配列でも同じだったりします。
bmanageが普通の Bullet*の配列だったとしても毎回 bmanage
->xとアクセスするより、
一旦 bmanageをポインタで受けて そのポインタ経由で pBman->xとした方が
(ほんの僅かかもしれませんが)速いことが多いです。
> 私はVisualC++2008を使っています
なら
[color=#d0d0ff" face="monospace]
for each(Bullet *b in bmanage)
{
b->x += cos(b->angle) * b->spd;
...
}
[/color]
なんて書き方もできますね。
http://msdn.microsoft.com/ja-jp/library/ms177203.aspx
Re:タスクシステムの実装について
Posted: 2010年3月02日(火) 19:46
by koki
環境によって別の書き方が出来る場合もあるんですね。
参考になります。ありがとうございます。