ページ 1 / 1
敵の移動計算
Posted: 2011年5月07日(土) 15:19
by dic
敵の移動を計算する式を考えています
点(0,200) (100,300) (200、50) (400,10)
各点を60フレーム間隔で横切る 速度v の計算式を考えています
今できても直線の移動しかできず、なめらかな曲線で移動させたいです
決められるのは点の座標と、点と点の間のフレーム数、各点の速度だけです
この条件だけで、敵の移動座標を求める方法って何か有名な式があるのでしょうか?
Re: 敵の移動計算
Posted: 2011年5月07日(土) 20:22
by MNS
http://marupeke296.com/DXG_No34_UnuniformSprine.html
このスプライン曲線というものを利用してみては?
ただ、各点を60フレームで横切るというのは、速度が一定じゃないので奇妙な動きに見えるかもしれませんよ
↓サンプル的なコード
コード:
class Ball
{
vec m_pos;
double t;
public:
Ball():t(0.0),m_pos(100,100){}
void update();
void render();
};
vec spline(vec p1, vec p2, vec v1, vec v2, double t)
{
vec pos;
double d1 = 2*t*t*t - 3*t*t + 1;
double d2 = -2*t*t*t + 3*t*t;
double d3 = t*t*t - 2*t*t + t;
double d4 = t*t*t - t*t;
pos = p1*d1+p2*d2+v1*d3+v2*d4;
return pos;
}
const int max = 4;
static vec targets[max] = {vec(0,299),vec(100,300),vec(200,50),vec(400,10)};
void Ball::update()
{
const double K = 100.0;//曲線具合
static vec p_v = getNormal(targets[1]-targets[0])*K; //以前の速度を記録
static int count = 0; //現在参照しているターゲット
t+=1.0/60.0; //60フレームで動く
int next = (count+1)%max; //次のターゲット
int nextnext = (count+2)%max; //次の次
vec v = getNormal(targets[nextnext]-targets[count])*K; //速度を決める
m_pos = spline(targets[count], targets[next], p_v, v, t); //位置を決める
}
Re: 敵の移動計算
Posted: 2011年5月08日(日) 11:47
by a5ua
時刻t = 0において、位置x = x0かつ速度v0、
時刻t = Tにおいて、位置x = x1かつ速度v1とし、
加速度を、A * t + Bと仮定して方程式を立ててみる。
d
2x/dt
2 = A * t + B
x'(0) = v0
x'(T) = v1
x(0) = x0
x(T) = x1
これより、A、Bを定めると、
A = (6 * (v1 + v0) * T - 12 * (x1 - x0)) / T
3
B = (6 * (x1 - x0) - 2 * (v1 + 2 * v0) * T) / T
2
時刻tにおける位置xはA、Bを使って、
x = (1/6) * A * t
3 + (1/2) * B * t
2 + v0 * t + x0
となるので、これを使って実装してみる。
うまく動いてそうだけど、滑らかかどうかは微妙かも。
以下、実装コード
► スポイラーを表示
コード:
class point
{
public:
point(double x, double y) : x(x), y(y){}
point &operator+=(const point &other)
{
x += other.x;
y += other.y;
return *this;
}
point &operator-=(const point &other)
{
x -= other.x;
y -= other.y;
return *this;
}
point &operator*=(double c)
{
x *= c;
y *= c;
return *this;
}
point &operator/=(double c)
{
x /= c;
y /= c;
return *this;
}
double x;
double y;
};
point operator+(const point &lhs, const point &rhs)
{
point result(lhs);
result += rhs;
return result;
}
point operator-(const point &lhs, const point &rhs)
{
point result(lhs);
result -= rhs;
return result;
}
point operator*(const point &lhs, double rhs)
{
point result(lhs);
result *= rhs;
return result;
}
point operator*(double lhs, const point &rhs)
{
return rhs * lhs;
}
point operator/(const point &lhs, double rhs)
{
point result(lhs);
result /= rhs;
return result;
}
コード:
// 加速度 a = A * t + B の係数を定める
point coefA(point x0, point x1, point v0, point v1, int n)
{
return (6 * (v1 + v0) * n - 12 * (x1 - x0)) / n / n / n;
}
point coefB(point x0, point x1, point v0, point v1, int n)
{
return (6 * (x1 - x0) - 2 * (v1 + 2 * v0) * n) / n / n;
}
#include <DxLib.h>
int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
ChangeWindowMode(TRUE);
if (DxLib_Init() != 0) {
return 0;
}
SetDrawScreen(DX_SCREEN_BACK);
const int TARGET_NUM = 4;
// 4つのチェックポイント
point t_pos[TARGET_NUM] = {point(0, 200), point(100, 300), point(200, 100), point(400, 10)};
// 各点における速度
point t_vel[TARGET_NUM] = {point(3, 6), point(3, -2), point(3, -1), point(5, 0)};
// 点と点の間のフレーム数
int interval[TARGET_NUM - 1] = {60, 60, 60};
int index = 0;
int count = 0;
while (ProcessMessage() == 0 && !CheckHitKey(KEY_INPUT_ESCAPE)) {
//ClearDrawScreen();
++count;
if (count == interval[index]) {
count = 0;
++index;
if (index == TARGET_NUM - 1) {
index = 0;
ClearDrawScreen();
}
}
// チェックポイントの描画
for (int i = 0; i < TARGET_NUM; ++i) {
DrawCircle((int)t_pos[i].x, (int)t_pos[i].y, 5, GetColor(255, 255, 0));
}
// 加速度と位置の計算
point A = coefA(t_pos[index], t_pos[index + 1], t_vel[index], t_vel[index + 1], interval[index]);
point B = coefB(t_pos[index], t_pos[index + 1], t_vel[index], t_vel[index + 1], interval[index]);
point P = t_pos[index] + t_vel[index] * count + 0.5 * B * count * count + 1 / 6.0 * A * count * count * count;
// 現在地の描画
DrawCircle((int)P.x, (int)P.y, 5, GetColor(255, 255, 255), FALSE);
ScreenFlip();
}
DxLib_End();
return 0;
}
Re: 敵の移動計算
Posted: 2011年5月08日(日) 15:30
by dic
>>a5uaさん
解説つきでありがとうございます
しかしながら私のツルツル脳みそでは理解できませんでした orz
>>MNSさん
スプライン曲線ははじめてききました
解説はなんとなくわかるのですが、これも私の脳みそがツルツルなためとりいれれません
効率といえばなかなかかっこよく聞こえますけど
自分のレベルにあった計算式を考えようと思います
私のレベルがそうとう低いということがわかっただけでもいいですので解決としておきます