移動量は極座標
はじめに
今回は初心者向けの内容です。
移動量の定義をするには、「極座標」が向いている、
ということを理解してもらえれば、と思います。
デカルト座標の欠点
今まで良く考えずに、こんな構造体を定義していました。
/** * 2次元ベクトル */ struct Vec2 { float x, y; }; /** * スプライト構造体 */ struct Sprite { Vec2 pos; // 座標 Vec2 mov; // 移動量 };
こうすると、移動させる場合は、
pos += mov;
とすればいいので楽なのですが、実は移動量の算出時に不便です。
というのは、例えばシューティングの定番弾幕である「扇形弾幕」
を生成するとします。
この場合必要なパラメータは、
- 速さ
- 方向
です。
ですが、movが持っているのは、x,yの移動量なので、
目的の「速さ」と「方向」を算出するのは大変です。
というのはx方向への移動量を-1、y方向への移動量を1とすれば、
確かに225度の方向へ飛んでいきます。
でもそこから扇形を作るには、数度ズラして、、、
とするわけですが、mov.xやmov.yがすごい数になってしまいますね。
また、速度を決めるのも大変です。
そこで、移動量を簡単に決めるために、
x,yの座標ではなく、「速さ」と「方向」を持つ座標系に変換します。
この「速さ」と「方向」を持つ座標を、「極座標」と言います。
極座標
/** * 極座標構造体 */ struct Polar { float theta; // 角度 float speed; // 速度 };
これで、直感的に弾幕を作成することができます。
// 扇形弾幕生成(5度ずつズラす) bullet[0].mov = Polar(225, 5); bullet[1].mov = Polar(230, 5); bullet[2].mov = Polar(235, 5); bullet[3].mov = Polar(240, 5); bullet[4].mov = Polar(245, 5);
でも、いざ移動をする場合には、
このままでは移動後の座標を求めることができません。
そこで、「極座標」をx,y座標に変換する必要があります。
方法としては、三角関数を利用します。
pos.x += cos(mov.theta)*speed; pos.y += sin(mov.theta)*speed;
おまけ
関連事項として、プレイヤーの移動量の算出について触れておきます。
まず、悪い例です。
if(IsPress(KEY_LEFT)) player.pos.x -= 5; if(IsPress(KEY_UP)) player.pos.y -= 5; if(IsPress(KEY_RIGHT)) player.pos.x += 5; if(IsPress(KEY_DONW)) player.pos.y += 5;
こうしてしまうと、図のように斜めの移動量が大きくなってしまいます。
これは、シューティングやアクションゲームでは致命的な作りになってしまいます。
というのは例えば、スルリと敵の間をすり抜けようとしたのに、
斜めだけ移動量が大きくて、勢い余って、敵に衝突してやられてしまった、
という事態が発生するからです。
(たいていのプレイヤーは、斜めの移動量が大きいなんてことには気づかないことが多い)
良いゲームをデザインする方法として、
「プレイヤーの納得しない理由でミスをさせてはいけない」
ということがあげられます。
これだと、プレイヤーは自分のミスに納得できませんよね。
そこで、例えば、
if(IsPress(KEY_LEFT) && IsPress(KEY_UP)) { player.mov.theta = 135; player.mov.speed = 5; } ・ ・ ・ player.pos += player.mov.ToVec2(); // 極座標をx,y座標に変換して加算
とするのが良い方法となります。