Make sure max enemies applies properly

This commit is contained in:
2025-04-16 08:50:06 +05:30
parent 67ac9d1935
commit c292da805d

View File

@@ -138,183 +138,41 @@ void ASpaceShooterGameMode::SpawnEnemy()
void ASpaceShooterGameMode::SpawnEnemyWave() void ASpaceShooterGameMode::SpawnEnemyWave()
{ {
UWorld* World = GetWorld(); // Count current enemies
if (!World || !EnemyClass) TArray<AActor*> FoundEnemies;
return; UGameplayStatics::GetAllActorsOfClass(GetWorld(), AEnemySpaceship::StaticClass(), FoundEnemies);
// Choose a random direction for the wave // Only spawn if we haven't reached the maximum
float WaveAngle = FMath::RandRange(0.0f, 2.0f * PI); if (FoundEnemies.Num() < MaxEnemies)
FVector2D EdgeDirection(FMath::Cos(WaveAngle), FMath::Sin(WaveAngle));
// Get player location for facing direction
FVector PlayerLocation = GetPlayerLocation();
// Get screen bounds
TArray<FVector2D> 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++)
{ {
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 UWorld* World = GetWorld();
FVector SpawnLocation = EnsureMinimumSpawnDistance(ProposedLocation, PlayerLocation); if (!World || !EnemyClass)
return;
FRotator SpawnRotation = FRotator::ZeroRotator; // Choose a random direction for the wave
FActorSpawnParameters SpawnParams; float WaveAngle = FMath::RandRange(0.0f, 2.0f * PI);
SpawnParams.SpawnCollisionHandlingOverride = FVector2D EdgeDirection(FMath::Cos(WaveAngle), FMath::Sin(WaveAngle));
ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
AEnemySpaceship* NewEnemy = World->SpawnActor<AEnemySpaceship>( // Get player location for facing direction
EnemyClass, SpawnLocation, SpawnRotation, SpawnParams); FVector PlayerLocation = GetPlayerLocation();
if (NewEnemy) // Get screen bounds
TArray<FVector2D> 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++)
{ {
RotateTowardsPlayer(NewEnemy, PlayerLocation); FVector ProposedLocation;
} ProposedLocation.X = PlayerLocation.X + (EdgeDirection.X * MinimumSpawnDistance) +
} (PerpDirection.X * (i - WaveSize / 2) * FormationSpacing);
ProposedLocation.Y = PlayerLocation.Y + (EdgeDirection.Y * MinimumSpawnDistance) +
// Increase wave counter and possibly switch back to random (PerpDirection.Y * (i - WaveSize / 2) * FormationSpacing);
CurrentWaveCount++; ProposedLocation.Z = PlayerLocation.Z;
if (CurrentWaveCount >= 3)
{
CurrentPattern = ESpawnPattern::Random;
CurrentWaveCount = 0;
}
}
void ASpaceShooterGameMode::SpawnEnemyFormation()
{
UWorld* World = GetWorld();
if (!World || !EnemyClass)
return;
// Get player location
FVector PlayerLocation = GetPlayerLocation();
// Select a formation type (0 = V-formation, 1 = Line, 2 = Diamond)
int32 FormationType = FMath::RandRange(0, 2);
// Choose a random approach angle
float ApproachAngle = FMath::RandRange(0.0f, 2.0f * PI);
FVector2D ApproachDir(FMath::Cos(ApproachAngle), FMath::Sin(ApproachAngle));
// Base spawn position far from player - increased from 2500 to MinimumSpawnDistance + 500
FVector BaseSpawnPos = PlayerLocation + FVector(ApproachDir.X, ApproachDir.Y, 0) * (MinimumSpawnDistance + 500.0f);
// Create formation positions
TArray<FVector> FormationPositions;
switch (FormationType)
{
case 0: // V-formation
for (int32 i = 0; i < 5; i++)
{
if (i == 0) // Leader
{
FormationPositions.Add(BaseSpawnPos);
}
else if (i % 2 == 1) // Left wing
{
FVector Offset(-ApproachDir.Y, ApproachDir.X, 0);
FormationPositions.Add(BaseSpawnPos + Offset * FormationSpacing * ((i + 1) / 2));
}
else // Right wing
{
FVector Offset(ApproachDir.Y, -ApproachDir.X, 0);
FormationPositions.Add(BaseSpawnPos + Offset * FormationSpacing * (i / 2));
}
}
break;
case 1: // Line formation
for (int32 i = 0; i < 5; i++)
{
FVector2D PerpDir(-ApproachDir.Y, ApproachDir.X);
FVector Offset(PerpDir.X, PerpDir.Y, 0);
FormationPositions.Add(BaseSpawnPos + Offset * FormationSpacing * (i - 2));
}
break;
case 2: // Diamond formation
FormationPositions.Add(BaseSpawnPos); // Center
FVector2D PerpDir(-ApproachDir.Y, ApproachDir.X);
// Top
FormationPositions.Add(BaseSpawnPos + FVector(ApproachDir.X, ApproachDir.Y, 0) * FormationSpacing);
// Bottom
FormationPositions.Add(BaseSpawnPos - FVector(ApproachDir.X, ApproachDir.Y, 0) * FormationSpacing);
// Left
FormationPositions.Add(BaseSpawnPos + FVector(PerpDir.X, PerpDir.Y, 0) * FormationSpacing);
// Right
FormationPositions.Add(BaseSpawnPos - FVector(PerpDir.X, PerpDir.Y, 0) * FormationSpacing);
break;
}
// Spawn enemies at formation positions
for (const FVector& Position : FormationPositions)
{
// Ensure the spawn location is far enough from the player
FVector SpawnLocation = EnsureMinimumSpawnDistance(Position, PlayerLocation);
FRotator SpawnRotation = FRotator::ZeroRotator;
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride =
ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
AEnemySpaceship* NewEnemy = World->SpawnActor<AEnemySpaceship>(
EnemyClass, SpawnLocation, SpawnRotation, SpawnParams);
if (NewEnemy)
{
RotateTowardsPlayer(NewEnemy, PlayerLocation);
}
}
// Switch back to random pattern after a formation spawn
CurrentPattern = ESpawnPattern::Random;
}
void ASpaceShooterGameMode::SpawnEnemyFlanking()
{
UWorld* World = GetWorld();
if (!World || !EnemyClass)
return;
// 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++)
{
// Calculate angle for this side
float Angle = BaseAngle + (Side * (2.0f * PI / NumSides));
FVector2D Direction(FMath::Cos(Angle), FMath::Sin(Angle));
// Spawn 1-2 enemies from this side
int32 NumEnemies = FMath::RandRange(1, 2);
for (int32 i = 0; i < NumEnemies; i++)
{
// 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 // Ensure the spawn location is far enough from the player
FVector SpawnLocation = EnsureMinimumSpawnDistance(ProposedLocation, PlayerLocation); FVector SpawnLocation = EnsureMinimumSpawnDistance(ProposedLocation, PlayerLocation);
@@ -332,10 +190,179 @@ void ASpaceShooterGameMode::SpawnEnemyFlanking()
RotateTowardsPlayer(NewEnemy, PlayerLocation); RotateTowardsPlayer(NewEnemy, PlayerLocation);
} }
} }
}
// Return to random spawning // Increase wave counter and possibly switch back to random
CurrentPattern = ESpawnPattern::Random; CurrentWaveCount++;
if (CurrentWaveCount >= 3)
{
CurrentPattern = ESpawnPattern::Random;
CurrentWaveCount = 0;
}
}
}
void ASpaceShooterGameMode::SpawnEnemyFormation()
{
// Count current enemies
TArray<AActor*> FoundEnemies;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AEnemySpaceship::StaticClass(), FoundEnemies);
// Only spawn if we haven't reached the maximum
if (FoundEnemies.Num() < MaxEnemies)
{
UWorld* World = GetWorld();
if (!World || !EnemyClass)
return;
// Get player location
FVector PlayerLocation = GetPlayerLocation();
// Select a formation type (0 = V-formation, 1 = Line, 2 = Diamond)
int32 FormationType = FMath::RandRange(0, 2);
// Choose a random approach angle
float ApproachAngle = FMath::RandRange(0.0f, 2.0f * PI);
FVector2D ApproachDir(FMath::Cos(ApproachAngle), FMath::Sin(ApproachAngle));
// Base spawn position far from player - increased from 2500 to MinimumSpawnDistance + 500
FVector BaseSpawnPos = PlayerLocation + FVector(ApproachDir.X, ApproachDir.Y, 0) * (MinimumSpawnDistance + 500.0f);
// Create formation positions
TArray<FVector> FormationPositions;
switch (FormationType)
{
case 0: // V-formation
for (int32 i = 0; i < 5; i++)
{
if (i == 0) // Leader
{
FormationPositions.Add(BaseSpawnPos);
}
else if (i % 2 == 1) // Left wing
{
FVector Offset(-ApproachDir.Y, ApproachDir.X, 0);
FormationPositions.Add(BaseSpawnPos + Offset * FormationSpacing * ((i + 1) / 2));
}
else // Right wing
{
FVector Offset(ApproachDir.Y, -ApproachDir.X, 0);
FormationPositions.Add(BaseSpawnPos + Offset * FormationSpacing * (i / 2));
}
}
break;
case 1: // Line formation
for (int32 i = 0; i < 5; i++)
{
FVector2D PerpDir(-ApproachDir.Y, ApproachDir.X);
FVector Offset(PerpDir.X, PerpDir.Y, 0);
FormationPositions.Add(BaseSpawnPos + Offset * FormationSpacing * (i - 2));
}
break;
case 2: // Diamond formation
FormationPositions.Add(BaseSpawnPos); // Center
FVector2D PerpDir(-ApproachDir.Y, ApproachDir.X);
// Top
FormationPositions.Add(BaseSpawnPos + FVector(ApproachDir.X, ApproachDir.Y, 0) * FormationSpacing);
// Bottom
FormationPositions.Add(BaseSpawnPos - FVector(ApproachDir.X, ApproachDir.Y, 0) * FormationSpacing);
// Left
FormationPositions.Add(BaseSpawnPos + FVector(PerpDir.X, PerpDir.Y, 0) * FormationSpacing);
// Right
FormationPositions.Add(BaseSpawnPos - FVector(PerpDir.X, PerpDir.Y, 0) * FormationSpacing);
break;
}
// Spawn enemies at formation positions
for (const FVector& Position : FormationPositions)
{
// Ensure the spawn location is far enough from the player
FVector SpawnLocation = EnsureMinimumSpawnDistance(Position, PlayerLocation);
FRotator SpawnRotation = FRotator::ZeroRotator;
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride =
ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
AEnemySpaceship* NewEnemy = World->SpawnActor<AEnemySpaceship>(
EnemyClass, SpawnLocation, SpawnRotation, SpawnParams);
if (NewEnemy)
{
RotateTowardsPlayer(NewEnemy, PlayerLocation);
}
}
// Switch back to random pattern after a formation spawn
CurrentPattern = ESpawnPattern::Random;
}
}
void ASpaceShooterGameMode::SpawnEnemyFlanking()
{
// Count current enemies
TArray<AActor*> FoundEnemies;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AEnemySpaceship::StaticClass(), FoundEnemies);
// Only spawn if we haven't reached the maximum
if (FoundEnemies.Num() < MaxEnemies)
{
UWorld* World = GetWorld();
if (!World || !EnemyClass)
return;
// 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++)
{
// Calculate angle for this side
float Angle = BaseAngle + (Side * (2.0f * PI / NumSides));
FVector2D Direction(FMath::Cos(Angle), FMath::Sin(Angle));
// Spawn 1-2 enemies from this side
int32 NumEnemies = FMath::RandRange(1, 2);
for (int32 i = 0; i < NumEnemies; i++)
{
// 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<AEnemySpaceship>(
EnemyClass, SpawnLocation, SpawnRotation, SpawnParams);
if (NewEnemy)
{
RotateTowardsPlayer(NewEnemy, PlayerLocation);
}
}
}
// Return to random spawning
CurrentPattern = ESpawnPattern::Random;
}
} }
FVector ASpaceShooterGameMode::GetScreenEdgeSpawnLocation() FVector ASpaceShooterGameMode::GetScreenEdgeSpawnLocation()