先ほど想定通りの挙動が得られたので少し詳細に書いて解決にしたいと思います。
大枠としてこのサイトを参考にしました(
http://monooki.ldblog.jp/archives/35959913.html)。
ですが、本ゲームには速度に加えて加速度もあったため、次のフレームの位置を予測するのに現在座標+速度+加速度を採用しました。これで自機のような壁にぶつかってからも力をかけ続けるような物体を壁で制止することが出来ました。
そして、前は「円を内接する正方形に近似する」と言いましたが、ゲーム性の観点から「円を外接する正方形に近似する」方針にしました。
次に反射ですが、速度ベクトルがもともと縦方向と横方向で保存されていたため、正方形の上または下の辺に当たったかと右または左の辺に当たったかとでそれぞれ対応する要素のみを反転させました。
最後に、ソースコードの該当する部分のみを貼っておきます。
コード:
void CMover::onWall(CVector WallPosition, CVector WallSize, double WallReflectionCF)
{
CVector nextPosition = Position + Velocity + Acceleration*Constant::perFrame;
double max = (Position.x + Size) - (WallPosition.x - WallSize.x / 2), may = (Position.y + Size) - (WallPosition.y - WallSize.y / 2);
double nax = (WallPosition.x + WallSize.x / 2) - (Position.x - Size), nay = (WallPosition.y + WallSize.y / 2) - (Position.y - Size);
double _max = (nextPosition.x + Size) - (WallPosition.x - WallSize.x / 2), _may = (nextPosition.y + Size) - (WallPosition.y - WallSize.y / 2);
double _nax = (WallPosition.x + WallSize.x / 2) - (nextPosition.x - Size), _nay = (WallPosition.y + WallSize.y / 2) - (nextPosition.y - Size);
bool U = false, D = false, R = false, L = false;
//カド同士の判定
if (0 >= max && 0 >= may && _max > 0 && _may > 0) {
if (_max >= _may) {
//下にある
D = true;
}
else {
//右にある
R = true;
}
}
if (0 >= nax && 0 >= may && _nax > 0 && _may > 0) {
if (_nax >= _may) {
//下にある
D = true;
}
else {
//左にある
L = true;
}
}
if (0 >= max && 0 >= nay && _max > 0 && _nay > 0) {
if (_max >= _nay) {
//上にある
U = true;
}
else {
//右にある
R = true;
}
}
if (0 >= nax && 0 >= nay && _nax > 0 && _nay > 0) {
if (_nax >= _nay) {
//上にある
U = true;
}
else {
//左にある
L = true;
}
}
//上下左右の判定
if (may > 0 && nay > 0) {
if (_nax > 0 && (Position.x - Size) > (WallPosition.x - WallSize.x / 2)) {
//左にある
L = true;
}
if (_max > 0 && (WallPosition.x + WallSize.x / 2) > (Position.x + Size)) {
//右にある
R = true;
}
}
if (max > 0 && nax > 0) {
if (_nay > 0 && (Position.y - Size) > (WallPosition.y - WallSize.y / 2)) {
//上にある
U = true;
}
if (_may > 0 && (WallPosition.y + WallSize.y / 2) > (Position.y + Size)) {
//下にある
D = true;
}
}
if (U) {
Position.y = WallPosition.y + WallSize.y / 2 + Size;
Velocity.y *= -ReflectCF * WallReflectionCF;
if(Acceleration.y < 0)Acceleration.y = 0;
}
if (D) {
Position.y = WallPosition.y - WallSize.y / 2 - Size;
Velocity.y *= -ReflectCF * WallReflectionCF;
if (Acceleration.y > 0)Acceleration.y = 0;
}
if (R) {
Position.x = WallPosition.x - WallSize.x / 2 - Size;
Velocity.x *= -ReflectCF * WallReflectionCF;
if (Acceleration.x > 0)Acceleration.x = 0;
}
if (L) {
Position.x = WallPosition.x + WallSize.x / 2 + Size;
Velocity.x *= -ReflectCF * WallReflectionCF;
if (Acceleration.x < 0)Acceleration.x = 0;
}
}
注:ReflectionCFは物体自身の反発係数、WallReflectionCFは壁の反発係数です。壁は重心をPositionとしています。物体のSizeは半径です。perFrameは1/60で加速度をフレームで割って分かりやすくしています(自分にとって)。
最後に、初歩的な質問で申し訳ないのですが、以前まであった「解決ボタン」は廃止されたのですか?
見つからなかったので、私の見落としでしたら教えてください。