diff --git a/Source/MyProject3/SpaceShooterGameMode.cpp b/Source/MyProject3/SpaceShooterGameMode.cpp index 3c01416..e639687 100644 --- a/Source/MyProject3/SpaceShooterGameMode.cpp +++ b/Source/MyProject3/SpaceShooterGameMode.cpp @@ -106,12 +106,11 @@ void ASpaceShooterGameMode::SpawnEnemy() switch (CurrentPattern) { case ESpawnPattern::Random: - // Spawn a single enemy at a random edge location { UWorld* World = GetWorld(); if (World && EnemyClass) { - FVector SpawnLocation = GetScreenEdgeSpawnLocation(); + FVector SpawnLocation = GetRandomSpawnLocation(); FRotator SpawnRotation = FRotator::ZeroRotator; FActorSpawnParameters SpawnParams; SpawnParams.SpawnCollisionHandlingOverride = @@ -145,66 +144,49 @@ void ASpaceShooterGameMode::SpawnEnemy() void ASpaceShooterGameMode::SpawnEnemyWave() { - // Count current enemies - TArray FoundEnemies; - UGameplayStatics::GetAllActorsOfClass(GetWorld(), AEnemySpaceship::StaticClass(), FoundEnemies); + UWorld* World = GetWorld(); + if (!World || !EnemyClass) + return; - // Only spawn if we haven't reached the maximum - if (FoundEnemies.Num() < MaxEnemies) + // Get player location for facing direction + FVector PlayerLocation = GetPlayerLocation(); + + // Choose a random angle for the wave + float WaveAngle = FMath::RandRange(0.0f, 2.0f * PI); + FVector2D BaseDirection(FMath::Cos(WaveAngle), FMath::Sin(WaveAngle)); + + // Create a perpendicular direction for the wave line + FVector2D PerpDirection(-BaseDirection.Y, BaseDirection.X); + + // Spawn wave of enemies + for (int32 i = 0; i < WaveSize; i++) { + // Calculate base spawn position + FVector BaseSpawnPos = PlayerLocation + FVector(BaseDirection.X, BaseDirection.Y, 0) * MinimumSpawnDistance; - UWorld* World = GetWorld(); - if (!World || !EnemyClass) - return; + // Offset along the wave line + FVector Offset = FVector(PerpDirection.X, PerpDirection.Y, 0) * (i - WaveSize / 2) * FormationSpacing; + FVector SpawnLocation = BaseSpawnPos + Offset; - // Choose a random direction for the wave - float WaveAngle = FMath::RandRange(0.0f, 2.0f * PI); - FVector2D EdgeDirection(FMath::Cos(WaveAngle), FMath::Sin(WaveAngle)); + FRotator SpawnRotation = FRotator::ZeroRotator; + FActorSpawnParameters SpawnParams; + SpawnParams.SpawnCollisionHandlingOverride = + ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; - // Get player location for facing direction - FVector PlayerLocation = GetPlayerLocation(); + AEnemySpaceship* NewEnemy = World->SpawnActor( + EnemyClass, SpawnLocation, SpawnRotation, SpawnParams); - // Get screen bounds - TArray ScreenBounds = GetScreenBounds(); - float ScreenWidth = ScreenBounds[1].X - ScreenBounds[0].X; - - // Create a line of enemies perpendicular to the direction - FVector2D PerpDirection(-EdgeDirection.Y, EdgeDirection.X); - - // Spawn wave of enemies - increased distance from 2000 to MinimumSpawnDistance - for (int32 i = 0; i < WaveSize; i++) + if (NewEnemy) { - FVector ProposedLocation; - ProposedLocation.X = PlayerLocation.X + (EdgeDirection.X * MinimumSpawnDistance) + - (PerpDirection.X * (i - WaveSize / 2) * FormationSpacing); - ProposedLocation.Y = PlayerLocation.Y + (EdgeDirection.Y * MinimumSpawnDistance) + - (PerpDirection.Y * (i - WaveSize / 2) * FormationSpacing); - ProposedLocation.Z = PlayerLocation.Z; - - // Ensure the spawn location is far enough from the player - FVector SpawnLocation = EnsureMinimumSpawnDistance(ProposedLocation, PlayerLocation); - - FRotator SpawnRotation = FRotator::ZeroRotator; - FActorSpawnParameters SpawnParams; - SpawnParams.SpawnCollisionHandlingOverride = - ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; - - AEnemySpaceship* NewEnemy = World->SpawnActor( - EnemyClass, SpawnLocation, SpawnRotation, SpawnParams); - - if (NewEnemy) - { - RotateTowardsPlayer(NewEnemy, PlayerLocation); - } + RotateTowardsPlayer(NewEnemy, PlayerLocation); } + } - // Increase wave counter and possibly switch back to random - CurrentWaveCount++; - if (CurrentWaveCount >= 3) - { - CurrentPattern = ESpawnPattern::Random; - CurrentWaveCount = 0; - } + CurrentWaveCount++; + if (CurrentWaveCount >= 3) + { + CurrentPattern = ESpawnPattern::Random; + CurrentWaveCount = 0; } } @@ -312,163 +294,70 @@ void ASpaceShooterGameMode::SpawnEnemyFormation() void ASpaceShooterGameMode::SpawnEnemyFlanking() { - // Count current enemies - TArray FoundEnemies; - UGameplayStatics::GetAllActorsOfClass(GetWorld(), AEnemySpaceship::StaticClass(), FoundEnemies); + UWorld* World = GetWorld(); + if (!World || !EnemyClass) + return; - // Only spawn if we haven't reached the maximum - if (FoundEnemies.Num() < MaxEnemies) + FVector PlayerLocation = GetPlayerLocation(); + + // Spawn enemies from multiple sides (2-3 sides) + int32 NumSides = FMath::RandRange(2, 3); + float BaseAngle = FMath::RandRange(0.0f, 2.0f * PI); + + for (int32 Side = 0; Side < NumSides; Side++) { + // Calculate angle for this side + float Angle = BaseAngle + (Side * (2.0f * PI / NumSides)); - UWorld* World = GetWorld(); - if (!World || !EnemyClass) - return; + // Spawn 1-2 enemies from this side + int32 NumEnemies = FMath::RandRange(1, 2); - // Get player location - FVector PlayerLocation = GetPlayerLocation(); - - // Spawn enemies from multiple sides (usually 2-3 sides) - int32 NumSides = FMath::RandRange(2, 3); - float BaseAngle = FMath::RandRange(0.0f, 2.0f * PI); - - for (int32 Side = 0; Side < NumSides; Side++) + for (int32 i = 0; i < NumEnemies; i++) { - // Calculate angle for this side - float Angle = BaseAngle + (Side * (2.0f * PI / NumSides)); - FVector2D Direction(FMath::Cos(Angle), FMath::Sin(Angle)); + // Add some variation to the spawn position + float OffsetAngle = Angle + FMath::RandRange(-0.3f, 0.3f); + FVector Direction(FMath::Cos(OffsetAngle), FMath::Sin(OffsetAngle), 0.0f); - // Spawn 1-2 enemies from this side - int32 NumEnemies = FMath::RandRange(1, 2); + // Calculate spawn position + FVector SpawnLocation = PlayerLocation + (Direction * (MinimumSpawnDistance + FMath::RandRange(0.0f, 300.0f))); - for (int32 i = 0; i < NumEnemies; i++) + FRotator SpawnRotation = FRotator::ZeroRotator; + FActorSpawnParameters SpawnParams; + SpawnParams.SpawnCollisionHandlingOverride = + ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; + + AEnemySpaceship* NewEnemy = World->SpawnActor( + EnemyClass, SpawnLocation, SpawnRotation, SpawnParams); + + if (NewEnemy) { - // Add some variation to the spawn position - float OffsetAngle = Angle + FMath::RandRange(-0.3f, 0.3f); - FVector2D OffsetDir(FMath::Cos(OffsetAngle), FMath::Sin(OffsetAngle)); - - // Increased from 2000 to MinimumSpawnDistance - FVector ProposedLocation = PlayerLocation + FVector(OffsetDir.X, OffsetDir.Y, 0) * MinimumSpawnDistance; - - // Ensure the spawn location is far enough from the player - FVector SpawnLocation = EnsureMinimumSpawnDistance(ProposedLocation, PlayerLocation); - - FRotator SpawnRotation = FRotator::ZeroRotator; - FActorSpawnParameters SpawnParams; - SpawnParams.SpawnCollisionHandlingOverride = - ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; - - AEnemySpaceship* NewEnemy = World->SpawnActor( - EnemyClass, SpawnLocation, SpawnRotation, SpawnParams); - - if (NewEnemy) - { - RotateTowardsPlayer(NewEnemy, PlayerLocation); - } + RotateTowardsPlayer(NewEnemy, PlayerLocation); } } - - // Return to random spawning - CurrentPattern = ESpawnPattern::Random; } + + CurrentPattern = ESpawnPattern::Random; } -FVector ASpaceShooterGameMode::GetScreenEdgeSpawnLocation() +FVector ASpaceShooterGameMode::GetRandomSpawnLocation() { FVector PlayerLocation = GetPlayerLocation(); - TArray ScreenBounds = GetScreenBounds(); - // Decide which edge to spawn from (0 = top, 1 = right, 2 = bottom, 3 = left) - int32 Edge = FMath::RandRange(0, 3); + // Generate a random angle in radians + float RandomAngle = FMath::RandRange(0.0f, 2.0f * PI); - FVector SpawnLocation; - float RandomPos; + // Create a direction vector from the random angle + FVector Direction( + FMath::Cos(RandomAngle), + FMath::Sin(RandomAngle), + 0.0f + ); - // Increased margin to spawn farther from screen edges - float ExtendedMargin = ScreenSpawnMargin + 500.0f; + // Use the minimum spawn distance plus some random additional distance + float SpawnDistance = MinimumSpawnDistance + FMath::RandRange(0.0f, 500.0f); - switch (Edge) - { - case 0: // Top edge - RandomPos = FMath::RandRange(ScreenBounds[0].X, ScreenBounds[1].X); - SpawnLocation = FVector(RandomPos, ScreenBounds[0].Y - ExtendedMargin, PlayerLocation.Z); - break; - - case 1: // Right edge - RandomPos = FMath::RandRange(ScreenBounds[0].Y, ScreenBounds[1].Y); - SpawnLocation = FVector(ScreenBounds[1].X + ExtendedMargin, RandomPos, PlayerLocation.Z); - break; - - case 2: // Bottom edge - RandomPos = FMath::RandRange(ScreenBounds[0].X, ScreenBounds[1].X); - SpawnLocation = FVector(RandomPos, ScreenBounds[1].Y + ExtendedMargin, PlayerLocation.Z); - break; - - case 3: // Left edge - RandomPos = FMath::RandRange(ScreenBounds[0].Y, ScreenBounds[1].Y); - SpawnLocation = FVector(ScreenBounds[0].X - ExtendedMargin, RandomPos, PlayerLocation.Z); - break; - } - - // Ensure the spawn location is far enough from the player - return EnsureMinimumSpawnDistance(SpawnLocation, PlayerLocation); -} - -FVector ASpaceShooterGameMode::GetSpawnZoneLocation() -{ - // If no spawn zones are defined, return a screen edge location - if (SpawnZones.Num() == 0) - { - return GetScreenEdgeSpawnLocation(); - } - - // Filter active spawn zones - TArray ActiveZones; - float TotalWeight = 0.0f; - - for (const FSpawnZone& Zone : SpawnZones) - { - if (Zone.bActive) - { - ActiveZones.Add(Zone); - TotalWeight += Zone.SpawnWeight; - } - } - - // If no active zones, return screen edge - if (ActiveZones.Num() == 0) - { - return GetScreenEdgeSpawnLocation(); - } - - // Select a zone based on weight - float RandomWeight = FMath::RandRange(0.0f, TotalWeight); - float WeightSum = 0.0f; - FVector PlayerLocation = GetPlayerLocation(); - - for (const FSpawnZone& Zone : ActiveZones) - { - WeightSum += Zone.SpawnWeight; - if (RandomWeight <= WeightSum) - { - // Generate random point within this zone's radius - float RandomAngle = FMath::RandRange(0.0f, 2.0f * PI); - float RandomRadius = FMath::RandRange(0.0f, Zone.Radius); - - FVector SpawnOffset( - FMath::Cos(RandomAngle) * RandomRadius, - FMath::Sin(RandomAngle) * RandomRadius, - 0.0f - ); - - FVector ProposedLocation = Zone.Location + SpawnOffset; - - // Ensure the spawn location is far enough from the player - return EnsureMinimumSpawnDistance(ProposedLocation, PlayerLocation); - } - } - - // Fallback - return GetScreenEdgeSpawnLocation(); + // Calculate the spawn position + return PlayerLocation + (Direction * SpawnDistance); } void ASpaceShooterGameMode::UpdateDifficulty() @@ -499,48 +388,6 @@ FVector ASpaceShooterGameMode::GetPlayerLocation() return FVector::ZeroVector; } -TArray ASpaceShooterGameMode::GetScreenBounds() -{ - TArray Bounds; - FVector2D ScreenMin, ScreenMax; - - // Get player controller for screen info - APlayerController* PlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0); - if (!PlayerController) - { - // Fallback values if no controller - Bounds.Add(FVector2D(-2000, -2000)); - Bounds.Add(FVector2D(2000, 2000)); - return Bounds; - } - - // Get viewport size - int32 ViewportSizeX, ViewportSizeY; - PlayerController->GetViewportSize(ViewportSizeX, ViewportSizeY); - - // Get world location of screen corners - FVector WorldLocation, WorldDirection; - - // Top-Left corner - PlayerController->DeprojectScreenPositionToWorld(0, 0, WorldLocation, WorldDirection); - ScreenMin = FVector2D(WorldLocation.X, WorldLocation.Y); - - // Bottom-Right corner - PlayerController->DeprojectScreenPositionToWorld(ViewportSizeX, ViewportSizeY, WorldLocation, WorldDirection); - ScreenMax = FVector2D(WorldLocation.X, WorldLocation.Y); - - // Add some margin - ScreenMin.X -= 200; - ScreenMin.Y -= 200; - ScreenMax.X += 200; - ScreenMax.Y += 200; - - Bounds.Add(ScreenMin); - Bounds.Add(ScreenMax); - - return Bounds; -} - void ASpaceShooterGameMode::RotateTowardsPlayer(AEnemySpaceship* Enemy, const FVector& PlayerLocation) { if (!Enemy) diff --git a/Source/MyProject3/SpaceShooterGameMode.h b/Source/MyProject3/SpaceShooterGameMode.h index f4c55a9..9dc06b8 100644 --- a/Source/MyProject3/SpaceShooterGameMode.h +++ b/Source/MyProject3/SpaceShooterGameMode.h @@ -109,11 +109,9 @@ private: void SpawnEnemyWave(); void SpawnEnemyFormation(); void SpawnEnemyFlanking(); - FVector GetScreenEdgeSpawnLocation(); - FVector GetSpawnZoneLocation(); + FVector GetRandomSpawnLocation(); void UpdateDifficulty(); FVector GetPlayerLocation(); - TArray GetScreenBounds(); void RotateTowardsPlayer(AEnemySpaceship* Enemy, const FVector& PlayerLocation); // New helper method to ensure minimum spawn distance