Improve Game Over Screen

This commit is contained in:
2025-04-16 13:57:06 +05:30
parent f732cdef59
commit 7f08808b71
6 changed files with 127 additions and 29 deletions

Binary file not shown.

View File

@@ -48,6 +48,7 @@ public:
void RestartGame(); void RestartGame();
int32 GetKillCount() const { return KillCount; } int32 GetKillCount() const { return KillCount; }
float GetRemainingTime() const { return RemainingTime; } float GetRemainingTime() const { return RemainingTime; }
float GetGameDuration() const { return GameDuration; }
bool IsGameOver() const { return bIsGameOver; } bool IsGameOver() const { return bIsGameOver; }
protected: protected:

View File

@@ -10,6 +10,7 @@ ASpaceShooterHUD::ASpaceShooterHUD()
// Find and set the default font // Find and set the default font
static ConstructorHelpers::FObjectFinder<UFont> FontObj(TEXT("/Engine/EngineFonts/RobotoDistanceField")); static ConstructorHelpers::FObjectFinder<UFont> FontObj(TEXT("/Engine/EngineFonts/RobotoDistanceField"));
TextFont = FontObj.Object; TextFont = FontObj.Object;
GameOverStartTime = 0.0f;
} }
ASpaceshipPawn* ASpaceShooterHUD::GetPlayerPawn() const ASpaceshipPawn* ASpaceShooterHUD::GetPlayerPawn() const
@@ -112,39 +113,113 @@ void ASpaceShooterHUD::DrawGameplayHUD()
DrawStatusBars(); 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() void ASpaceShooterHUD::DrawGameOverScreen()
{ {
ASpaceShooterGameMode* GameMode = GetGameMode(); 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 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"); FString GameOverText = TEXT("GAME OVER");
float TextWidth, TextHeight; float TextWidth, TextHeight;
GetTextSize(GameOverText, TextWidth, TextHeight, TextFont); GetTextSize(GameOverText, TextWidth, TextHeight, TextFont, GameOverScale);
DrawText(GameOverText, FLinearColor::Red, DrawGameOverText(GameOverText,
ViewportSize.X / 2 - TextWidth / 2, FVector2D((ViewportSize.X - TextWidth) * 0.5f, CenterY),
ViewportSize.Y / 2 - TextHeight / 2, PulsatingColor,
TextFont, 2.0f); GameOverScale);
// Draw final score // Draw stats with scaling animations
FString ScoreText = FString::Printf(TEXT("Final Kill Count: %d"), GameMode->GetKillCount()); const float StatsScale = 1.5f;
GetTextSize(ScoreText, TextWidth, TextHeight, TextFont); float StatsY = CenterY + Spacing;
DrawText(ScoreText, FLinearColor::White,
ViewportSize.X / 2 - TextWidth / 2,
ViewportSize.Y / 2 + TextHeight * 2,
TextFont);
// 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"); FString RestartText = TEXT("Press R to Restart");
GetTextSize(RestartText, TextWidth, TextHeight, TextFont); GetTextSize(RestartText, TextWidth, TextHeight, TextFont, StatsScale);
DrawText(RestartText, FLinearColor::Yellow, DrawGameOverText(RestartText,
ViewportSize.X / 2 - TextWidth / 2, FVector2D((ViewportSize.X - TextWidth) * 0.5f, StatsY + BounceOffset),
ViewportSize.Y / 2 + TextHeight * 4, RestartTextColor,
TextFont); StatsScale);
} }
ASpaceShooterGameMode* ASpaceShooterHUD::GetGameMode() const ASpaceShooterGameMode* ASpaceShooterHUD::GetGameMode() const

View File

@@ -36,10 +36,36 @@ protected:
UPROPERTY(EditAnywhere, Category = "HUD|Bars") UPROPERTY(EditAnywhere, Category = "HUD|Bars")
FLinearColor BackgroundBarColor = FLinearColor(0.0f, 0.0f, 0.0f, 0.5f); // Semi-transparent black 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: private:
void DrawGameplayHUD(); void DrawGameplayHUD();
void DrawGameOverScreen(); void DrawGameOverScreen();
void DrawStatusBars(); void DrawStatusBars();
class ASpaceShooterGameMode* GetGameMode() const; class ASpaceShooterGameMode* GetGameMode() const;
class ASpaceshipPawn* GetPlayerPawn() const; class ASpaceshipPawn* GetPlayerPawn() const;
float GameOverStartTime;
void DrawGameOverBackground();
void DrawGameOverText(const FString& Text, const FVector2D& Position, const FLinearColor& Color, float Scale = 1.0f);
}; };

View File

@@ -586,10 +586,6 @@ void ASpaceshipPawn::Die()
DisableInput(PC); 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 // For now, just log the death
if (GEngine) if (GEngine)
{ {