float AMurphysLawCharacter::TakeDamage(float DamageAmount, struct FDamageEvent const & DamageEvent, class AController * EventInstigator, AActor * DamageCauser) { float ActualDamage = 0.f; if (CurrentHealth > 0.f) { if (Role == ROLE_Authority) { ActualDamage = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser); // If the player actually took damage if (ActualDamage > 0.f) { // If the character has a HUD, we show the damages on it auto MyController = Cast<AMurphysLawPlayerController>(GetController()); if (MyController != nullptr) { // We start by getting best info on the hit FVector ImpulseDirection; FHitResult Hit; DamageEvent.GetBestHitInfo(this, DamageCauser, Hit, ImpulseDirection); // We calculate the vector from the character to the damage causer FVector2D HitVector = FVector2D(FRotationMatrix(GetControlRotation()).InverseTransformVector(-ImpulseDirection)); HitVector.Normalize(); // We compute the vector representing the ForwardVector FVector2D StraightVector = FVector2D(1.f, 0.f); StraightVector.Normalize(); // Finally, we calculate the angle where the hit came from float Angle = UKismetMathLibrary::DegAcos(FVector2D::DotProduct(StraightVector, HitVector)); // The angle ranges from -180.f to 180.f Angle = HitVector.Y < 0.f ? -Angle : Angle; // Dispatch to the controller MyController->ShowDamage(Angle); } } } else { // Let the server do it Server_TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser); } } return ActualDamage; }
void UReporterBase::DrawLine(UCanvas* Canvas,const FVector2D& StartPos,const FVector2D& EndPos,const FLinearColor& Color, EReporterLineStyle::Type LineStyle) { FCanvasLineItem LineItem; LineItem.SetColor( Color ); switch(LineStyle) { case EReporterLineStyle::Line: { LineItem.Draw( Canvas->Canvas, ToScreenSpace(StartPos, Canvas), ToScreenSpace(EndPos, Canvas) ); } break; case EReporterLineStyle::Dash: { float NormalizedDashSize = DASH_LINE_SIZE / Canvas->SizeX; FVector2D Dir = EndPos - StartPos; float LineLength = Dir.Size(); Dir.Normalize(); FVector2D CurrentLinePos = StartPos; while(FVector2D::DotProduct(EndPos - CurrentLinePos, Dir) > 0) { LineItem.Draw( Canvas->Canvas, ToScreenSpace(CurrentLinePos, Canvas), ToScreenSpace(CurrentLinePos + Dir * NormalizedDashSize, Canvas) ); CurrentLinePos += Dir * NormalizedDashSize * 2.0f; } } break; } }
float FEyeXUtils::CalculateRotationAngle(const FVector2D& Left, const FVector2D& Right) { static const FVector2D Y = FVector2D(0.0f, 1.0f); FVector2D LeftToRight = Right - Left; LeftToRight.Normalize(); const float Radians = FMath::Acos(LeftToRight | Y); return FMath::RadiansToDegrees(Radians) - 90.0f; }
float ADynamicCarController::getAcceleration(float deltaSec) const { float a = aMax * deltaSec; float velocityLength = getBrakeDistance(); float distLeftLength = (target - to2D(agent->GetActorLocation())).Size() - safetyBuffer; if (velocityLength >= distLeftLength) { // Check if we should start breaking FVector2D normVelocity = to2D(velocity); normVelocity.Normalize(); FVector2D normDistLeft = target - to2D(agent->GetActorLocation()); normDistLeft.Normalize(); if (normVelocity.Equals(normDistLeft, 0.1)) { return -a; } } return a; }
void UPaperTerrainComponent::SpawnSegments(const TArray<FTerrainSegment>& TerrainSegments, bool bGenerateSegmentColliders) { #ifdef USE_SIMPLIFIED_POLYGON_COLLIDERS_FOR_SEGMENTS TArray<FVector2D> CollisionPolygonPoints; #endif // The tangent from the first box added in this segment FVector2D StartTangent; for (const FTerrainSegment& Segment : TerrainSegments) { for (const FTerrainSpriteStamp& Stamp : Segment.Stamps) { const class UPaperSprite* NewSprite = Stamp.Sprite; float Position = Stamp.Time; float HorizontalScale = Stamp.Scale; float NominalWidth = Stamp.NominalWidth; const struct FPaperTerrainMaterialRule* Rule = Segment.Rule; if (bGenerateSegmentColliders && (Rule->bEnableCollision) && (CachedBodySetup != nullptr)) { const FTransform LocalTransformAtCenter(GetTransformAtDistance(Position)); #ifdef USE_SIMPLIFIED_POLYGON_COLLIDERS_FOR_SEGMENTS // Check note be low Re: bClosedSplines FVector2D BoxExtents( 0.5f * NominalWidth * HorizontalScale, 0.5f * FMath::Max<float>(1.0f, FMath::Abs<float>(Rule->CollisionOffset * 0.5f)) ); FVector BoxPoints[4]; BoxPoints[0] = LocalTransformAtCenter.TransformPosition(FVector(BoxExtents.X, 0, BoxExtents.Y)); BoxPoints[1] = LocalTransformAtCenter.TransformPosition(FVector(-BoxExtents.X, 0, BoxExtents.Y)); BoxPoints[2] = LocalTransformAtCenter.TransformPosition(FVector(-BoxExtents.X, 0, -BoxExtents.Y)); BoxPoints[3] = LocalTransformAtCenter.TransformPosition(FVector(BoxExtents.X, 0, -BoxExtents.Y)); FVector2D BoxPoints2D[4]; BoxPoints2D[0].Set(BoxPoints[0].X, BoxPoints[0].Z); BoxPoints2D[1].Set(BoxPoints[1].X, BoxPoints[1].Z); BoxPoints2D[2].Set(BoxPoints[2].X, BoxPoints[2].Z); BoxPoints2D[3].Set(BoxPoints[3].X, BoxPoints[3].Z); // If there is a previous polygon, try to merge if (CollisionPolygonPoints.Num() >= 4) { int InsertPoint = CollisionPolygonPoints.Num() / 2 - 1; float LengthV0 = FVector2D::Distance(CollisionPolygonPoints[InsertPoint], BoxPoints2D[0]); float LengthV1 = FVector2D::Distance(CollisionPolygonPoints[InsertPoint + 1], BoxPoints2D[3]); FVector2D CurrentSegmentTangent = BoxPoints2D[1] - BoxPoints2D[0]; CurrentSegmentTangent.Normalize(); bool bNewSegmentStraightEnough = FVector2D::DotProduct(CurrentSegmentTangent, StartTangent) > FMath::Acos(45.0f); // TODO: Arbitray number needs to come from somewhere... float MergeThreshold = 10; bool bMergeIntoPolygon = LengthV0 < MergeThreshold && LengthV1 < MergeThreshold; if (bNewSegmentStraightEnough && bMergeIntoPolygon) { CollisionPolygonPoints.Insert(BoxPoints2D[2], InsertPoint + 1); CollisionPolygonPoints.Insert(BoxPoints2D[1], InsertPoint + 1); } else { InsertConvexCollisionDataFromPolygon(CollisionPolygonPoints); CollisionPolygonPoints.Empty(0); CollisionPolygonPoints.Add(BoxPoints2D[0]); CollisionPolygonPoints.Add(BoxPoints2D[1]); CollisionPolygonPoints.Add(BoxPoints2D[2]); CollisionPolygonPoints.Add(BoxPoints2D[3]); StartTangent = BoxPoints2D[1] - BoxPoints2D[0]; StartTangent.Normalize(); } } else { CollisionPolygonPoints.Add(BoxPoints2D[0]); CollisionPolygonPoints.Add(BoxPoints2D[1]); CollisionPolygonPoints.Add(BoxPoints2D[2]); CollisionPolygonPoints.Add(BoxPoints2D[3]); StartTangent = BoxPoints2D[1] - BoxPoints2D[0]; StartTangent.Normalize(); } #else FKBoxElem Box; // The spline is never "closed" properly right now //if (bClosedSpline) //{ // //@TODO: Add proper support for this! // Box.SetTransform(LocalTransformAtCenter); // Box.X = NominalWidth * HorizontalScale; // Box.Y = CollisionThickness; // Box.Z = 30.0f; //} //else { Box.SetTransform(LocalTransformAtCenter); Box.X = NominalWidth * HorizontalScale; Box.Y = CollisionThickness; Box.Z = FMath::Max<float>(1.0f, FMath::Abs<float>(Rule->CollisionOffset * 0.5f)); } CachedBodySetup->AggGeom.BoxElems.Add(Box); #endif } if (NewSprite) { FPaperTerrainSpriteGeometry& MaterialBatch = *new (GeneratedSpriteGeometry) FPaperTerrainSpriteGeometry(); //@TODO: Look up the existing one instead MaterialBatch.Material = NewSprite->GetDefaultMaterial(); MaterialBatch.DrawOrder = Rule->DrawOrder; FSpriteDrawCallRecord& Record = *new (MaterialBatch.Records) FSpriteDrawCallRecord(); Record.BuildFromSprite(NewSprite); Record.Color = TerrainColor.ToFColor(/*bSRGB=*/ false); // Work out if the sprite is likely to be bent > X deg (folded over itself) const FVector ForwardVector(1, 0, 0); const FTransform LocalTransformAtBack(GetTransformAtDistance(Position - 0.5f * NominalWidth * HorizontalScale)); FVector StartForwardVector = LocalTransformAtBack.TransformVector(ForwardVector).GetSafeNormal(); const FTransform LocalTransformAtFront(GetTransformAtDistance(Position + 0.5f * NominalWidth * HorizontalScale)); FVector EndForwardVector = LocalTransformAtFront.TransformVector(ForwardVector).GetSafeNormal(); bool bIsSpriteBent = FVector::DotProduct(StartForwardVector, EndForwardVector) < 0.0f;// 0.7071f; // (45deg looks worse) for (FVector4& XYUV : Record.RenderVerts) { FTransform LocalTransformAtX(GetTransformAtDistance(Position + (XYUV.X * HorizontalScale))); // When the quad is overly bent, inherit rotation from the start of the quad to unfold it if (bIsSpriteBent) { LocalTransformAtX.SetRotation(LocalTransformAtFront.GetRotation()); } const FVector SourceVector = (XYUV.Y * PaperAxisY); const FVector NewVector = LocalTransformAtX.TransformPosition(SourceVector); const float NewX = FVector::DotProduct(NewVector, PaperAxisX); const float NewY = FVector::DotProduct(NewVector, PaperAxisY); XYUV.X = NewX; XYUV.Y = NewY; } } } } //@TODO: Sort by draw order first, materials next - Merge batches with the same material GeneratedSpriteGeometry.Sort([](const FPaperTerrainSpriteGeometry& A, const FPaperTerrainSpriteGeometry& B) { return B.DrawOrder > A.DrawOrder; }); #ifdef USE_SIMPLIFIED_POLYGON_COLLIDERS_FOR_SEGMENTS // For whatever is remaining if (CollisionPolygonPoints.Num() > 0) { InsertConvexCollisionDataFromPolygon(CollisionPolygonPoints); } #endif }