2

私はゲームで飛行機の束を表すunsignedintを使用します。各飛行機には、飛行と接地の2つの状態があります。この状態を飛行機番号と一緒に保存したいと思います。それを達成するための「最良の」方法は何ですか?プレーンとその状態を含むstd::mapsを使用できますが、それはやり過ぎで遅いようです。ビットフラグを使用して実行できますか?テストの割り当てとテストは迅速に行う必要があります。

擬似コード:

unsigned int Boing = 777;

if( Boing is flying)
 set some bit;

is Boing flying? (how to check for the current state)

シンプルで速いテクニックのヒントは大歓迎です!

4

9 に答える 9

2

最も速くてクリーンな方法は、おそらくビットフィールドを避け、構造体を定義することです。

struct Plane
{
    bool isFlying;
    unsigned int number;
}

...


std::vector<Plane> planes;
Plane p;
p.isFlying = true;
p.number = 777;
planes.push_back(p);

この方法では、フラグを同じ単語に詰め込もうとするよりも多くのメモリを使用しますが、フィールドの取得/設定にかかる作業は少なくなります。メモリに制約がない限り、すべてをしっかりと詰め込もうとしないことを強くお勧めします。

enum状態にではなくを使用することを検討することもできboolます。

于 2011-11-07T19:39:58.697 に答える
2

簡単な方法の1つは、飛んでいない場合は数値を負にすることです。

于 2011-11-07T19:42:20.170 に答える
2
struct Stuff
{
  unsigned int Boing: 31;
  unsigned int isFlying: 1;
};

.
.
.

Stuff myStuff;
myStuff.Boing = 777;
myStuff.isFlying = false;

ビットフィールドの詳細

于 2011-11-07T19:48:11.860 に答える
1

unsigned intで使用可能な値の全範囲を使用しないと仮定すると(妥当な可能性はありますが、絶対に確実とは言えません)、範囲をunsigned in containsよりも1ビット少なく制限してから、最上位ビットを使用して「飛行」状態を保存します。その場合、次のようなことができます。

// This theoretically isn't required to work, but will for most reasonable machines.
unsigned flying_bit = 1 << (CHAR_BITS * sizeof(unsigned));

void take_off(unsigned &plane) {
    plane |= flying_bit;
}

void land(unsigned &plane) { 
    plane &= flying_bit;
}

bool is_flying(unsigned const &plane) { 
    return plane & flying_bit != 0;
}

別の可能性は、実際のビットフィールドを使用することです。

struct plane { 
    uint32_t model: 31;
    uint32_t flying: 1;
};

この場合、次のように値を直接割り当てるだけです。

plane myplane = {777, 0};

myplane.flying = 1; // take off

myplane.flying = 0; // land
于 2011-11-07T19:45:48.960 に答える
1

整数に署名してみませんか?正の値は飛んでいますが、負の値は飛んでおらず、ゼロは無効です。

于 2011-11-07T19:58:09.133 に答える
0

構造体またはクラスを使用して、情報「数値」と「状態」、および平面になりたいその他の情報を組み合わせます。intでビット演算を使用する場合(これは可能ですが、お勧めできません)、状態を変更すると、プレーンの実際の数が変更されます。

于 2011-11-07T19:41:33.440 に答える
0

unsignedintが32ビットであるとしましょう。

#define SET_FLYING(x)     (x) |= (1<<31)
#define SET_GROUNDED(x)   (x) &= ~(1<<31)
#define IS_FLYING(x)      ((x) & (1<<31))
#define ID(x)             ((x) & ~(1<<31))

よりスタイリッシュにしたい場合は、それらをインライン関数として記述できます。とにかく、私はそれをマクロとして実装するか関数として実装するかではなく、ビット操作がどのように行われるかを示すためにもっと書きました。

さまざまなサイズのintで機能させるには、31を次のように変更します。

instead of 31: ((sizeof(x)<<3)-1)

これは基本的にsizeof(x)*8-1

PS誰かが私に「いいえ、いいえ!マクロを使用しないでください。これはC ++です。私が書いたこの非常に複雑なものを使用してください」と言いたい場合は、息を止めてください。-1を付けて先に進んでください。

編集:私が上で書いたのは、あなたの質問に対する答えでした:「符号ビットをフラグとして使用する方法」。これをより良い方法で実行したいが、(を追加して)メモリ使用量を拡張しないbool場合は、いつでも次のように記述できます。

struct airplane
{
    unsigned int id: 31;
    unsigned int is_flying: 1;
};

airplane Boing = {777, false};

次に、ビット演算の割り当てと読み取り、idまたはis_flyingビット演算を実行しますが、これらはコンパイラによって処理されます。

于 2011-11-07T19:43:57.033 に答える
0

状態とプレーン番号の両方をunsignedintにパックできます。unsignedintがプラットフォーム上で32ビットであると仮定します

unsigned int myplane;
int planenumber = (myplane & 0xffff ) //can be the plane number
int booleanstate = ((myplane >> 16) & 0xffff) //can be the boolean state
于 2011-11-07T19:46:16.920 に答える
0

プレーン番号としてビットセットインデックスを使用するビットセットはどうですか?これ以上の状態が必要ない場合は、これで完了です。必要に応じて、状態ごとに使用することもできます(たとえば、クラッシュした場合、修復には個別のビットベクトルが必要だったため、実際に必要なプレーン状態ごとに正確に1ビットを使用します。

しかし、ゲームグラフィックスを扱う場合、速度が主な関心事であるとは思えません。物理学は、平面状態での操作と比較して、CPU時間の大部分を消費します。

#include <iostream>
#include <boost/dynamic_bitset.hpp>

using namespace boost;

class State
{
public:
    State(int nPlanes):_States(dynamic_bitset<>(nPlanes))
    {
    }

    void SetState(int nPlane, bool bFly)
    {
        _States[nPlane] = bFly;
    }

    void Dump()
    {
        for (boost::dynamic_bitset<>::size_type i = 0; i < _States.size(); ++i)
            std::cout << _States[i];
    }

private:
    dynamic_bitset<> _States;
};


int _tmain(int argc, _TCHAR* argv[])
{
    State planes(500);
    planes.SetState(0, true);
    planes.SetState(5,true);
    planes.Dump();

    return 0;
}
于 2011-11-07T20:14:11.310 に答える