コンピューターは全ての情報を「0」と「1」の箱で記憶します。
ここでは、9種類のバラバラなデータを、32個の小さな箱(32bit)に隙間なく敷き詰めて、
最終的に「たった1つの大きな数字」に変換(パッキング)する仕組みを体験できます。
🧩 32個の小さな箱(0か1しか入りません)
⬇️
上の9つのデータを、すべて合体させた1つの数字
0
🚀 パッキングするとデータはどう動く?(通信・処理シミュレーション)
CPUからメモリへ、あるいはネットワーク経由でデータを送る場合を想像してください。
パッキングをしない場合、9個のデータを別々に送る必要がありますが、パッキングをすれば1回の送信で完了します。
💡 仕組みの解説
⚡
なぜわざわざ「1つの数字」にまとめるのか?
たくさんの独立したデータを扱う際、メモリへのアクセス回数やネットワークの通信回数が増えると、それが処理のボトルネック(渋滞)になります。32個のビットにデータを敷き詰めて1つの整数(32bit整数)として扱うことで、1回の処理で複数のデータを同時に移動・コピー・保存できるようになり、パフォーマンスが劇的に向上します。
📉
マイナスの数字はどうやって表現しているのか?
上の「変化量」のスライダーをマイナスに動かしてみてください。割り当てられた領域の一番左側の箱が「1」になることがわかります。コンピューターの内部では、特別なマイナス記号を使わず、割り当てられたビット列の最上位ビット(一番左のビット)を「マイナスの目印」として扱う方法(2の補数表現)が広く用いられています。
32個の小さな箱(32bit)の中に詰め込まれた9つのデータが、
実際のゲームやアプリケーションの中で「何を意味しているのか」を具体的に解説します。
⚡ パワー(基本ステータス)
各2個の箱(2bit)を使用し、「0〜3」の4段階の値を表現します。主にキャラクターやアイテムの基礎的な強さ・ランクを表します。
パワーA (0〜1bit)
例:
攻撃力のランク。
0=非力、1=普通、2=強い、3=最強
パワーB (2〜3bit)
例:
防御力のランク。
0=紙装甲、1=普通、2=硬い、3=鉄壁
パワーC (4〜5bit)
例:
素早さのランク。
0=鈍足、1=普通、2=俊敏、3=神速
📈 変化量(動的パラメータ)
各6個の箱(6bit)を使用し、「-32〜31」の値を表現します。最上位ビットをマイナスの目印として使うことで、増減(バフ・デバフ)や相対的な移動を表現できます。
変化量A (6〜11bit)
例:HPの増減量。
+10なら回復、-15ならダメージ。
またはX軸への移動距離。
変化量B (12〜17bit)
例:スタミナの増減量。
走ると減り、休むと回復する。
またはY軸への移動距離。
変化量C (18〜23bit)
例:魔力・エネルギーの増減。
スキルの効果時間(残り時間)のカウントダウン(マイナス変化)など。
⚙️ 状態・🛡️ ダメージ・🧳 予備ポケット
キャラクターの現在の状況や、システム拡張のためのフラグ(目印)として機能します。
状態 (24〜26bit)
現在のモードや状態異常など、最大8種類を区別します。
0: 正常
1: 毒状態
...など
ダメージ (27〜29bit)
受けているダメージの重症度や属性。
0: 無傷
7: 致命傷(属性IDなど)
予備 (30〜31bit)
現在は使われていない空きスペースです。将来の機能拡張のために確保されています。
💻 実際のプログラムでの書き方(JavaScript例)
シフト演算子(<<、>>)と論理積(&)、論理和(|)を使って、データの出し入れを行います。
1. データを1つの数字にまとめる(パッキング)
const packData = (pA, pB, pC, cA, cB, cC, st, dm, rs) => {
// マイナス値(-32〜31)を、6bitで表現できる正の数(0〜63)に変換する魔法の関数
const enc6 = (v) => (v < 0 ? v + 64 : v) & 0x3F;
return (
(pA & 0x3) | // 0〜1bit目 (2bit)
((pB & 0x3) << 2) | // 2〜3bit目へ左に2ずらす
((pC & 0x3) << 4) | // 4〜5bit目へ左に4ずらす
(enc6(cA) << 6) | // 6〜11bit目 (6bit)
(enc6(cB) << 12) | // 12〜17bit目
(enc6(cC) << 18) | // 18〜23bit目
((st & 0x7) << 24) | // 24〜26bit目 (3bit)
((dm & 0x7) << 27) | // 27〜29bit目 (3bit)
((rs & 0x3) << 30) // 30〜31bit目 (2bit)
) >>> 0; // 最後に符号なし32bit整数として確定させる
};
2. 1つの数字からデータを取り出す(アンパッキング)
const unpackData = (packedValue) => {
// 6bitの値(0〜63)を取り出した後、マイナスを含む元の値(-32〜31)に戻す関数
const dec6 = (v) => (v & 0x20 ? v - 64 : v); // 最上位ビット(32)が立っていればマイナス
return {
pA: packedValue & 0x3, // 一番右の2bitを取り出す
pB: (packedValue >>> 2) & 0x3, // 右に2ずらして2bit取り出す
pC: (packedValue >>> 4) & 0x3,
cA: dec6((packedValue >>> 6) & 0x3F), // 6ずらして6bit分(0x3F)取り出し、元に戻す
cB: dec6((packedValue >>> 12) & 0x3F),
cC: dec6((packedValue >>> 18) & 0x3F),
st: (packedValue >>> 24) & 0x7, // 24ずらして3bit分(0x7)取り出す
dm: (packedValue >>> 27) & 0x7,
rs: (packedValue >>> 30) & 0x3 // 30ずらして2bit取り出す
};
};