>>.... Mobile Spawn Algorithm.... Header File
-> NOTE: THIS IS RAW SOURCE
>>.... Mobile Spawn Algorithm... CPP File
//-----------------------------------------------------------------------------------------------------------------
// Simnply Spawns an object in the game world for a simple mobile game. -
// This was the verticle slice build to test some other systems for the game concept. -
// Nicholas Mallonee -
//-----------------------------------------------------------------------------------------------------------------
#pragma once
//-----------------------------------------------------------------------------------------------------------------
// Includes and Libraries -
//-----------------------------------------------------------------------------------------------------------------
#include "GameFramework/Actor.h"
#include "Code_Base/Orbs/Orb.h"
#include "Runtime/Engine/Public/TimerManager.h"
#include "Spawner.generated.h"
//-----------------------------------------------------------------------------------------------------------------
// Spawner States -- Enum -
//-----------------------------------------------------------------------------------------------------------------
UENUM()
enum class ESpawnerState : uint8
{
Random,
Trail,
EveryOther
};
//-----------------------------------------------------------------------------------------------------------------
// Spawner Struct -
//-----------------------------------------------------------------------------------------------------------------
USTRUCT(BlueprintType)
struct FSpawnerInformation
{
GENERATED_USTRUCT_BODY()
// -- Private -- Struct information
private:
UPROPERTY()
ESpawnerState state;
UPROPERTY()
TArray lastUsedLocations;
UPROPERTY()
int32 spawnCount;
// -- Public -- Accessors, Mutators, Other methods, and constuctor
public:
/*
* Takes a state to change the spawner to
* @Param The state that the spawner should be changed to
*/
void setState(ESpawnerState inState)
{
state = inState;
}
/*
* Adds a Vector to the struct's array
* @Param The Vector in which to add to the array
*/
void addLocation(FVector loc)
{
if (lastUsedLocations.Num() > 10)
{
lastUsedLocations.RemoveAt(0);
lastUsedLocations.Add(loc);
}
else
{
lastUsedLocations.Add(loc);
}
}
/*
* Changes the number of Spawn Count
* @Param Number to change the spawn count to
*/
void setSpawnCount(int32 in)
{
spawnCount = in;
}
/*
* Returns the state of the spawners behavior
* @Return the current state of the spawner
*/
ESpawnerState getState()
{
return state;
}
/*
* @Param Takes in a position to return
* @Return The Vector at a given Position
*/
FVector getLocation(int32 pos)
{
return lastUsedLocations[pos];
}
/*
* Returns the current count of how many times a spawn method has been called
* Since the last time it switched.
* @Return the int32 value of many times a metod was called
*/
int32 getCount()
{
return spawnCount;
}
/*
* Returns the array's logical size
* @Returns the arrays size + 1
*/
int32 getArraySize()
{
return lastUsedLocations.Num();
}
/*
* Checks for an exact x in the array using a linear search
* Note: This Method was never used and was later removed.
* @Returns If an X was found
*/
bool isXInArray(float x)
{
bool flag = false;
return flag;
}
/*
* Destroyes the objects to Gives the Memory back to the system
*/
void destroy()
{
lastUsedLocations.~TArray();
}
// -- Default Constructor
FSpawnerInformation()
{
state = ESpawnerState::Random;
spawnCount = 0;
lastUsedLocations.SetNum(0);
}
};
//-----------------------------------------------------------------------------------------------------------------
// Spawner Class Information -
//-----------------------------------------------------------------------------------------------------------------
UCLASS()
class BERYL_API ASpawner : public AActor
{
GENERATED_BODY()
// -- Public Information -- Constructor and Engine Events -- //
public:
ASpawner();
virtual void BeginPlay() override;
virtual void Tick( float DeltaSeconds ) override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
// -- Private Information -- Spawning Methods -- //
private:
void determineSpawnPath();
void spawnInRandomSpot();
void spawnUsingGeneratedX(float inX);
// -- Private Information -- Number Generation and Check -- //
private:
bool canUseX(float inX);
float generateNewRandomX();
float generateTrailX();
float generateEveryOther();
// -- Private Information -- Orbs to Spawn -- //
private:
UPROPERTY(EditDefaultsOnly, Category = "Basic Orb")
TSubclassOf basicOrb;
// -- Private Information -- Spawner Information Struct -- //
private:
FSpawnerInformation spawnerInformation;
// -- Private Information -- Timers -- //
private:
FTimerManager spawnTimer;
FTimerHandle spawnTimerHandler;
};
//-----------------------------------------------------------------------------------------------------------------
// Simnply Spawns an object in the game world for a simple mobile game. -
// This was the verticle slice build to test some other systems for the game concept. -
// Nicholas Mallonee -
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
// Includes and Libraries -
//-----------------------------------------------------------------------------------------------------------------
#include "Beryl.h"
#include "Engine.h"
#include "Spawner.h"
//-----------------------------------------------------------------------------------------------------------------
// Constructors -
//-----------------------------------------------------------------------------------------------------------------
ASpawner::ASpawner()
{
// Allow the actor to tick
PrimaryActorTick.bCanEverTick = true;
}
//-----------------------------------------------------------------------------------------------------------------
// Engine Events -
//-----------------------------------------------------------------------------------------------------------------
void ASpawner::BeginPlay()
{
Super::BeginPlay();
// Set the handler
GetWorld()->GetTimerManager().SetTimer(spawnTimerHandler, this, &ASpawner::determineSpawnPath, .15f, true);
}
void ASpawner::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
}
void ASpawner::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
// destroy the array in the struct
spawnerInformation.destroy();
// Clear Any Timers that are live -- Old way, removed after 4.7
//GetWorldTimerManager().ClearTimer(this, &ASpawner::spawnInRandomSpot);
// Clear Any Timers that are live -- new way
GetWorld()->GetTimerManager().ClearTimer(spawnTimerHandler);
// If we wanted to clear all the timers. -- safe way to remove all
//UWorld* const world = GetWorld();
//if (world)
//{
// GetWorld()->GetTimerManager().ClearAllTimersForObject(this);
//}
Super::EndPlay(EndPlayReason);
}
//-----------------------------------------------------------------------------------------------------------------
// Basic Spawn Methods -
//-----------------------------------------------------------------------------------------------------------------
void ASpawner::determineSpawnPath()
{
// Check the current state
if (spawnerInformation.getState() == ESpawnerState::Random)
{
// Check the last time it was changed, if it is above 50 switch the state
if (spawnerInformation.getCount() >= 50)
{
int32 rand = FMath::RandRange(0, 10); // Random number to choose the weighted next state
if (rand >= 0 && rand < 7) // 0 through 6
{
spawnerInformation.setState(ESpawnerState::Trail); // Change the state to trails
spawnerInformation.setSpawnCount(0); // Set the spawn count back to 0
// Ignore the check for spaces and quick generate a place to spawn
spawnInRandomSpot();
}
else if (rand >= 7 && rand < 10)
{
spawnerInformation.setState(ESpawnerState::Random); // Change the state to random again
spawnerInformation.setSpawnCount(0); // Set the spawn count back to 0
// Ignore the check for spaces and quick generate a place to spawn
spawnInRandomSpot();
}
else
{
spawnerInformation.setState(ESpawnerState::EveryOther); // Change the state to everyother
spawnerInformation.setSpawnCount(0); // Set the spawn count back to 0
// Ignore the check for spaces and quick generate a place to spawn so we can go back around
spawnInRandomSpot();
}
}
else // Else we know we can check and spawn an object
{
float newX = generateNewRandomX(); // Generate a new X to use
spawnerInformation.setSpawnCount((spawnerInformation.getCount() + 1)); // Add to the count
spawnUsingGeneratedX(newX); // Spawn the new object
}
}
else if (spawnerInformation.getState() == ESpawnerState::Trail)
{
if (spawnerInformation.getCount() >= 5)
{
int32 rand = FMath::RandRange(0, 10); // Random number to choose the weighted next state
if (rand >= 0 && rand < 7) // 0 through 6
{
spawnerInformation.setState(ESpawnerState::Random); // Change the state to trails
spawnerInformation.setSpawnCount(0); // Set the spawn count back to 0
// Ignore the check for spaces and quick generate a place to spawn
spawnInRandomSpot();
}
else if (rand >= 7 && rand < 10)
{
spawnerInformation.setState(ESpawnerState::Trail); // Change the state to random again
spawnerInformation.setSpawnCount(0); // Set the spawn count back to 0
// Ignore the check for spaces and quick generate a place to spawn
spawnInRandomSpot();
}
else
{
spawnerInformation.setState(ESpawnerState::EveryOther); // Change the state to everyother
spawnerInformation.setSpawnCount(0); // Set the spawn count back to 0
// Ignore the check for spaces and quick generate a place to spawn so we can go back around
spawnInRandomSpot();
}
}
else
{
float newX = generateTrailX(); // Generate a new X to use
spawnerInformation.setSpawnCount((spawnerInformation.getCount() + 1)); // Add to the count
spawnUsingGeneratedX(newX); // Spawn the new object
}
}
else if (spawnerInformation.getState() == ESpawnerState::EveryOther)
{
if (spawnerInformation.getCount() >= 7)
{
int32 rand = FMath::RandRange(0, 10); // Random number to choose the weighted next state
if (rand >= 0 && rand < 7) // 0 through 6
{
spawnerInformation.setState(ESpawnerState::Random); // Change the state to trails
spawnerInformation.setSpawnCount(0); // Set the spawn count back to 0
// Ignore the check for spaces and quick generate a place to spawn
spawnInRandomSpot();
}
else if (rand >= 7 && rand < 10)
{
spawnerInformation.setState(ESpawnerState::Trail); // Change the state to random again
spawnerInformation.setSpawnCount(0); // Set the spawn count back to 0
// Ignore the check for spaces and quick generate a place to spawn
spawnInRandomSpot();
}
else
{
spawnerInformation.setState(ESpawnerState::EveryOther); // Change the state to everyother
spawnerInformation.setSpawnCount(0); // Set the spawn count back to 0
// Ignore the check for spaces and quick generate a place to spawn so we can go back around
spawnInRandomSpot();
}
}
else
{
float newX = generateEveryOther(); // Generate a new X to use
spawnerInformation.setSpawnCount((spawnerInformation.getCount() + 1)); // Add to the count
spawnUsingGeneratedX(newX); // Spawn the new object
}
}
else
{
spawnerInformation.setState(ESpawnerState::Random); // Change the state to trails
spawnerInformation.setSpawnCount(0); // Set the spawn count back to 0
// Ignore the check for spaces and quick generate a place to spawn
spawnInRandomSpot();
}
}
void ASpawner::spawnInRandomSpot()
{
// Check for world and have it as a const
UWorld* const world = GetWorld();
// if the world exists try to spawn the object
if (world)
{
// Generate an X to use
float x = FMath::RandRange(-270, 270);
// generate to the left of the player
FVector loc = FVector(0.f, x, 500.f);
// set the spawn params
FActorSpawnParameters spawnParams;
spawnParams.Owner = this;
spawnParams.Instigator = Instigator;
// Spawn the actor
GetWorld()->SpawnActor<AOrb>(basicOrb, loc, FRotator::ZeroRotator, spawnParams);
}
}
void ASpawner::spawnUsingGeneratedX(float inX)
{
// Check for world and have it as a const
UWorld* const world = GetWorld();
// if the world exists try to spawn the object
if (world)
{
// Package the X into a vector
FVector loc = FVector(0.f, inX, 500.f);
// Save the packaged Vector
spawnerInformation.addLocation(loc);
// set the spawn params
FActorSpawnParameters spawnParams;
spawnParams.Owner = this;
spawnParams.Instigator = Instigator;
// Spawn the actor
GetWorld()->SpawnActor<AOrb>(basicOrb, loc, FRotator::ZeroRotator, spawnParams);
}
}
//-----------------------------------------------------------------------------------------------------------------
// Basic Number Generation and checks -
//-----------------------------------------------------------------------------------------------------------------
bool ASpawner::canUseX(float inX)
{
if (spawnerInformation.getArraySize() > 5)
{
if (spawnerInformation.isXInArray(inX)) // if the exact X was found return
return false;
else
return true;
}
else
return true;
}
float ASpawner::generateNewRandomX()
{
return FMath::RandRange(-270.f, 270.f);
}
float ASpawner::generateTrailX()
{
// Get the last location and the X from that
FVector last;
float lastX = 0.f;
if (spawnerInformation.getArraySize() >= 10)
{
last = spawnerInformation.getLocation((9));
lastX = last.X;
}
else if (spawnerInformation.getArraySize() >= 1)
{
last = spawnerInformation.getLocation((spawnerInformation.getArraySize() - 1));
lastX = last.X;
}
else
lastX = 0.f;
if (lastX <= -260.f || lastX >= 260.f)
{
if (lastX <= -260.f)
lastX = lastX + 50.f;
else if (lastX >= 260.f)
lastX = lastX - 50.f;
}
else
{
int32 rand = FMath::RandRange(0, 1);
if (rand == 0)
lastX = lastX - 40.f;
else
lastX = lastX + 40.f;
}
return lastX;
}
float ASpawner::generateEveryOther()
{
// Get the last location and the X from that
FVector last;
float lastX = 0.f;
if (spawnerInformation.getArraySize() >= 10)
{
last = spawnerInformation.getLocation((9));
lastX = last.X;
}
else if (spawnerInformation.getArraySize() >= 1)
{
last = spawnerInformation.getLocation((spawnerInformation.getArraySize() - 1));
lastX = last.X;
}
else
lastX = 150.f;
if (lastX < 0.f && lastX != 0.f)
lastX = lastX * (-1);
else if (lastX > 0.f && lastX != 0.f)
lastX = lastX * (-1);
else
lastX = 150.f;
return lastX;
}
Nicholas Mallonee