Exemplo n.º 1
0
// Called every frame
void ACart::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );
	auto World = GetWorld();
	for (int32 i = 0; i < 4; i++)
	{
		FHitResult HitResult(ForceInit);
		FCollisionQueryParams Params = FCollisionQueryParams(FName(TEXT("Trace")), true, this);
		Params.bTraceComplex = true;
		//Params.bTraceAsyncScene = true;
		Params.bReturnPhysicalMaterial = true;

		const FName TraceTag("MyTraceTag");
		World->DebugDrawTraceTag = TraceTag;
		Params.TraceTag = TraceTag;

		

		bool Hit = World->LineTraceSingleByChannel(HitResult, Arrows[i]->GetComponentLocation(), Arrows[i]->GetComponentLocation() + Arrows[i]->GetForwardVector() * (SpringLength + WheelRadius), ECC_PhysicsBody, Params);
		if (Hit)
		{
			FVector Force = HitResult.ImpactNormal * SpringStrength * BodyMesh->GetMass() * (1 - HitResult.Distance / (SpringLength + WheelRadius));
			BodyMesh->AddForceAtLocation(Force, Arrows[i]->GetComponentLocation());
			Wheels[i]->SetWorldLocation(HitResult.Location - (Arrows[i]->GetForwardVector() * WheelRadius));
		}
		else
		{
			Wheels[i]->SetWorldLocation(Arrows[i]->GetComponentLocation() + Arrows[i]->GetForwardVector() * SpringLength);
		}
		
	}
}
Exemplo n.º 2
0
HitResult SphereObject::GetCollision( const Ray& ray ) const
{
    HitResult Res = HitResult( );
    
    // Calculate ray start's offset from the sphere center
    CPPEngine::Vector3 p = ray.Start - this->Center;

    float rSquared = this->Radius * this->Radius;
    float p_d = p.Dot( ray.Direction );

    // The sphere is behind the start point.
    if ( p_d < 0 )
        return Res;

    // The sphere contains the ray's start point.
    if( p.LengthSquared( ) < rSquared )
    {
        Res.Hit = true;
        Res.Position = ray.Start;

        return Res;
    }

    // Flatten p into the plane passing through c perpendicular to the ray.
    // This gives the closest approach of the ray to the center.
    CPPEngine::Vector3 a = p - ray.Direction * p_d;
    float aSquared = a.LengthSquared( );

    // Closest approach is outside the sphere.
    if ( aSquared > rSquared )
        return Res;

    // Calculate distance from plane where ray enters/exits the sphere.    
    float h = sqrt( rSquared - aSquared );

    // Calculate intersection point relative to sphere center.
    CPPEngine::Vector3 i = a - h * ray.Direction;

    CPPEngine::Vector3 intersection = this->Center + i;
    CPPEngine::Vector3 normal = i / this->Radius;
    // We've taken a shortcut here to avoid a second square root.
    // Note numerical errors can make the normal have length slightly different from 1.
    // If you need higher precision, you may need to perform a conventional normalization.

    Res.Position = intersection;
    Res.Normal = normal;
    Res.DistanceSquared = ( intersection - ray.Start ).LengthSquared( );
    Res.Object = this;
    Res.Hit = true;
    return Res;
}
Exemplo n.º 3
0
void ATraceWeapon::Attack()
{
	Super::Attack();
	

	FVector Start = GetActorLocation();

	FVector Direction = Instigator->GetActorRotation().Vector();
	FVector End = Start + Direction * Range;

	FHitResult Impact = WeaponTrace(Start, End);

	HitResult(Impact, Start, Direction);

	


}
Exemplo n.º 4
0
/**
*	Read actor method
*	Sets up structure, which contains information about a trace hit. Point of impact and surface normal at that point.
*	Runs the ray trace method, firing a ray out infront of the character upon keypress of "read".
*
*	@params N/A
*	@return N/A	
**/
void APlayerCharacter::Read()
{
	FHitResult HitResult(EForceInit::ForceInit);

	bool bSuccessTrace = TraceFromSelf(HitResult, 150.0f, ECollisionChannel::ECC_EngineTraceChannel1); // Fire ray trace.
	if (bSuccessTrace)
	{
		AActor* const HitActor = HitResult.GetActor(); 
		if (HitActor)
		{ 
			ASign* SignActor = Cast<class ASign>(HitActor); // Get actor collided with.
			if (SignActor)
			{
				FString const SignMessage = SignActor->GetMessage();  // Take message from Sig
				GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Yellow, SignMessage);	// Display as debug message.
			}
		}
	}
}
Exemplo n.º 5
0
//////////////////////////////////////////////////////////////////////////
// lineCast
BcBool ScnPhysicsWorldComponent::lineCast( const MaVec3d& A, const MaVec3d& B, MaVec3d& Intersection, MaVec3d& Normal )
{
	btCollisionWorld::ClosestRayResultCallback HitResult( 
		btVector3( A.x(), A.y(), A.z() ),
		btVector3( B.x(), B.y(), B.z() ) );
	DynamicsWorld_->rayTest( 
		btVector3( A.x(), A.y(), A.z() ),
		btVector3( B.x(), B.y(), B.z() ),
		HitResult );

	if( HitResult.hasHit() )
	{
		Intersection = MaVec3d( 
			HitResult.m_hitPointWorld.x(),
			HitResult.m_hitPointWorld.y(),
			HitResult.m_hitPointWorld.z() );
		Normal = MaVec3d( 
			HitResult.m_hitNormalWorld.x(),
			HitResult.m_hitNormalWorld.y(),
			HitResult.m_hitNormalWorld.z() );
		return BcTrue;
	}
	return BcFalse;
}
Exemplo n.º 6
0
void UFlareAsteroidComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
	float CollisionSize = GetCollisionShape().GetExtent().Size();
	EffectsUpdateTimer += DeltaTime;

	// Get player ship
	AFlareGame* Game = Cast<AFlareGame>(GetWorld()->GetAuthGameMode());
	FCHECK(Game);
	AFlarePlayerController* PC = Game->GetPC();
	FCHECK(PC);
	AFlareSpacecraft* ShipPawn = PC->GetShipPawn();

	// Update if close to player and visible
	if (ShipPawn
	 && (ShipPawn->GetActorLocation() - GetComponentLocation()).Size() < 500000
	 && (GetWorld()->TimeSeconds - LastRenderTime) < 0.5)
	{
		if (EffectsUpdateTimer > EffectsUpdatePeriod)
		{
			// World data
			FVector AsteroidLocation = GetComponentLocation();
			FVector SunDirection = Game->GetPlanetarium()->GetSunDirection();
			SunDirection.Normalize();
	
			// Compute new FX locations
			for (int32 Index = 0; Index < Effects.Num(); Index++)
			{
				FVector RandomDirection = FVector::CrossProduct(SunDirection, EffectsKernels[Index]);
				RandomDirection.Normalize();
				FVector StartPoint = AsteroidLocation + RandomDirection * CollisionSize;

				// Trace params
				FHitResult HitResult(ForceInit);
				FCollisionQueryParams TraceParams(FName(TEXT("Asteroid Trace")), false, NULL);
				TraceParams.bTraceComplex = true;
				TraceParams.bReturnPhysicalMaterial = false;
				ECollisionChannel CollisionChannel = ECollisionChannel::ECC_WorldDynamic;

				// Trace
				bool FoundHit = GetWorld()->LineTraceSingleByChannel(HitResult, StartPoint, AsteroidLocation, CollisionChannel, TraceParams);
				if (FoundHit && HitResult.Component == this && Effects[Index])
				{
					FVector EffectLocation = HitResult.Location;

					if (!Effects[Index]->IsActive())
					{
						Effects[Index]->Activate();
					}
					Effects[Index]->SetWorldLocation(EffectLocation);
					Effects[Index]->SetWorldRotation(SunDirection.Rotation());
				}
				else
				{
					Effects[Index]->Deactivate();
				}
			}

			EffectsUpdateTimer = 0;
		}
	}

	// Disable all
	else
	{
		for (int32 Index = 0; Index < Effects.Num(); Index++)
		{
			Effects[Index]->Deactivate();
		}
	}
}
void UFlareSpacecraftDamageSystem::OnCollision(class AActor* Other, FVector HitLocation, FVector NormalImpulse)
{
	// If receive hit from over actor, like a ship we must apply collision damages.
	// The applied damage energy is 0.2% of the kinetic energy of the other actor. The kinetic
	// energy is calculated from the relative speed between the 2 actors, and only with the relative
	// speed projected in the axis of the collision normal: if 2 very fast ship only slightly touch,
	// only few energy will be decipated by the impact.
	//
	// The damages are applied only to the current actor, the ReceiveHit method of the other actor
	// will also call an it will apply its collision damages itself.

	// If the other actor is a projectile, specific weapon damage code is done in the projectile hit
	// handler: in this case we ignore the collision
	AFlareShell* OtherProjectile = Cast<AFlareShell>(Other);
	if (OtherProjectile)
	{
		return;
	}

	// No primitive component, ignore
	UPrimitiveComponent* OtherRoot = Cast<UPrimitiveComponent>(Other->GetRootComponent());
	if (!OtherRoot)
	{
		return;
	}

	// Ignore debris
	AStaticMeshActor* OtherActor = Cast<AStaticMeshActor>(Other);
	if (OtherActor)
	{
		if (OtherActor->GetName().StartsWith("Debris"))
		{
			return;
		}
	}

	// Relative velocity
	FVector DeltaVelocity = ((OtherRoot->GetPhysicsLinearVelocity() - Spacecraft->Airframe->GetPhysicsLinearVelocity()) / 100);

	// Compute the relative velocity in the impact axis then compute kinetic energy
	/*float ImpactSpeed = DeltaVelocity.Size();
	float ImpactMass = FMath::Min(Spacecraft->GetSpacecraftMass(), OtherRoot->GetMass());
	*/

	//200 m /s -> 6301.873047 * 20000 -> 300 / 2 damage

	float ImpactSpeed = 0;
	float ImpactEnergy = 0;
	float ImpactMass = Spacecraft->GetSpacecraftMass();

	// Check if the mass was set and is valid
	if (ImpactMass > KINDA_SMALL_NUMBER)
	{
		ImpactSpeed = NormalImpulse.Size() / (ImpactMass * 100.f);
		ImpactEnergy = ImpactMass * ImpactSpeed / 8402.f;
	}

	float  Radius = 0.2 + FMath::Sqrt(ImpactEnergy) * 0.11;
	//FLOGV("OnCollision %s", *Spacecraft->GetImmatriculation().ToString());
	//FLOGV("  OtherRoot->GetPhysicsLinearVelocity()=%s", *OtherRoot->GetPhysicsLinearVelocity().ToString());
	//FLOGV("  OtherRoot->GetPhysicsLinearVelocity().Size()=%f", OtherRoot->GetPhysicsLinearVelocity().Size());
	//FLOGV("  Spacecraft->Airframe->GetPhysicsLinearVelocity()=%s", *Spacecraft->Airframe->GetPhysicsLinearVelocity().ToString());
	//FLOGV("  Spacecraft->Airframe->GetPhysicsLinearVelocity().Size()=%f", Spacecraft->Airframe->GetPhysicsLinearVelocity().Size());
	//FLOGV("  dot=%f", FVector::DotProduct(DeltaVelocity.GetUnsafeNormal(), HitNormal.GetUnsafeNormal()));
	/*FLOGV("  DeltaVelocity=%s", *DeltaVelocity.ToString());
	FLOGV("  ImpactSpeed=%f", ImpactSpeed);
	FLOGV("  ImpactMass=%f", ImpactMass);
	FLOGV("  ImpactEnergy=%f", ImpactEnergy);
	FLOGV("  Radius=%f", Radius);*/



	bool HasHit = false;
	FHitResult BestHitResult;
	float BestHitDistance = 0;

	for (int32 ComponentIndex = 0; ComponentIndex < Components.Num(); ComponentIndex++)
	{
		UFlareSpacecraftComponent* Component = Cast<UFlareSpacecraftComponent>(Components[ComponentIndex]);
		if (Component)
		{
			FHitResult HitResult(ForceInit);
			FCollisionQueryParams TraceParams(FName(TEXT("Fragment Trace")), true);
			TraceParams.bTraceComplex = true;
			TraceParams.bReturnPhysicalMaterial = false;
			Component->LineTraceComponent(HitResult, HitLocation, HitLocation + Spacecraft->GetLinearVelocity().GetUnsafeNormal() * 10000, TraceParams);

			if (HitResult.Actor.IsValid()){
				float HitDistance = (HitResult.Location - HitLocation).Size();
				if (!HasHit || HitDistance < BestHitDistance)
				{
					BestHitDistance = HitDistance;
					BestHitResult = HitResult;
				}

				//FLOGV("Collide hit %s at a distance=%f", *Component->GetReadableName(), HitDistance);
				HasHit = true;
			}
		}

	}

	if (HasHit)
	{
		//DrawDebugLine(Spacecraft->GetWorld(), HitLocation, BestHitResult.Location, FColor::Magenta, true);
	}
	else
	{
		int32 BestComponentIndex = -1;
		BestHitDistance = 0;

		for (int32 ComponentIndex = 0; ComponentIndex < Components.Num(); ComponentIndex++)
		{
			UFlareSpacecraftComponent* Component = Cast<UFlareSpacecraftComponent>(Components[ComponentIndex]);
			if (Component)
			{
				float ComponentDistance = (Component->GetComponentLocation() - HitLocation).Size();
				if (BestComponentIndex == -1 || BestHitDistance > ComponentDistance)
				{
					BestComponentIndex = ComponentIndex;
					BestHitDistance = ComponentDistance;
				}
			}
		}
		UFlareSpacecraftComponent* Component = Cast<UFlareSpacecraftComponent>(Components[BestComponentIndex]);


		FCollisionQueryParams TraceParams(FName(TEXT("Fragment Trace")), true);
		TraceParams.bTraceComplex = true;
		TraceParams.bReturnPhysicalMaterial = false;
		Component->LineTraceComponent(BestHitResult, HitLocation, Component->GetComponentLocation(), TraceParams);
		//DrawDebugLine(Spacecraft->GetWorld(), HitLocation, BestHitResult.Location, FColor::Yellow, true);


	}

	AFlareSpacecraft* OtherSpacecraft = Cast<AFlareSpacecraft>(Other);
	UFlareCompany* DamageSource = NULL;
	if (OtherSpacecraft)
	{
		DamageSource = OtherSpacecraft->GetParent()->GetCompany();
		LastDamageCauser = OtherSpacecraft;
	}
	else
	{
		LastDamageCauser = NULL;
	}
	ApplyDamage(ImpactEnergy, Radius, BestHitResult.Location, EFlareDamage::DAM_Collision, DamageSource);
}