private static void CalculateVectors3(Slope myObject, Object targetObject) { // targetObjectの矩形の判定に使う点を求める defPositionVector[0] = targetObject.position; defPositionVector[1] = defPositionVector[0] + new Vector2(targetObject.width, 0); defPositionVector[2] = defPositionVector[0] + new Vector2(targetObject.width, targetObject.height); defPositionVector[3] = defPositionVector[0] + new Vector2(targetObject.width / 2, targetObject.height); defPositionVector[4] = defPositionVector[0] + new Vector2(0, targetObject.height); // 直角三角形の辺ベクトルを計算(時計回り) /* [0]End * /| * / | * / | * / | * / | * [0]Start([2]End)/_____|[1]End */ myObject.sideVectorStart[0] = myObject.position + new Vector2(0, myObject.height); // 斜面下側 myObject.sideVectorEnd[0] = myObject.position + new Vector2(myObject.width, 0); // 斜面上側 myObject.sideVectorStart[1] = myObject.sideVectorEnd[0]; // 右端上側 myObject.sideVectorEnd[1] = myObject.position + new Vector2(myObject.width, myObject.height); // 右端下側 myObject.sideVectorStart[2] = myObject.sideVectorEnd[1]; // 下端右側 myObject.sideVectorEnd[2] = myObject.sideVectorStart[0]; // 下端左側 // foreachは割り当てには使えない for (int i = 0; i < myObject.sideVector.Length; i++) myObject.sideVector[i] = myObject.sideVectorEnd[i] - myObject.sideVectorStart[i]; }
private static void CalculateVectors4(Slope myObject, Object targetObject) { // Character矩形の頂点を求める // Point1: defPositionVector[1] = targetObject.position; // Point2: defPositionVector[2] = defPositionVector[1] + new Vector2(targetObject.width, 0); // Point3: defPositionVector[3] = defPositionVector[1] + new Vector2(targetObject.width, targetObject.height); // Point4: defPositionVector[4] = defPositionVector[1] + new Vector2(0, targetObject.height); defPositionVector[0] = defPositionVector[1] + new Vector2(targetObject.width / 2, targetObject.height); // Characterの速度ベクトルを引く point0(底辺中点)になるように補正 // 速度だと全部等しくなるので一旦辺にしてみるか... prevVector = targetObject.locus[0] + new Vector2(targetObject.width / 2, targetObject.height);//defPositionVector[3]; curVector = targetObject.position + new Vector2(targetObject.width / 2, targetObject.height); //drawPos;//defPositionVector[4]; speedVector = curVector - prevVector; // 斜面のslopeVector myObject.slopeVectorDown = myObject.position + new Vector2(0, myObject.height); // 斜面下側 myObject.slopeVectorUp = myObject.position + new Vector2(myObject.width, 0); // 斜面上側 myObject.slopeVector = (myObject.slopeVectorUp - myObject.slopeVectorDown); // 斜面のベクトル // 上を三角形の辺全てに拡張 myObject.sideVectorStart[0] = myObject.position + new Vector2(0, myObject.height); // 斜面下側 myObject.sideVectorEnd[0] = myObject.position + new Vector2(myObject.width, 0); // 斜面上側 myObject.sideVectorStart[1] = myObject.sideVectorEnd[0]; // 右端上側 myObject.sideVectorEnd[1] = myObject.position + new Vector2(myObject.width, myObject.height);// 右端下側 myObject.sideVectorStart[2] = myObject.sideVectorEnd[1];// 下端右側 myObject.sideVectorEnd[2] = myObject.sideVectorStart[0];// 下端左側 for (int i = 0; i < 3; i++) myObject.sideVector[i] = myObject.sideVectorEnd[i] - myObject.sideVectorStart[i]; // vectors vectors[0] = defPositionVector[0] - myObject.slopeVectorDown; }
private static void CalculateCrossPoints4(Slope myObject, Object targetObject) { /* alice syndromeが... * 交点=A+ベクトルAB*①/ (①+②) * ①:(defPositionVector[sideNum] - myObject.slopeVectorDown) × slopeVector * ②:(defPositionVector[sideNum+1] - myObject.slopeVectorDown) × slopeVector */ float crossProduct1 = 0; float crossProduct2 = 0; crossProduct1 = (prevVector.X - myObject.slopeVectorDown.X) * myObject.slopeVector.Y// もしかして正負逆転の必要?それはないか... - myObject.slopeVector.X * (prevVector.Y - myObject.slopeVectorDown.Y); crossProduct2 = (curVector.X - myObject.slopeVectorDown.X) * myObject.slopeVector.Y - myObject.slopeVector.X * (curVector.Y - myObject.slopeVectorDown.Y);//Math.Abs()やったらもっとひどくなった*/ crossPoint = prevVector + new Vector2(speedVector.X * (crossProduct1 / (crossProduct1 + crossProduct2)),// crosuProduct2がおかしい そもそも比が-ってなんだ speedVector.Y * (crossProduct1 / (crossProduct1 + crossProduct2)));// ratioを()でくくるのを忘れてた*2 // 交点計算(交差する場所が遠い場合変な値にもなるだろうが最近の交点にはたどり着けるだろう) for (int i = 0; i < 3; i++) { crossProduct1 = (prevVector.X - myObject.sideVectorStart[i].X) * myObject.sideVector[i].Y// もしかして正負逆転の必要?それはないか... - myObject.sideVector[i].X * (prevVector.Y - myObject.sideVectorStart[i].Y); crossProduct2 = (curVector.X - myObject.sideVectorStart[i].X) * myObject.sideVector[i].Y - myObject.sideVector[i].X * (curVector.Y - myObject.sideVectorStart[i].Y); // X成分はまともだがYが異常である たまにInfinityとかになる crossPoints[i] = prevVector + new Vector2(speedVector.X * (crossProduct1 / (crossProduct1 + crossProduct2)), speedVector.Y * (crossProduct1 / (crossProduct1 + crossProduct2))); }// 動かないと当然speedVectorは0 Vector2 max = new Vector2(0, 0); float maxDistance = 0; //float prevMaxDistance = 0; //foreach(Vector2 crossPoint in crossPoints) { for (int i = 0; i < crossPoints.Length; i++) {// crossPointsがみんな同値になってしまう。辺でやるとやはり変わったが float distance = Vector2.Distance(crossPoints[i], defPositionVector[0]);//crossPoint - prevVector;//targetObject.position; //if (max < distanceD) { //prevMaxDistance = distanceD; if (i == 0) maxDistance = distance; if (maxDistance >= distance) { maxDistance = distance; sideNum = i; } } if (sideNum == 1) { } }
private static void CalculateCrossProduct3(Slope myObject, Object targetObject) { //myObject.sideNum = 0; vectors[0] = defPositionVector[2] - myObject.sideVectorStart[0];// 3 vectors[1] = defPositionVector[0] - myObject.sideVectorStart[1];// 4 1 vectors[2] = defPositionVector[0] - myObject.sideVectorStart[2];// CheckDirection(myObject, targetObject); for (int i = 0; i <= 2; i++) crossProduct[0, i] = (myObject.sideVector[i].X * vectors[i].Y) - (vectors[i].X * myObject.sideVector[i].Y); // 初期化 targetObject.isHit = false; myObject.isHit = false; myObject.isUnderSomeone = false; targetObject.isOnSomething = false; // マップチップの矩形領域内に入っているか否かで大まかに絞る if (myObject.position.X + myObject.width < targetObject.position.X) { } else if (targetObject.position.X + targetObject.width < myObject.position.X) { } else if (targetObject.position.Y + targetObject.height < myObject.position.Y) { } else if (myObject.position.Y + myObject.height < targetObject.position.Y) { } else { // targetObjectは矩形内にいる if (targetObject.speed.Y > 0 && myObject.sideNum == 0 && crossProduct[0, 0] > 0) { targetObject.isHit = true; myObject.isHit = true; // 着地処理 targetObject.isOnSomething = true; targetObject.jumpCount = 0; targetObject.isJumping = false; myObject.isUnderSomeone = true; adjustObject3(myObject, targetObject); } if (targetObject.speed.X < 0 && myObject.sideNum == 1 && crossProduct[0, 1] > 0) {// 右側が壁の斜面チップを対象 targetObject.isHit = true; myObject.isHit = true; if (myObject.position.X + myObject.width - targetObject.position.X < myObject.maxLength) { if (targetObject.position.Y + targetObject.height > myObject.position.Y && targetObject.position.Y < myObject.position.Y + myObject.height) { targetObject.position.X = myObject.position.X + myObject.width;// 右に補正 } } } else if (targetObject.speed.Y < 0 && myObject.sideNum == 2 && crossProduct[0, 2] > 0) { targetObject.isHit = true; myObject.isHit = true; if (targetObject.position.X + targetObject.width > myObject.position.X && targetObject.position.X < myObject.position.X + myObject.width) { if (myObject.position.Y + myObject.height - targetObject.position.Y < maxLength) { targetObject.speed.Y = 0; targetObject.position.Y = myObject.position.Y + myObject.height;// 下に補正 } } } } }
private static void adjustObject4(Slope myObject, Object targetObject) { //Vector2 adjustVector; Vector2 criterionVector = new Vector2(targetObject.position.X + targetObject.width / 2, targetObject.position.Y + targetObject.height);// 底辺の中点 float xFromDown; /*targetObject.scalarSpeed = 0; adjustVector = (criterionVector - crossPoint) * (-1);//curVector targetObject.position += adjustVector;// drawVectorじゃだめっぽい?*/ //targetObject.position = crossPoint - criterionVector;//new Vector2(targetObject.width, targetObject.height); if (targetObject.isHit) { if (criterionVector.X < myObject.position.X + myObject.width) { xFromDown = targetObject.position.X + targetObject.width / 2 - myObject.position.X;//kokoda targetObject.position.Y = myObject.position.Y + myObject.height - xFromDown; targetObject.position.Y -= targetObject.height - 1; targetObject.speed.Y = (float)-targetObject.gravity - 1;// 振動☆ } } /*if(isCrossSide[0]) { if (criterionVector.X < myObject.position.X + myObject.width) { adjustDistance = targetObject.position.X + targetObject.width / 2 - myObject.position.X;//kokoda targetObject.position.Y = myObject.position.Y + myObject.height - adjustDistance; targetObject.position.Y -= targetObject.height; } } else if(isCrossSide[1]) { if (targetObject.scalarSpeed < 0 ) {// 右側が壁の斜面チップを対象 // このようにy方向を絞ると斜面を下ってる途中でめりこんでると判定されてしまう。 if (myObject.position.X + myObject.width - targetObject.position.X < myObject.maxLength) {// ブロックの右端 if (targetObject.position.Y + targetObject.height > myObject.position.Y && targetObject.position.Y < myObject.position.Y + myObject.height) { targetObject.position.X = myObject.position.X + myObject.width;// 右に補正 } } } }*/ }
private static void CalculateCrossPoint3(Slope myObject, Object targetObject) { /* alice syndromeが... * 交点=A+ベクトルAB*①/ (①+②) * ①:(defPositionVector[sideNum] - myObject.slopeVectorDown) × slopeVector * ②:(defPositionVector[sideNum+1] - myObject.slopeVectorDown) × slopeVector */ float crossProduct1 = 0; float crossProduct2 = 0; // Characterの速度ベクトルを引く point3の軌跡にしてみる prevVector = targetObject.locus[0] + new Vector2(targetObject.width, targetObject.height); speedVector = curVector - prevVector;// ここまではおkそう // 下記はCharacterの辺との交点計算用 /*crossProduct1 = (defPositionVector[sideNum].X - myObject.slopeVectorDown.X) * myObject.slopeVector.Y - myObject.slopeVector.X * (defPositionVector[sideNum].Y - myObject.slopeVectorDown.Y); crossProduct2 = (defPositionVector[sideNum+1].X - myObject.slopeVectorDown.X) * myObject.slopeVector.Y - myObject.slopeVector.X * (defPositionVector[sideNum+1].Y - myObject.slopeVectorDown.Y); crossPoint = defPositionVector[sideNum] + new Vector2 (vectors[sideNum].X * crossProduct1 / crossProduct1 + crossProduct2, vectors[sideNum].Y * crossProduct1 / crossProduct1 + crossProduct2);*/ crossProduct1 = (prevVector.X - myObject.slopeVectorDown.X) * myObject.slopeVector.Y// もしかして正負逆転の必要?それはないか... - myObject.slopeVector.X * (prevVector.Y - myObject.slopeVectorDown.Y); crossProduct2 = (curVector.X - myObject.slopeVectorDown.X) * myObject.slopeVector.Y - myObject.slopeVector.X * (curVector.Y - myObject.slopeVectorDown.Y);//Math.Abs()やったらもっとひどくなった // X成分はまともだがYが異常である crossPoint = prevVector + new Vector2(speedVector.X * (crossProduct1 / (crossProduct1 + crossProduct2)),// crosuProduct2がおかしい そもそも比が-ってなんだ speedVector.Y * (crossProduct1 / (crossProduct1 + crossProduct2)));// ratioを()でくくるのを忘れてた*2 }
private static void adjustObject3(Slope myObject, Object targetObject) { Vector2 criterionVector = defPositionVector[3];//new Vector2(targetObject.position.X + targetObject.width / 2, targetObject.position.X + targetObject.height);// 底辺の中点 float adjustDistance = 0; /*if (myObject.degree == 45) adjustDistance = targetObject.position.X + targetObject.width / 2 - myObject.position.X; else if (myObject.degree == 22.5f) adjustDistance = 5; else if (myObject.degree == 11.25f) adjustDistance = 5;*/ // CDクラスでは一般的に書いて場合分けはSlope classでやろう targetObject.speed.Y = 0; if (criterionVector.X > myObject.position.X && criterionVector.X < myObject.position.X + myObject.width) { adjustDistance = targetObject.position.X + targetObject.width / 2 - myObject.position.X; targetObject.position.Y = myObject.position.Y + myObject.height - adjustDistance; targetObject.position.Y -= targetObject.height; } // 上端付近での当たり判定 else if (criterionVector.X > myObject.position.X + myObject.width && targetObject.position.X < myObject.position.X + myObject.width) { //if(targetObject.position.Y -targetObject.height == myObject.position.Y) //if (targetObject.position.Y + targetObject.height - myObject.position.Y < myObject.maxLength) { targetObject.position.Y = myObject.position.Y - targetObject.height; // 上に補正 //targetObject.position.Y = myObject.position.Y - targetObject.height;// 上端付近 } // 下端付近での当たり判定 else if (criterionVector.X < myObject.position.X && targetObject.position.X + targetObject.width > myObject.position.X) { targetObject.position.Y = myObject.position.Y + myObject.height - targetObject.height; // これだと上るときに引っかかる。斜面の高さに合わせる //targetObject.gravity = 0; //adjustDistance = targetObject.position.X + targetObject.width - myObject.position.X; //targetObject.position.Y = (myObject.position.Y + myObject.height /*- adjustDistance*/) - targetObject.height; } }
/// <summary> /// ベクトルを用いた斜面用の衝突判定メソッドを直角三角形の全ての辺にぶつかるように拡張したもの /// </summary> /// <param name="myObject"></param> /// <param name="targetObject"></param> public static void RightTriangle(Slope myObject, Object targetObject) { // 3辺のベクトルの右左ではいってくる方向わかるじゃないか 何故気づかなかった... CalculateVectors3(myObject, targetObject);// 辺ではなく頂点 CalculateCrossProduct3(myObject, targetObject); }
/// <summary> /// 斜面ベクトルとの交差判定での当たり判定のテスト:矩形内にある→速度ベクトルと斜面ベクトルとで交差判定→ /// 交差してたら交点計算→prevVectorと比較して一番近い交点を持つ辺を判定。 /// </summary> public static void CDatTerrain4(Slope myObject, Object targetObject) { // 速度ベクトルを使って押し戻すのは何回もやってきたが、結局それは無理だということが明らかになりますた CalculateVectors4(myObject, targetObject);// 辺ではなく頂点 IsCross4(myObject, targetObject); }
private static void IsCross4(Slope myObject, Object targetObject) { // slopeVectorとVectorsとで外積を計算する // 判定すべきVectorsはslopeVectorの始点からtarget_objectの各頂点に引いた4つだけなので、slopeVectorと4回だけ判定すればよい for (int i = 1; i < 5; i++) crossProduct[0, i] = (myObject.slopeVector.X * vectors[i].Y) - (vectors[i].X * myObject.slopeVector.Y); myObject.isHit = false; myObject.isUnderSomeone = false; targetObject.isHit = false; targetObject.isOnSomething = false; // 重力を切ると上がるときに判定できない。 /*for(int i=1;i<5;i++) {// Vectorsのどれか一つでもslopeVectorの右に位置していれば重なっている。 //if(targetObject.drawPos + targetObject.width > myObject.drawPos && targetObject.drawPos > myObject.drawPos + myObject.width) if (myObject.position.X + myObject.width < targetObject.position.X) { }else if (targetObject.position.X + targetObject.width < myObject.position.X) { }else{// x方向で範囲内に入っている if(crossProduct[0,i] > 0) {// slopeVectorの右にあればめりこんでいるので負になる しかしy軸の関係で正? targetObject.isHit = true; myObject.isHit = true; targetObject.isOnSomething = true; myObject.isUnderSomeone = true; sideNum = i; CalculateCrossPoint3(targetObject, myObject); adjustObjectT1(targetObject, myObject); } } }*/ crossProduct[0, 0] = (myObject.slopeVector.X * vectors[0].Y) - (vectors[0].X * myObject.slopeVector.Y); // 先にマップチップの矩形の判定でおおまかに切る /*if (myObject.position.X + myObject.width < targetObject.position.X) { }else if (targetObject.position.X + targetObject.width < myObject.position.X) { }else if (targetObject.position.Y + targetObject.height < myObject.position.Y) { }else if (myObject.position.Y + myObject.height < targetObject.position.Y) { }else{ // 次に速度ベクトルと辺ベクトルとの交点でどの判定をするか決定 if(crossProduct[0,0] >= 0) {// slopeVectorの右にあればめりこんでいるので負になる しかしy軸の関係で正? targetObject.isHit = true; myObject.isHit = true; //sideNum = 0; targetObject.isOnSomething = true; targetObject.jumpCount = 0; targetObject.isJumping = false; myObject.isUnderSomeone = true; CalculateCrossPoints4(myObject, targetObject); //if(sideNum==0) adjustObject4(myObject, targetObject); } }*/ for (int i = 0; i < isCrossSide.Length; i++) isCrossSide[i] = false; // 10/25:当たり判定もどの辺に押し戻すかも両方交差判定に統一する //速度ベクトルと3本の辺ベクトルに対して3回交差判定を行う 外積を使った交差判定との計算量については厳密には比較していないが、 //大体同じくらいだろうと判断して既存の直線と方程式での交差判定を使う jをspeedVectorに。 //for(int i=0;i<=0;i++) { /*Result[0] = (myObject.slopeVectorUp.X - myObject.slopeVectorDown.X) * (prevVector.Y - myObject.slopeVectorDown.Y) - (myObject.slopeVectorUp.Y - myObject.slopeVectorDown.Y) * (prevVector.X - myObject.slopeVectorDown.X); Result[1] = (myObject.slopeVectorUp.X - myObject.slopeVectorDown.X) * (curVector.Y - myObject.slopeVectorDown.Y) - (myObject.slopeVectorUp.Y - myObject.slopeVectorDown.Y) * (curVector.X - myObject.slopeVectorDown.X); Result[2] = (curVector.X - prevVector.X) * (myObject.slopeVectorDown.Y - prevVector.Y) - (curVector.Y - prevVector.Y) * (myObject.slopeVectorDown.X - prevVector.X); Result[3] = (curVector.X - prevVector.X) * (myObject.slopeVectorUp.Y - prevVector.Y) - (curVector.Y - prevVector.Y) * (myObject.slopeVectorUp.X - prevVector.X);*/ Result[0] = (myObject.slopeVectorUp.X - myObject.slopeVectorDown.X) * (prevVector.Y - myObject.slopeVectorDown.Y) - (myObject.slopeVectorUp.Y - myObject.slopeVectorDown.Y) * (prevVector.X - myObject.slopeVectorDown.X); Result[1] = (myObject.slopeVectorUp.X - myObject.slopeVectorDown.X) * (curVector.Y - myObject.slopeVectorDown.Y) - (myObject.slopeVectorUp.Y - myObject.slopeVectorDown.Y) * (curVector.X - myObject.slopeVectorDown.X); Result[2] = (curVector.X - prevVector.X) * (myObject.slopeVectorDown.Y - prevVector.Y) - (curVector.Y - prevVector.Y) * (myObject.slopeVectorDown.X - prevVector.X); Result[3] = (curVector.X - prevVector.X) * (myObject.slopeVectorUp.Y - prevVector.Y) - (curVector.Y - prevVector.Y) * (myObject.slopeVectorUp.X - prevVector.X); // 1つの線分の組に対して値を計算し終わったら判定 CompareCross4(myObject, targetObject); if (targetObject.isHit) { //isCrossSide[i] = true; adjustObject4(myObject, targetObject); } //} }
private static void CheckDirection(Slope myObject, Object targetObject) { for (int i = 0; i <= 2; i++) { crossProducts2[i] = (myObject.sideVector[i].X * vectors[i].Y) - (vectors[i].X * myObject.sideVector[i].Y); if (crossProducts2[i] < 0) myObject.sideNum = i; } }