diff --git a/Content/Blueprints/BP_SpaceshipPawn.uasset b/Content/Blueprints/BP_SpaceshipPawn.uasset index 35baa83..12430fa 100644 --- a/Content/Blueprints/BP_SpaceshipPawn.uasset +++ b/Content/Blueprints/BP_SpaceshipPawn.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6e62fcec27bc08d7fe4b98fc7ff15dd02f3b3564831c0e8311f424ecacad8e4 -size 33771 +oid sha256:5ca3a33d366307792424f85a42db06b3ef2dbc8374e5c2ce30de5924a0e22bcb +size 33596 diff --git a/Content/Blueprints/BP_SpaceshipProjectile.uasset b/Content/Blueprints/BP_SpaceshipProjectile.uasset index fa4f0f4..d61b993 100644 --- a/Content/Blueprints/BP_SpaceshipProjectile.uasset +++ b/Content/Blueprints/BP_SpaceshipProjectile.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ddc8b567ebcb8d509a3b067ece867985461758f4eebe51b7f242f19e2849711 -size 32752 +oid sha256:146740f223702b9d66a193b0df6d2be391dbc8d6221b4f301fe73659602c265b +size 31436 diff --git a/Source/MyProject3/SpaceShooterGameMode.h b/Source/MyProject3/SpaceShooterGameMode.h index 96c7bcf..f4c55a9 100644 --- a/Source/MyProject3/SpaceShooterGameMode.h +++ b/Source/MyProject3/SpaceShooterGameMode.h @@ -48,6 +48,7 @@ public: void RestartGame(); int32 GetKillCount() const { return KillCount; } float GetRemainingTime() const { return RemainingTime; } + float GetGameDuration() const { return GameDuration; } bool IsGameOver() const { return bIsGameOver; } protected: diff --git a/Source/MyProject3/SpaceShooterHUD.cpp b/Source/MyProject3/SpaceShooterHUD.cpp index 0b3e67f..5f0c83c 100644 --- a/Source/MyProject3/SpaceShooterHUD.cpp +++ b/Source/MyProject3/SpaceShooterHUD.cpp @@ -10,6 +10,7 @@ ASpaceShooterHUD::ASpaceShooterHUD() // Find and set the default font static ConstructorHelpers::FObjectFinder FontObj(TEXT("/Engine/EngineFonts/RobotoDistanceField")); TextFont = FontObj.Object; + GameOverStartTime = 0.0f; } ASpaceshipPawn* ASpaceShooterHUD::GetPlayerPawn() const @@ -112,39 +113,113 @@ void ASpaceShooterHUD::DrawGameplayHUD() DrawStatusBars(); } +void ASpaceShooterHUD::DrawGameOverBackground() +{ + if (!Canvas) return; + + // Draw a semi-transparent black background + FCanvasBoxItem BoxItem(FVector2D(0, 0), FVector2D(Canvas->SizeX, Canvas->SizeY)); + BoxItem.SetColor(FLinearColor(0.0f, 0.0f, 0.0f, 0.7f)); + Canvas->DrawItem(BoxItem); +} + +void ASpaceShooterHUD::DrawGameOverText(const FString& Text, const FVector2D& Position, const FLinearColor& Color, float Scale) +{ + if (!Canvas || !TextFont) return; + + float TextWidth, TextHeight; + GetTextSize(Text, TextWidth, TextHeight, TextFont, Scale); + + // Draw text shadow + DrawText(Text, FLinearColor(0.0f, 0.0f, 0.0f, Color.A * 0.5f), + Position.X + 3.0f, Position.Y + 3.0f, TextFont, Scale); + + // Draw main text + DrawText(Text, Color, Position.X, Position.Y, TextFont, Scale); +} + void ASpaceShooterHUD::DrawGameOverScreen() { ASpaceShooterGameMode* GameMode = GetGameMode(); - if (!GameMode) return; + if (!GameMode || !Canvas) return; + + // Initialize GameOverStartTime if needed + if (GameOverStartTime == 0.0f) + { + GameOverStartTime = GetWorld()->GetTimeSeconds(); + } + + // Draw darkened background + DrawGameOverBackground(); - // Get canvas dimensions const FVector2D ViewportSize(Canvas->SizeX, Canvas->SizeY); + const float CurrentTime = GetWorld()->GetTimeSeconds(); + const float TimeSinceGameOver = CurrentTime - GameOverStartTime; + + // Calculate pulsating alpha for "GAME OVER" text + float PulsatingAlpha = FMath::Lerp(PulsateMinAlpha, PulsateMaxAlpha, + (FMath::Sin(TimeSinceGameOver * PulsateSpeed) + 1.0f) * 0.5f); + + // Calculate vertical positions + float CenterY = ViewportSize.Y * 0.4f; // Slightly above center + float Spacing = 60.0f * GameOverScale; + + // Draw "GAME OVER" with pulsating effect + FLinearColor PulsatingColor = GameOverTextColor; + PulsatingColor.A = PulsatingAlpha; - // Draw game over text FString GameOverText = TEXT("GAME OVER"); float TextWidth, TextHeight; - GetTextSize(GameOverText, TextWidth, TextHeight, TextFont); + GetTextSize(GameOverText, TextWidth, TextHeight, TextFont, GameOverScale); - DrawText(GameOverText, FLinearColor::Red, - ViewportSize.X / 2 - TextWidth / 2, - ViewportSize.Y / 2 - TextHeight / 2, - TextFont, 2.0f); + DrawGameOverText(GameOverText, + FVector2D((ViewportSize.X - TextWidth) * 0.5f, CenterY), + PulsatingColor, + GameOverScale); - // Draw final score - FString ScoreText = FString::Printf(TEXT("Final Kill Count: %d"), GameMode->GetKillCount()); - GetTextSize(ScoreText, TextWidth, TextHeight, TextFont); - DrawText(ScoreText, FLinearColor::White, - ViewportSize.X / 2 - TextWidth / 2, - ViewportSize.Y / 2 + TextHeight * 2, - TextFont); + // Draw stats with scaling animations + const float StatsScale = 1.5f; + float StatsY = CenterY + Spacing; - // Draw restart instructions + // Time Survived + int32 TotalSeconds = FMath::RoundToInt(GameMode->GetGameDuration() - GameMode->GetRemainingTime()); + int32 Minutes = TotalSeconds / 60; + int32 Seconds = TotalSeconds % 60; + FString TimeText = FString::Printf(TEXT("Time Survived: %02d:%02d"), Minutes, Seconds); + GetTextSize(TimeText, TextWidth, TextHeight, TextFont, StatsScale); + DrawGameOverText(TimeText, + FVector2D((ViewportSize.X - TextWidth) * 0.5f, StatsY), + StatsTextColor, + StatsScale); + + // Kill Count + StatsY += Spacing * 0.7f; + FString KillText = FString::Printf(TEXT("Enemies Destroyed: %d"), GameMode->GetKillCount()); + GetTextSize(KillText, TextWidth, TextHeight, TextFont, StatsScale); + DrawGameOverText(KillText, + FVector2D((ViewportSize.X - TextWidth) * 0.5f, StatsY), + StatsTextColor, + StatsScale); + + // Calculate final score based on time and kills + int32 FinalScore = GameMode->GetKillCount() * 100 + TotalSeconds * 10; + StatsY += Spacing * 0.7f; + FString ScoreText = FString::Printf(TEXT("Final Score: %d"), FinalScore); + GetTextSize(ScoreText, TextWidth, TextHeight, TextFont, StatsScale); + DrawGameOverText(ScoreText, + FVector2D((ViewportSize.X - TextWidth) * 0.5f, StatsY), + StatsTextColor, + StatsScale); + + // Draw restart text with bounce effect + float BounceOffset = FMath::Sin(TimeSinceGameOver * 3.0f) * 5.0f; + StatsY += Spacing * 1.2f; FString RestartText = TEXT("Press R to Restart"); - GetTextSize(RestartText, TextWidth, TextHeight, TextFont); - DrawText(RestartText, FLinearColor::Yellow, - ViewportSize.X / 2 - TextWidth / 2, - ViewportSize.Y / 2 + TextHeight * 4, - TextFont); + GetTextSize(RestartText, TextWidth, TextHeight, TextFont, StatsScale); + DrawGameOverText(RestartText, + FVector2D((ViewportSize.X - TextWidth) * 0.5f, StatsY + BounceOffset), + RestartTextColor, + StatsScale); } ASpaceShooterGameMode* ASpaceShooterHUD::GetGameMode() const diff --git a/Source/MyProject3/SpaceShooterHUD.h b/Source/MyProject3/SpaceShooterHUD.h index abf7b24..34f1fa7 100644 --- a/Source/MyProject3/SpaceShooterHUD.h +++ b/Source/MyProject3/SpaceShooterHUD.h @@ -36,10 +36,36 @@ protected: UPROPERTY(EditAnywhere, Category = "HUD|Bars") FLinearColor BackgroundBarColor = FLinearColor(0.0f, 0.0f, 0.0f, 0.5f); // Semi-transparent black + // Game Over Screen Configuration + UPROPERTY(EditAnywhere, Category = "HUD|GameOver") + float GameOverScale = 3.0f; + + UPROPERTY(EditAnywhere, Category = "HUD|GameOver") + FLinearColor GameOverTextColor = FLinearColor(1.0f, 0.2f, 0.2f, 1.0f); // Bright red + + UPROPERTY(EditAnywhere, Category = "HUD|GameOver") + FLinearColor StatsTextColor = FLinearColor(0.9f, 0.9f, 0.9f, 1.0f); // Off-white + + UPROPERTY(EditAnywhere, Category = "HUD|GameOver") + FLinearColor RestartTextColor = FLinearColor(1.0f, 0.843f, 0.0f, 1.0f); // Gold + + UPROPERTY(EditAnywhere, Category = "HUD|GameOver") + float PulsateSpeed = 2.0f; + + UPROPERTY(EditAnywhere, Category = "HUD|GameOver") + float PulsateMinAlpha = 0.7f; + + UPROPERTY(EditAnywhere, Category = "HUD|GameOver") + float PulsateMaxAlpha = 1.0f; + private: void DrawGameplayHUD(); void DrawGameOverScreen(); void DrawStatusBars(); class ASpaceShooterGameMode* GetGameMode() const; class ASpaceshipPawn* GetPlayerPawn() const; + + float GameOverStartTime; + void DrawGameOverBackground(); + void DrawGameOverText(const FString& Text, const FVector2D& Position, const FLinearColor& Color, float Scale = 1.0f); }; \ No newline at end of file diff --git a/Source/MyProject3/SpaceshipPawn.cpp b/Source/MyProject3/SpaceshipPawn.cpp index dff1f30..7601099 100644 --- a/Source/MyProject3/SpaceshipPawn.cpp +++ b/Source/MyProject3/SpaceshipPawn.cpp @@ -586,10 +586,6 @@ void ASpaceshipPawn::Die() DisableInput(PC); } - // You could either restart the level after a delay or show a game over screen here - // For example: - // GetWorldTimerManager().SetTimer(RestartTimerHandle, this, &ASpaceshipPawn::RestartLevel, 3.0f, false); - // For now, just log the death if (GEngine) {