フラグ管理手法について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Priest
記事: 123
登録日時: 11年前
住所: 愛知

フラグ管理手法について

#1

投稿記事 by Priest » 11年前

本トピックではフラグ管理の手法について質問したいと思います。

私が現在製作中のC言語+DXライブラリを用いた三次元シューティングゲームでは、
キャラクタの行動フラグの中に、下に示す射撃を管理するフラグが用意されていました。

コード:

Pc.Flag.Shot // キャラクタPcの射撃中フラグ

// 例
Pc.Flag.Shot = 1; // 射撃状態
Pc.Flag.Shot = 0; // 射撃状態ではない
TPSなので、キャラクタの射撃方向は視点の真正面になります。
そこで、「キャラクタが撃っている間と射撃中止から60フレーム経過までは正面を向いて、60フレーム後からは進行方向を向く」処理をさせたい時、
graph.png
下記のように実装していました。

コード:

if( Pc.Flag.Shot || 射撃をやめてからの時間<60 ){
    正面を向く;
} else {
    進行方向を向く;
}

// プログラム内のどこか
if(プレイヤが射撃ボタンを押す){
    Pc.Flag.Shot = 1;
    弾を出す;
} else {
    // 直前まで撃っていたが今やめた 
    if( Pc.Flag.Shot ){
        射撃をやめてからの時間=0;
    }
    Pc.Flag.Shot = 0;
}

// main関数内のループ
while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0 ){
    略
    射撃をやめてからの時間++;
    略
}
ある時、ふと新たなフラグ設計が浮かびました。
下に示す新たなフラグ(じゃないような気もしますが…)、変数を用意し、同じ処理をさせました。
結果、処理が体感できるほどに高速になったように感じます。

コード:

Pc.Flag.LastShotFrame // 最後に射撃をしたフレーム
Game.Frame // ゲーム開始からの積算フレーム数

コード:

if(Game.Frame - Pc.Flag.LastShotFrame < 60){
    正面を向く;
} else {
    進行方向を向く;
}

// どこか
if(プレイヤが射撃ボタンを押す){
    Pc.Flag.LastShotFrame = Game.Frame;
    弾を出す;
}

// main関数内のループ
while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0 ){
    略
    Game.Frame++;
    略
}
こういった経緯がありまして、キャラクタの行動管理の手法にも色々な物があるのだなと思い、
もし、他にもっと効率的な行動管理手法があるならばご教授お願いしたく思い、投稿させていただきました。

前者は、0と1でその行動をとっているか取っていないかを管理する手法。
後者は、その行動を取った最後の時間だけを管理する手法。
他にも管理方法があれば教えてください。よろしくお願いします。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: フラグ管理手法について

#2

投稿記事 by ISLe » 11年前

これだけで体感できるほど変わるとは思えませんが。

『射撃をやめてからの時間』だけで判定できるので、先のコードをPc.Flag.Shotを使わないようにするだけで良いと思います。

コード:

if (射撃をやめてからの時間 < 60) {
    正面を向く;
} else {
    進行方向を向く;
}

// プログラム内のどこか
if (プレイヤが射撃ボタンを押す) {
    射撃をやめてからの時間 = 0;
    弾を出す;
}

// main関数内のループ
while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0) {
    略
    射撃をやめてからの時間++;
    略
}
『最後に射撃をしたフレーム』を使うと『ゲーム開始からの積算フレーム数』に依存する分保守性が下がります。

Priest
記事: 123
登録日時: 11年前
住所: 愛知

Re: フラグ管理手法について

#3

投稿記事 by Priest » 11年前

ISLeさん

ありがとうございました!
確かにFlag.Shotはない方がすっきりしますね。
今まで0,1で表現されるFlagを頼りに管理してきたものですから、
絶対使わなきゃという固定概念のようなものが住み着いていたようです。
保守性についてもごもっともです。
ISLe さんが書きました: これだけで体感できるほど変わるとは思えませんが。
これについては、『射撃をやめてからの時間』のインクリメント作業がゲームに存在しているキャラクタの数だけ行われ、
さらにその他の動作(移動、攻撃、被弾、…してからの時間)についても、同様に行っていたことが原因かもです。
一方後者ならGmae.Frame++;の一回だけで済みますから。

コード:

for(全キャラ) Pc.射撃をやめてからの時間++;
といってもFPS表示が前者より60安定するなー程度なので気のせいだったのかもしれません。

これに関連して、計算時間についてですが、
1ループ中の1回のインクリメントが、100回に増えたとしても実はそこまで速度には影響しない感じなんでしょうか?
どちらも計算量のオーダー的にはO(n)ですからそこまで影響しないかも?ですね。
今は3GHzとか計算できるCPUもでてますしね。

あらためてありがとうございました!

コード:

#include <Priest.h>
int MyPolicy ( void ) { printf( "何事も楽しくね!" ); return 0; }

nil
記事: 428
登録日時: 12年前

Re: フラグ管理手法について

#4

投稿記事 by nil » 11年前

>1ループ中の1回のインクリメントが、100回に増えたとしても実はそこまで速度には影響しない感じなんでしょうか?
現在のCPUの性能を鑑みれば影響を与えることなど無いでしょう。
それに、インクリメント一回と1つのキャラを3D空間上に描画する作業とでは後者のほうが時間がかかります。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: フラグ管理手法について

#5

投稿記事 by ISLe » 11年前

ゲームプログラムではキャラクターが個別にアニメーション用カウンタ等を持っていることはふつうにありますね。

キャラクター単位でも体感できるのは数千個レベルだと思います。
インクリメントの数で体感できるのは億レベルになるんじゃないでしょうかね。

カウントのためだけにループを増やしていったりしたら多少は遅くなるかもしれませんが、わたしは1フレーム1回のループにまとめる主義なので。

Priest
記事: 123
登録日時: 11年前
住所: 愛知

Re: フラグ管理手法について

#6

投稿記事 by Priest » 11年前

涼雅さん、ISLeさん

了解です。ありがとうございました!
計算量はあまり気にせず、がしがしプログラミングしていきますね!

コード:

#include <Priest.h>
int MyPolicy ( void ) { printf( "何事も楽しくね!" ); return 0; }

閉鎖

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