cs381/as6/components/SpawnComponent.cpp

94 lines
3.2 KiB
C++

#include "components/SpawnComponent.hpp"
#include "Entities.hpp"
#include "Entity.hpp"
#include "components/CollectibleComponent.hpp"
#include "components/HazardComponent.hpp"
#include "components/NullZoneComponent.hpp"
#include "components/ScrollComponent.hpp"
#include "components/ScrollableComponent.hpp"
#include "components/TransformComponent.hpp"
#include "raylib.h"
#include <algorithm>
void SpawnComponent::Setup() {
// Start a bit beyond the initial handcrafted segment.
cursorWX = 1500.0f;
}
void SpawnComponent::Update(float) {
if (!context || !context->entities) {
return;
}
auto scroll = entity->GetComponent<ScrollComponent>();
if (!scroll) {
return;
}
const float cameraX = scroll->get().scrollX;
const float spawnLimit = cameraX + spawnAheadDistance;
// 70% stars, 20% asteroids, 5% null zones, 5% hazards -> keeps early play mostly collectible
while (cursorWX < spawnLimit) {
const float r = static_cast<float>(GetRandomValue(0, 99));
if (r < 70.0f) {
const float y = static_cast<float>(GetRandomValue(48, GetScreenHeight() - 48));
auto star = CreateStar(cursorWX, y);
star->SetContext(context);
context->entities->push_back(star);
} else if (r < 90.0f) {
const float y = static_cast<float>(GetRandomValue(42, GetScreenHeight() - 42));
auto asteroid = CreateAsteroid(cursorWX, y);
asteroid->SetContext(context);
context->entities->push_back(asteroid);
} else if (r < 95.0f) {
const float width = static_cast<float>(GetRandomValue(70, 140));
auto zone = CreateNullZone(cursorWX, width);
zone->SetContext(context);
context->entities->push_back(zone);
} else {
const float y = static_cast<float>(GetRandomValue(42, GetScreenHeight() - 42));
auto blackHole = CreateBlackHole(cursorWX, y);
blackHole->SetContext(context);
context->entities->push_back(blackHole);
}
const float gap =
static_cast<float>(GetRandomValue(static_cast<int>(minGap), static_cast<int>(maxGap)));
cursorWX += gap;
}
const float cullX = cameraX - despawnBehindDistance;
for (auto &candidate : *context->entities) {
if (!candidate || candidate.get() == entity || candidate->queuedForFree) {
continue;
}
const bool isSpawnedGameplayObject =
candidate->GetComponent<CollectibleComponent>().has_value() ||
candidate->GetComponent<HazardComponent>().has_value() ||
candidate->GetComponent<NullZoneComponent>().has_value();
if (!isSpawnedGameplayObject) {
continue;
}
auto scrollable = candidate->GetComponent<ScrollableComponent>();
if (scrollable) {
if (scrollable->get().worldX < cullX) {
candidate->QueueFree();
}
continue;
}
auto transform = candidate->GetComponent<TransformComponent>();
if (transform && transform->get().x < cullX) {
candidate->QueueFree();
}
}
}
void SpawnComponent::Cleanup() {}