れいざー再び(回転レーザーの判定編)

ちまちまとゲーム作ってます。んで、前にやったレーザーの判定をちこっと直しました。


先ずはおさらい。レーザーを矩形判定でやるので、矩形を直線状に並べて処理します。

  // レーザ判定(抜粋)
//POINT Pos; // レーザーの当たり判定の発生位置(適当に初期化しておく)
//int Size; // レーザー判定の大きさの半分(適当に初期化しておく)
  const int Pitch = (Size*2)>>8; // 間隔。判定の大きさに等しい(ので倍)

  int dx = Pitch*(COS4096(Angle)>>8);
  int dy = Pitch*(SIN4096(Angle)>>8);

  for( int Length = GetLength(pObj)<<8;
    Length > 0;
    Length-=Pitch, Pos.x += dx, Pos.y += dy
      )
  {
    CAttackRect tmpAttackRect // 当たり判定構造体
      (
        Pos.x - Size,
        Pos.y - Size,
        Pos.x + Size,
        Pos.y + Size,
        ID,
        pObj,
        Attackin
      );
    AttackP2E.AddAttackin( &tmpAttackRect ); // 判定を登録
  }

怪しいシフト演算とかは固定少数に囚われている私の病気なんで気にしないでください。そんで、コレを当たり判定表示モードで描画してみると。。。

続いて、レーザーを回転させることを考える。レーザーは回転させると離れた位置ではとんでもない移動量が発生する。従って、上のようなちんまい判定そのままでやるとすり抜けが発生してしまう。なので、判定的には自機を基点として角度は回転の増分とする三角形でやりたい(角度の増分とは、1フレームで自機が回転する量のこと)。もちろん、三角形の判定は面倒なので、矩形で近似しますすす。

  // 回転レーザ判定(抜粋)
//POINT Pos; // レーザーの当たり判定の発生位置(適当に初期化しておく)
//int Size; // レーザー判定の大きさの半分(最小値)適当に初期化しておく
  int Delta = (((Angle - PrevAngle)/2 + 1024) & 2047 ) - 1024;  // 回転増分の半分
  Angle -= Delta;  // 現在角度から引く(現在の直線と前回の直線の間となる)

  if( Delta < 0 )
    Delta = -Delta;

  int SinA = SIN4096(Angle)>>8;
  int CosA = COS4096(Angle)>>8;

  int TanD = SIN4096(Delta)/(COS4096(Delta)>>8);

  for( int Length = GetLength(pObj)<<8; Length>0; )
  {
    int Pitch = (Size*2)>>8; // 間隔。判定の大きさに等しい(ので倍)
    Length -= Pitch;

    Pos.x += Pitch * CosA;  // 判定の中心をずらす
    Pos.y += Pitch * SinA;  // 判定の中心をずらす

    Size += Pitch * TanD;  // 矩形サイズを大きくする

    CAttackRect tmpAttackRect
      (
        Pos.x - Size,
        Pos.y - Size,
        Pos.x + Size,
        Pos.y + Size,
        ID,
        pObj,
        Attackin
      );
    AttackP2E.AddAttackin( &tmpAttackRect );  // 判定を登録
  }

こんな感じ。途中の「矩形サイズを大きくする」ってのが微妙に謎で、っていうか後でみた私が判んなかったのでメモしておくと、

みたいな感じで、矩形判定の間隔(Pitch)にタンジェントの値をかけると矩形判定の増分が得られるみたいです。へー。

そんなこんなで、

こう。チラッとだけ見えてる赤い直線は実は表示しているレーザーだったりして、めちゃくちゃ誤差が出ているわけなんですが、まあ判定を表示して見せるわけじゃないんで大体でいいんすよ。