抛物线轨迹计算


不同输入情况下的抛物线有不同计算方式。为了保证飞行时间的一致,水平初速度和起点两个参数是任何情况下都需要的。


三、示例代码

void UParabolicMovementComponent::InitComputeParams()
{
//无目标时
	if (!bHasTarget)
	{
//		指定出射角度时计算方法
// 		FQuat quat = UpdatedComponent->GetComponentQuat() * FQuat(Rotation);
// 		DirHorz = quat.Rotator().Vector();
// 		float Theta = DirHorz.Z / DirHorz.Size2D();
// 		VerticalSpeed = HorzSpeed * tan(Theta);
// 		DirHorz.Z = 0;
		//指定最大高度时计算方法
DirHorz = UpdatedComponent->GetComponentRotation().Vector();
		DirHorz.Z = 0;
		DirHorz.Normalize();
//若无目标则默认G=980.0f
		VerticalSpeed = FMath::Sqrt(2 * Gravity * MaxHeight);
	}
//有目标时
	else
	{
		DirHorz = GetTargetPosition() - GetHostPosition();
		float HeightDist = DirHorz.Z;
		DirHorz.Z = 0;
		float Dist = DirHorz.Size();
		DirHorz.Normalize();
		TotalTime = Dist / HorzSpeed;
		VerticalSpeed = (2.0f * (MaxHeight + FMath::Sqrt(MaxHeight*MaxHeight - MaxHeight*HeightDist))) / TotalTime;
		Gravity = VerticalSpeed * VerticalSpeed / (2.0f * MaxHeight);
		//VerticalSpeed = HeightDist / TotalTime + .5f * Gravity * TotalTime;
	}
	CurrentTime = 0;
	StartPos = GetHostPosition();
	Velocity = DirHorz * HorzSpeed + FVector::UpVector * VerticalSpeed;
	UpdateComponentVelocity();
}

//计算当前时刻所在位置
void UParabolicMovementComponent::ComputeMovement(float DeltaTime, FVector& OutMoveDelta)
{
	CurrentTime += DeltaTime;
	if(bHasTarget)
	{
		if (CurrentTime >= TotalTime)
		{
			CurrentTime = TotalTime;
			bStop = true;
		}
	}
	
	float CurrentVertSpeed = VerticalSpeed - Gravity * CurrentTime;
	float fVertDist = .5f * (VerticalSpeed + CurrentVertSpeed) * CurrentTime;
	OutMoveDelta = StartPos + CurrentTime * HorzSpeed * DirHorz + fVertDist * FVector::UpVector - GetHostPosition();
	Velocity = DirHorz * HorzSpeed + FVector::UpVector * CurrentVertSpeed;
	//OutNewRotation = Velocity.Rotation().Quaternion();
}


导弹线轨迹计算

物体以某个初速度方向出发后,先保持稳定线性速度,以一定角速度向目标点旋转,当速度方向和自身-目标方向的夹角小于一定角度后,速度方向立刻改为自身-目标方向,进行直线加速。




示例代码

void UMissleMovementComponent::InitComputeParams()
{
	Dir = (UpdatedComponent->GetComponentQuat() * Rotation.Quaternion()).Rotator().Vector();
	Dir.Normalize();
	Velocity = Dir * StartSpeed;
	CurrentSpeed = StartSpeed;
	UpdateComponentVelocity();
}

void UMissleMovementComponent::ComputeMovement(float DeltaTime, FVector& OutMoveDelta)
{
	float MinDist = GetMinimalDistance();
	static const float fLimit = (float)cos(FMath::DegreesToRadians(LimitDegree));
	FVector vDir;
	vDir = GetTargetPosition() - GetHostPosition();
		
	float fLeft = vDir.Size();
	vDir.Normalize();
	float fDist = CurrentSpeed * DeltaTime; 	
	if (fDist >= fLeft)
	{
		fDist = fLeft;
		bStop = true;
	}

	float fAngle = Velocity.GetSafeNormal() | vDir;
	//如果小于最小距离;或者角度相近,使用直线
	if (fLeft < MinDist || fAngle > fLimit)
	{
		CurrentSpeed += LinearAcc * DeltaTime;
		OutMoveDelta = vDir * fDist;
		Velocity = vDir * CurrentSpeed;
	}
	else
	{
		OutMoveDelta = Velocity * DeltaTime;
		FVector vUp = Velocity ^ vDir;
		vUp.Normalize();
		FQuat q(vUp, RotationSpeed * DeltaTime);
		Velocity = q.RotateVector(Velocity);
	}
	//OutNewRotation = Velocity.ToOrientationQuat();
	//OutNewRotation = Velocity.Rotation().Quaternion();
}
float UMissleMovementComponent::GetMinimalDistance()
{
	float d = 2.0f * StartSpeed / RotationSpeed;
	return d;
}


posted on 2016-03-16 14:58  Corgi  阅读(2149)  评论(0编辑  收藏  举报