Я не знаю, какая у вас система координат
- плоскость
- сфера
- эллипсоид типа WGS84
Полагаю, ваша земля плоская (вызвана вашими константами, однако ваши позиции предполагают что-то другое) ... поэтому я буду придерживаться этого пока ... У вас есть 2 проблемы:
Физика Ньютона / Даламбера
Вы странны, поскольку у вас нет умножения dt
, поэтому оно работает, только если ваше обновление составляет 1 Гц.взгляните на это:
вам не нужен ограничитель скорости в качестве воздушного трениясделаю это за вас, и вы должны ехать с ускорениями ... или силой, если вы хотите учесть и массовые изменения.
Однако, поскольку вы работаете с землей / землей, я предполагаю, что вместо ньютоновского полета будет атмосферный полет, так чтов этом случае вам нужно управлять курсом не ускорением, а поворотом интегрированной скорости.Основное подруливающее устройство должно по-прежнему рассматриваться как ускорение.
Столкновения не нужны в вашем случае (если ваша земля не плоская или на пути нет препятствий).
Система управления ракетой
Предлагаю использовать 3-х режимное (марковская модель) управление ракетой.
запуск
Сначала поднимите ракету на безопасную высоту, чтобы избежать препятствий, сэкономить топливо и максимизировать скорость
круиз
Поездка в целевой район (пока еще держу свою высоту).Просто вычислите курс, проецируемый на наземную плоскость, и примените коррекцию к курсу ракеты, чтобы он соответствовал ей (все еще идя параллельно земле).
попадание
попадание в цельво время спуска.Почти так же, как # 2 , но на этот раз вам тоже нужно изменить высоту ...
Кроме того, вы можете добавить стратегии, чтобы избежать обнаружения/ разрушение или препятствия и т. д. Вы также можете использовать поддельный подход из разных заголовков, чтобы скрыть позицию запуска ...
Вот простой пример C ++ такого подхода:
//---------------------------------------------------------------------------
void vector_one(double *c,double *a)
{
double l=sqrt((a[0]*a[0])+(a[1]*a[1])+(a[2]*a[2]));
if (l>1e-10) l=1.0/l; else l=0.0;
c[0]=a[0]*l;
c[1]=a[1]*l;
c[2]=a[2]*l;
}
//---------------------------------------------------------------------------
// Z=0 plane is ground, Z+ is up
const double g=9.81; // [m/s^2] Earth's gravity
const double acc0=20.0; // [m/s^2] rocket main thruster acceleration
const double kv2 =0.002; // [-] rocket air friction coeff (speed limiter)
const double alt0=50.0; // [m] rocket safe altitude
const double dis0=100.0; // [m] rocket safe distance to target
const double dis1= 10.0; // [m] rocket explosion distance to target
const double dang0=375.0*M_PI/180.0;// [rad/s] rocket turn speed per yaw/roll/pitch
// Rocket
double dst[3]={+90.0,-50.0,0.0}; // [m] target position
double pos[3]={-100.0,200.0,0.0}; // [m] rocket position
double vel[3]={ 0.0, 0.0,0.0}; // [m/s] rocket velocity
double acc[3]={ 0.0, 0.0,0.0}; // [m/s^2] rocket acceleration
enum{
_state_none=0,
_state_launch, // rise to alt0
_state_cruise, // get near target but maintain alt0
_state_hit, // descend and hit
};
int state=_state_launch;
void update(double dt) // update rocket after dt [sec] has passed
{
int i;
double v,a,hdg[3],tar[3];
// guiding system
if (state==_state_none)
{
for (i=0;i<3;i++) vel[i]=0.0;
for (i=0;i<3;i++) acc[i]=0.0;
return;
}
if (state==_state_launch)
{
// init heading to Up
for (i=0;i<3;i++) hdg[i]=0.0; hdg[2]=1.0;
if (pos[2]>=alt0) state=_state_cruise;
}
v=sqrt((vel[0]*vel[0])+(vel[1]*vel[1])+(vel[2]*vel[2]));// |vel|
if ((state==_state_cruise)||(state==_state_hit))
{
vector_one(hdg,vel); // heading
for (i=0;i<3;i++) tar[i]=dst[i]-pos[i]; // to target
a=sqrt((tar[0]*tar[0])+(tar[1]*tar[1])+(tar[2]*tar[2])); // distance to target
if (state==_state_cruise)
{
tar[2]=0; // no altitude change
if (a<=dis0) state=_state_hit;
}
else{
if (a<=dis1) state=_state_none; // here you shoul add exlosion code
}
vector_one(tar,tar);
// a = angle between hdg and tar [rad]
for (a=0.0,i=0;i<3;i++) a+=hdg[i]*tar[i];
a=fabs(acos(a));
// approximate turn up to dang0
if (a>1e-10) a=dt*dang0/a; else a=0.0;
for (i=0;i<3;i++) hdg[i]=hdg[i]+a*(tar[i]-hdg[i]);
vector_one(hdg,hdg); // new heading
for (i=0;i<3;i++) vel[i]=v*hdg[i]; // new vel
}
// physics
for (i=0;i<3;i++) acc[i] =-kv2*vel[i]*v; // air friction (k*|vel|^2)
for (i=0;i<3;i++) acc[i]+=hdg[i]*acc0; // rocket thrust
acc[2]-=g; // gravity
// Newton/D'Alembert simulation
for (i=0;i<3;i++) vel[i]+=acc[i]*dt;
for (i=0;i<3;i++) pos[i]+=vel[i]*dt;
}
//---------------------------------------------------------------------------
Возможно, вам придется немного подкорректировать константы в соответствии с вашими размерами и игровыми потребностями.Как вы можете видеть, вы можете настроить ракету довольно много, что идеально подходит для игры (технические улучшения).
Физика прямолинейна Ньютон / Даламбер (кроме поворота vel
из-за крыльев) инаправляющая система работает, как описано выше.В первом состоянии ракета просто поднимается до alt0
, затем она пытается повернуться к цели со скоростью dang0
, сохраняя высоту, и, когда она ближе, чем dis0
, она также начинает снижаться.Если ближе, чем dis1
, ракета должна взорваться ...
Вот предварительный просмотр (вид сверху):
Белая линиялиния от земли, чтобы проверить высоту ракеты ... Ракета синего цвета, а цель красного цвета.
Математика поворота такова:
, поэтому я просто масштабировал tar-hdg
, чтобы приблизительно соответствовать dang0*dt
и добавлял это к исходному hdg
.теперь новый курс поворачивается к цели на dang0*dt
, поэтому я просто нормализую его к размеру единицы и пересчитываю скорость в этом новом направлении (поскольку крылья поворачивают скорость вместо ускорения)
Осторожно
Все используемые устройства должны быть совместимы. Я использую SI .Ваша константа 9.81
предполагает то же самое, но ваши значения позиции и цели не имеют смысла, если в метрах ... Зачем стрелять ракетой, если цель находится всего в нескольких метрах?Также значения предполагают, что ваши координаты либо не декартовы, либо земля не плоская / плоская.Также значения предполагают целые числа, надеюсь, что вместо этого у вас есть числа с плавающей точкой / двойные числа