雪解けの春を待つ

しがない専門学生の徒然日記

登れない坂はただの壁だ

通勤時間は往復4時間半!驚きの遠距離通勤生活!

みたいな番組見て

 

「は???普通じゃね???」

 

って思ってしまった往復5時間半通学の六花(ろっか)です。こんばんは。

 

 

さて、最近はアクションゲームを作るべく、

壁ずりベクトルを作ってました。

 

入力は右のまま、

坂道の上では坂に沿って移動するようにする

っていうアレですね。

 

DXライブラリに外積内積を算出する関数はあるんですが、

3D用なだけあって、2Dの外積はないんですよね。

3Dではベクトル、2Dではスカラーになる、憎きあいつです。

 

というわけで作りました。ベクトルクラス。

キャラの座標とかも、点じゃなくてベクトルで保持したほうが後々便利だしね。

 

 

class Vector{

public:

 float x,y,z;

 

 Vector(float x = 0.0f, float y = 0.0f, float z = 0.0f):x(x), y(y), z(z) {}

 ~Vector() {};

 static const float GetDotVec(Vector v1, Vector v2);  //2つのベクトルの内積を返す

 static const float GetCrossVec2(Vector v1, Vector v2);  //2つのベクトルの外積を返す(2次元)

 static const Vector GetCrossVec3(Vector v1, Vector v2);  //2つのベクトルの外積を返す(3次元)

 static const float GetVecLen(Vector v);  //ベクトルの長さを得る

 static const Vector GetUnitVec(Vector v);  //ベクトルを正規化

 static const Vector VecScale(Vector v, float n);  //ベクトルをn倍する

 static const Vector GetUnitNormVec2Left(Vector v);  //2次元ベクトルの単位法線ベクトルを得る v1×v2 ベクトルの左側の方

  static const Vector GetUnitNormVec2Right(Vector v);  //2次元ベクトルの単位法線ベクトルを得る v1×v2 ベクトルの右側の方 

 static const Vector GetUnitNormVec3(Vector v1, Vector v2);  //3次元平面の単位法線ベクトルを得る v1,v2は平面上に存在するベクトル


 //オペレータ定義

 Vector& operator = (const Vector& v) { x = v.x; y = v.y; z = v.z; return *this; }

 Vector& operator + (const Vector& v) { return Vector(x + v.x, y + v.y, z + v.z); }

 Vector& operator - (const Vector& v) { return Vector(x - v.x, y - v.y, z - v.z); }

 Vector& operator += (const Vector& v) { return Vector(x += v.x, y += v.y, z += v.z); }

 Vector& operator -= (const Vector& v) { return Vector(x -= v.x, y -= v.y, z -= v.z); }

};

 

const float Vector::GetDotVec(Vector v1, Vector v2)

 { return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;}

const float Vector::GetCrossVec2(Vector v1, Vector v2)

 { return (v1.x*v2.y) - (v1.y*v2.x);}
const Vector Vector::GetCrossVec3(Vector v1, Vector v2){

  Vector Result;

  Result.x = v1.y*v2.z - v1.z*v2.y; Result.y = v1.z*v2.x - v1.x*v2.z; Result.z = v1.x*v2.y - v1.y*v2.x;

  return Result;

}
const float Vector::GetVecLen(Vector v) { return std::pow(v.x*v.x + v.y*v.y + v.z*v.z, 0.5f);}
const Vector Vector::GetUnitVec(Vector v) {

  float len = GetVecLen(v);

  Vector Result = v; Result.x /= len; Result.y /= len; Result.z /= len;

  return Result;

}
const Vector Vector::VecScale(Vector v, float n) {

  Vector Result;

  Result.x *= n; Result.y *= n; Result.z *= n;

  return Result;

}
const Vector Vector::GetUnitNormVec2Left(Vector v) {  //左回りに90度回転してるだけやで☆

  Vector Result = v;

  float tmpx = Result.x; Result.x = Result.y; Result.y = (-1)*tmpx;

  Result = GetUnitVec(Result);

  return Result;

}
const Vector Vector::GetUnitNormVec2Right(Vector v) {  //こっちは右回りやで☆

  Vector Result = v;

  float tmpx = Result.x; Result.x = (-1)*Result.y; Result.y = tmpx;

  Result = GetUnitVec(Result);

  return Result;

}
const Vector Vector::GetUnitNormVec3(Vector v1, Vector v2) {

  Vector Result = GetCrossVec3(v1, v2);

  Result = GetUnitVec(Result);

  return Result;

}

 

 

はてブロでソースコードを綺麗に公開してる人ってどうやってるの……

 

まあこれを使って、

 進行ベクトル+坂の法線ベクトル

で壁ずりベクトルが出せる、と。

 

 

 ただ、「坂に当たった」っていう判定が難しい……

外積を使うと簡単なんだけど、それでは「線分」じゃなくて「線」との判定なんだよね。

そうすると、坂の延長線上ならどこでもヒットしてしまう。

 

線分と点の当たり判定は内積でやるんだけど、

 v1・v2=|v1||v2|cosθ=|v1||v2|

この条件では誤差で全くヒットしない。

 

今は誤差範囲を設定してなんとか動いたけど、

やっぱり入力方向によっては坂をすり抜ける……

 

まあピクセル単位でやってりゃそうなるわな、って感じですが。

なんかいい方法ないかなー。

 

まだ重力もつけてないので、

まだまだ改良の余地あり、ですかね。

 

ちなみに上に乗せたコード、

プログラミング始めて半年の学生が書いたコードということにご注意ください。

おかしなところあればコメントくださるとうれしいです!

 

 

まだクラス内関数の勉強も足りないなー

constとかstaticを関数につけた時の効果とかあいまいだし……

 

先は長いなぁ

 

 

話も長くなったので今日はこれにて。