アイテムの所持で節約


ゲームをやっていて、プレイヤーがあるアイテムを所持しているかどうかという情報があります。

単純に持っているか否か。または持っている場合に幾つ持っているかという場合が考えられます。

 

持っているか否かの2値なら、booleanという真偽を取るのを使えばいいのだけど、それだと使うメモリが多すぎる。私が主にやっていたCという言語だと「ビットフィールド構造体」というのがあり、それだとアイテムの情報をまとめて小さく持たせることが出来ます。

 

持っているか否かなら、0か1かの1bitあれば判断できます。

Cだと小さめのbyteという型を使って
unsigned byte 魔法の鍵=0; // 0=持っていない、1=持っている

と宣言していってもいいのですが、1byteは8bitとなったので、鍵の種類の数×8bit長のサイズが必要になります。7種の鍵があるとそれだけで7byte=56bit必要。種類が少ないうちはいいですけどね。

 

例えばアイテムの中の鍵を持っているか否かだけなら「ビットフィールド構造体」で以下の様に宣言し、それぞれの鍵が0=持っていない、1=持っているで判断することが出来ます。

struct itemKey { // 0=持っていない、1=持っている
 unsigned int 魔法の鍵 : 1;
 unsigned int 盗賊の鍵 : 1;
 unsigned int ただの鍵 : 1;
 unsigned int 秘密の鍵 : 1;
 unsigned int 部屋Aの鍵 : 1;
 unsigned int 部屋Bの鍵 : 1;
 unsigned int 洞窟Aの鍵 : 1;
};
分かりやすくするために変数名に日本語を書いちゃってるのがいけませんが(実際はkey_secretとかにする)、そのあとの数字が割り当てたいビット数です。

これだと7bitあれば7個のアイテムの所持判断が出来ます。実際はこの構造体itemKeyが全体でコンピュータの自然なビット長とかのサイズになったりしますが。(16bit PCなら9bit空白が割り振られてitemKey全体が16bit長になるとかそういうこと)

 

また持っているアイテムの個数が必要な場合、割り当てたいサイズを1でなく必要なbit数だけ宣言してあげればよいです。例えば「ただの鍵」が最大で10個まで持てるようなアイテム(使ったらなくなる)なら、2の3乗では8なので足りず、4乗が16なので4bitあれば足りますね。

struct itemKey { // 鍵の所持個数
 unsigned int 魔法の鍵 : 1;
 unsigned int 盗賊の鍵 : 1;
 unsigned int ただの鍵 : 4; // 最大値10まで←ここだけサイズを4bitに変えた
 unsigned int 秘密の鍵 : 1;
 unsigned int 部屋Aの鍵 : 1;
 unsigned int 部屋Bの鍵 : 1;
 unsigned int 洞窟Aの鍵 : 1;
};

というような宣言に変更すれば、全部で10bitあれば、「ただの鍵」を個数にした情報も含めて保持出来ることになります。(実際の構造体itemKeyのサイズは、上と同じ)

(なので、できたら無駄なく使いたいので、最大が8個とか16個とか32とか64、128、256、512、1024個とかそういう2の累乗の値になりがちなのです。そしてそういう数字をプログラムの人が切れがいい数字とかいうわけです。

 上で、3bit使うと2^3で8個だけど、0をアイテム持っていないという情報とすると、1~7のMAX7個となってしまうんだけど…。でも持っているいないの情報は別にして個数は0~7の8個までとするとか、人によって考え方ややり方が様々です。)

 

そんなこんなで昔はメモリを節約していました。

あとメモリじゃなくて実行時間の方を短縮するという問題もありますしね。下手にループさせてすごく時間がかかっていたものを、ちょっと頭を使って修正したら早く終了するようになったとか、そういうやつ。

ゲームをやっていて何となく思ったのであれこれ書いたのでした。

 

ただ、実際のゲームでは「魔法の鍵」は魔法使いがいないと使えないとか、レベルが足りずに使えないとか、そういう情報が必要かも知れません。その時はCの進化形のC++の時代になると、別の考え方でアイテム毎にclassを作り管理するのかもしれません。

class 魔法の鍵 {
 … // コンストラクタ、デストラクタ、変数等々
public:
 bool isHave(); // 持っていればtrueを、持っていなければfalseを返す
 bool canUse(); // 諸々の情報から鍵が使える状態ならtrueを、使えない状態ならfalseを返す
}
みたいな(文法不確か)

C++だと各鍵に共通の情報を含んだ「鍵(基本)」クラスから継承して各鍵クラスを宣言するとかも考えられます。

 

メモリ節約については、昔は640KBとかメモリの制限があったりして、メモリはなるべく少なく使うように考えないといけなかったのです。データの保存先も小さいので(HDDだって20MBとか40MBとかでしたし)データベースもケチって設計しないと。送るにしても小さいファイルで10分とかかかってた気がするし。

(2000年問題というのもサイズをケチって西暦を下二桁で保存したからですよね)

そういうの(メモリの節約)は今だって基本的には同じはずですが、分かりにくさを犠牲にしてまでそういう方法はとらないとか、いや絶対サイズ優先とか(ハードに乗せるファームウェアだと制限があったり)、そういう開発毎に何らかのポリシーがある場合があるのでした。

 

言語が違うと書き方は異なるし、ビットフィールドなんて高級言語にはないんじゃなかろうか?

私がプログラムをしていた時代はもうかなり前です。ゲームに関しては現在は何らかのツールとかがあって、そういう開発ツールで開発していると思うので全然違いそう。コンパイラの最適化も優秀になっていそうですし。

*ちょっと記憶で書いてしまったのでコードの書き方とか間違ってたらスマソ。

広告とか


-- 記事一覧ページへ --



Pocket

同じカテゴリーの記事

SNSでもご購読できます。