Improve documentation coverage
parent
bf729d4796
commit
2c43dee225
|
|
@ -6,6 +6,7 @@
|
||||||
#include "raylib-cpp.hpp"
|
#include "raylib-cpp.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
// main controllable probe with meter, trail, and projection helpers
|
||||||
std::shared_ptr<Entity> CreateProbe() {
|
std::shared_ptr<Entity> CreateProbe() {
|
||||||
auto e = std::make_shared<Entity>();
|
auto e = std::make_shared<Entity>();
|
||||||
auto &transform = e->AddComponent<TransformComponent>();
|
auto &transform = e->AddComponent<TransformComponent>();
|
||||||
|
|
@ -48,6 +49,7 @@ std::shared_ptr<Entity> CreateProbe() {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// helper controller entity for free cursor-based well placement
|
||||||
std::shared_ptr<Entity> CreateGravityWell() {
|
std::shared_ptr<Entity> CreateGravityWell() {
|
||||||
auto e = std::make_shared<Entity>();
|
auto e = std::make_shared<Entity>();
|
||||||
auto &transform = e->AddComponent<TransformComponent>();
|
auto &transform = e->AddComponent<TransformComponent>();
|
||||||
|
|
@ -60,6 +62,7 @@ std::shared_ptr<Entity> CreateGravityWell() {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// permanent hazard black hole that serves as a heavy obstacle
|
||||||
std::shared_ptr<Entity> CreateBlackHole(float x, float y) {
|
std::shared_ptr<Entity> CreateBlackHole(float x, float y) {
|
||||||
auto e = std::make_shared<Entity>();
|
auto e = std::make_shared<Entity>();
|
||||||
auto &transform = e->AddComponent<TransformComponent>();
|
auto &transform = e->AddComponent<TransformComponent>();
|
||||||
|
|
@ -70,6 +73,7 @@ std::shared_ptr<Entity> CreateBlackHole(float x, float y) {
|
||||||
scrollable.worldX = x;
|
scrollable.worldX = x;
|
||||||
|
|
||||||
auto &well = e->AddComponent<GravityWellComponent>();
|
auto &well = e->AddComponent<GravityWellComponent>();
|
||||||
|
// oversized static hazard that always pulls with high mass so the probe has to dodge it
|
||||||
well.mass = static_cast<float>(1 << 21);
|
well.mass = static_cast<float>(1 << 21);
|
||||||
well.minDist = 24.0f;
|
well.minDist = 24.0f;
|
||||||
well.controlledByMouse = false;
|
well.controlledByMouse = false;
|
||||||
|
|
@ -100,6 +104,7 @@ std::shared_ptr<Entity> CreateBlackHole(float x, float y) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// player-placed well that expires after ttl and can be cleared via right click
|
||||||
std::shared_ptr<Entity> CreatePlayerBlackHole(float worldX, float y, float scrollX, float ttl) {
|
std::shared_ptr<Entity> CreatePlayerBlackHole(float worldX, float y, float scrollX, float ttl) {
|
||||||
auto e = std::make_shared<Entity>();
|
auto e = std::make_shared<Entity>();
|
||||||
auto &transform = e->AddComponent<TransformComponent>();
|
auto &transform = e->AddComponent<TransformComponent>();
|
||||||
|
|
@ -110,6 +115,7 @@ std::shared_ptr<Entity> CreatePlayerBlackHole(float worldX, float y, float scrol
|
||||||
scrollable.worldX = worldX;
|
scrollable.worldX = worldX;
|
||||||
|
|
||||||
auto &well = e->AddComponent<GravityWellComponent>();
|
auto &well = e->AddComponent<GravityWellComponent>();
|
||||||
|
// temporary player-placed well that drains meter and lasts exactly ttl seconds
|
||||||
well.mass = static_cast<float>(1 << 22);
|
well.mass = static_cast<float>(1 << 22);
|
||||||
well.minDist = 28.0f;
|
well.minDist = 28.0f;
|
||||||
well.controlledByMouse = false;
|
well.controlledByMouse = false;
|
||||||
|
|
@ -147,6 +153,7 @@ std::shared_ptr<Entity> CreatePlayerBlackHole(float worldX, float y, float scrol
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// collectible star that restores meter and counts toward score
|
||||||
std::shared_ptr<Entity> CreateStar(float x, float y) {
|
std::shared_ptr<Entity> CreateStar(float x, float y) {
|
||||||
auto e = std::make_shared<Entity>();
|
auto e = std::make_shared<Entity>();
|
||||||
auto &t = e->AddComponent<TransformComponent>();
|
auto &t = e->AddComponent<TransformComponent>();
|
||||||
|
|
@ -174,6 +181,7 @@ std::shared_ptr<Entity> CreateStar(float x, float y) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// small hazard that nudges the player when hit
|
||||||
std::shared_ptr<Entity> CreateAsteroid(float x, float y) {
|
std::shared_ptr<Entity> CreateAsteroid(float x, float y) {
|
||||||
auto e = std::make_shared<Entity>();
|
auto e = std::make_shared<Entity>();
|
||||||
auto &t = e->AddComponent<TransformComponent>();
|
auto &t = e->AddComponent<TransformComponent>();
|
||||||
|
|
@ -198,6 +206,7 @@ std::shared_ptr<Entity> CreateAsteroid(float x, float y) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// visual debris after collecting stars to reinforce feedback
|
||||||
std::shared_ptr<Entity> CreateDebris(float x, float y, float vx, float vy, float ttl) {
|
std::shared_ptr<Entity> CreateDebris(float x, float y, float vx, float vy, float ttl) {
|
||||||
auto e = std::make_shared<Entity>();
|
auto e = std::make_shared<Entity>();
|
||||||
auto &t = e->AddComponent<TransformComponent>();
|
auto &t = e->AddComponent<TransformComponent>();
|
||||||
|
|
@ -225,6 +234,7 @@ std::shared_ptr<Entity> CreateDebris(float x, float y, float vx, float vy, float
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// null zone that strips gravity and forces the player to avoid it
|
||||||
std::shared_ptr<Entity> CreateNullZone(float x, float width) {
|
std::shared_ptr<Entity> CreateNullZone(float x, float width) {
|
||||||
auto e = std::make_shared<Entity>();
|
auto e = std::make_shared<Entity>();
|
||||||
auto &t = e->AddComponent<TransformComponent>();
|
auto &t = e->AddComponent<TransformComponent>();
|
||||||
|
|
@ -251,6 +261,7 @@ std::shared_ptr<Entity> CreateNullZone(float x, float width) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// world entity that owns scrolling and spawn logic
|
||||||
std::shared_ptr<Entity> CreateWorld() {
|
std::shared_ptr<Entity> CreateWorld() {
|
||||||
auto e = std::make_shared<Entity>();
|
auto e = std::make_shared<Entity>();
|
||||||
e->AddComponent<ScrollComponent>();
|
e->AddComponent<ScrollComponent>();
|
||||||
|
|
@ -258,6 +269,7 @@ std::shared_ptr<Entity> CreateWorld() {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hud/stat tracker that shows meter and plays sounds
|
||||||
std::shared_ptr<Entity> CreateStats() {
|
std::shared_ptr<Entity> CreateStats() {
|
||||||
auto e = std::make_shared<Entity>();
|
auto e = std::make_shared<Entity>();
|
||||||
e->AddComponent<StatsComponent>();
|
e->AddComponent<StatsComponent>();
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ void CollectibleComponent::Setup() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// probe knock collecting stars is how meter value climbs and provides audiovisual feedback
|
||||||
context->EmitCollectiblePicked(*entity);
|
context->EmitCollectiblePicked(*entity);
|
||||||
entity->QueueFree();
|
entity->QueueFree();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ void ColliderComponent::Update(float) {
|
||||||
const float dy = selfTransform->get().y - otherTransform->get().y;
|
const float dy = selfTransform->get().y - otherTransform->get().y;
|
||||||
const float r = radius + otherCollider->get().radius;
|
const float r = radius + otherCollider->get().radius;
|
||||||
if ((dx * dx + dy * dy) <= (r * r)) {
|
if ((dx * dx + dy * dy) <= (r * r)) {
|
||||||
|
// collision emitted per frame keeps gameplay reactive without physics bodies
|
||||||
EmitCollision(*other);
|
EmitCollision(*other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ void GravityReceiverComponent::Update(float dt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inVoid) {
|
if (inVoid) {
|
||||||
|
// inside a null zone, the probe floats freely until it exits
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ void GravityWellComponent::Update(float) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right click removes all player-created black holes
|
// right click removes all player-created black holes so the player can clear the screen quickly
|
||||||
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) {
|
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) {
|
||||||
for (auto &ent : *context->entities) {
|
for (auto &ent : *context->entities) {
|
||||||
if (!ent || ent->queuedForFree) {
|
if (!ent || ent->queuedForFree) {
|
||||||
|
|
@ -36,6 +36,7 @@ void GravityWellComponent::Update(float) {
|
||||||
// Do not early return; allow left-click placement to still happen in the same frame
|
// Do not early return; allow left-click placement to still happen in the same frame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only spawn a new black hole when the player has enough meter and pressed left
|
||||||
if (!IsMouseButtonPressed(MOUSE_BUTTON_LEFT) || !context->statsEntity) {
|
if (!IsMouseButtonPressed(MOUSE_BUTTON_LEFT) || !context->statsEntity) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ void HazardComponent::Setup() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hazards instantly end the run by calling the death callback
|
||||||
if (context->onPlayerDeath) {
|
if (context->onPlayerDeath) {
|
||||||
context->onPlayerDeath();
|
context->onPlayerDeath();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ void LifetimeComponent::Setup() {}
|
||||||
void LifetimeComponent::Update(float dt) {
|
void LifetimeComponent::Update(float dt) {
|
||||||
remaining -= dt;
|
remaining -= dt;
|
||||||
if (remaining <= 0.0f) {
|
if (remaining <= 0.0f) {
|
||||||
|
// helper component that simply removes itself when the ttl expires
|
||||||
entity->QueueFree();
|
entity->QueueFree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ bool PhysicsComponent::IsInsideNullZone(double xPos) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// looks weird because of formatter
|
||||||
bool PhysicsComponent::ComputeGravityDeltaVelocity(double px, double py, double dt, double &dvx,
|
bool PhysicsComponent::ComputeGravityDeltaVelocity(double px, double py, double dt, double &dvx,
|
||||||
double &dvy, bool ignoreWellActive) const {
|
double &dvy, bool ignoreWellActive) const {
|
||||||
dvx = 0.0;
|
dvx = 0.0;
|
||||||
|
|
@ -80,11 +81,13 @@ bool PhysicsComponent::ComputeGravityDeltaVelocity(double px, double py, double
|
||||||
if (context && entity == context->probeEntity && context->statsEntity) {
|
if (context && entity == context->probeEntity && context->statsEntity) {
|
||||||
auto stats = context->statsEntity->GetComponent<StatsComponent>();
|
auto stats = context->statsEntity->GetComponent<StatsComponent>();
|
||||||
if (stats && stats->get().value <= 0.0f) {
|
if (stats && stats->get().value <= 0.0f) {
|
||||||
|
// meter drained, block gravity from anything that isn't always active
|
||||||
probeMeterDepleted = true;
|
probeMeterDepleted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsInsideNullZone(px)) {
|
if (IsInsideNullZone(px)) {
|
||||||
|
// null zone overrides gravity, so the probe/globally simulated object stops feeling wells
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,6 +118,7 @@ bool PhysicsComponent::ComputeGravityDeltaVelocity(double px, double py, double
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// guard against infinite force by respecting the well's minimum distance
|
||||||
const double clampedDist = std::max(dist, static_cast<double>(wellGravity->get().minDist));
|
const double clampedDist = std::max(dist, static_cast<double>(wellGravity->get().minDist));
|
||||||
const double force =
|
const double force =
|
||||||
static_cast<double>(wellGravity->get().mass) / (clampedDist * clampedDist);
|
static_cast<double>(wellGravity->get().mass) / (clampedDist * clampedDist);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ void ProbeStateComponent::Update(float) {
|
||||||
transform->get().x < -20.0f ||
|
transform->get().x < -20.0f ||
|
||||||
transform->get().x > static_cast<float>(GetScreenWidth() + 20)) {
|
transform->get().x > static_cast<float>(GetScreenWidth() + 20)) {
|
||||||
if (context->onPlayerDeath) {
|
if (context->onPlayerDeath) {
|
||||||
|
// leaving the viewport is treated as death to keep the probe bounded
|
||||||
context->onPlayerDeath();
|
context->onPlayerDeath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ void ProjectionComponent::Update(float) {
|
||||||
|
|
||||||
auto wellGravity = other->GetComponent<GravityWellComponent>();
|
auto wellGravity = other->GetComponent<GravityWellComponent>();
|
||||||
if (wellGravity && wellGravity->get().active) {
|
if (wellGravity && wellGravity->get().active) {
|
||||||
|
// highlight arc when another well is active so the player knows the projection is
|
||||||
|
// influenced
|
||||||
highlightActive = true;
|
highlightActive = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -84,6 +86,8 @@ void ProjectionComponent::Update(float) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// storing each simulated position gives the hud the full trajectory so the player can line
|
||||||
|
// up placements
|
||||||
points.push_back({static_cast<float>(px), static_cast<float>(py)});
|
points.push_back({static_cast<float>(px), static_cast<float>(py)});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ void ScrollComponent::Update(float dt) {
|
||||||
speed += accel * dt;
|
speed += accel * dt;
|
||||||
scrollX += speed * dt * 60.0f;
|
scrollX += speed * dt * 60.0f;
|
||||||
if (context) {
|
if (context) {
|
||||||
|
// stores our current scroll speed for components that rely on the camera position
|
||||||
context->scrollX = scrollX;
|
context->scrollX = scrollX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ void ScrollableComponent::Update(float) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// keeps the drawable aligned with the camera by subtracting the global scroll offset
|
||||||
transform->get().x = worldX - context->scrollX;
|
transform->get().x = worldX - context->scrollX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ void SpawnComponent::Update(float) {
|
||||||
const float cameraX = scroll->get().scrollX;
|
const float cameraX = scroll->get().scrollX;
|
||||||
const float spawnLimit = cameraX + spawnAheadDistance;
|
const float spawnLimit = cameraX + spawnAheadDistance;
|
||||||
|
|
||||||
|
// 70% stars, 20% asteroids, 5% null zones, 5% hazards -> keeps early play mostly collectible
|
||||||
while (cursorWX < spawnLimit) {
|
while (cursorWX < spawnLimit) {
|
||||||
const float r = static_cast<float>(GetRandomValue(0, 99));
|
const float r = static_cast<float>(GetRandomValue(0, 99));
|
||||||
if (r < 70.0f) {
|
if (r < 70.0f) {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ void StatsComponent::SetValue(float newValue) {
|
||||||
const float oldValue = value;
|
const float oldValue = value;
|
||||||
value = newValue;
|
value = newValue;
|
||||||
if (context && oldValue != value) {
|
if (context && oldValue != value) {
|
||||||
|
// notify listeners so the hud and gravity meter stay in sync with the updated value
|
||||||
context->EmitMeterChanged(oldValue, value);
|
context->EmitMeterChanged(oldValue, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,7 @@ void GameplayScene::Enter() {
|
||||||
meterValue = 60.0f;
|
meterValue = 60.0f;
|
||||||
|
|
||||||
context.onPlayerDeath = [this]() {
|
context.onPlayerDeath = [this]() {
|
||||||
// Inject the collected star count into the queued DeathScene by passing it
|
// queue the death scene with the current star count so the recap is accurate
|
||||||
// as a constructor argument. SceneManager::QueueSceneChange supports
|
|
||||||
// forwarding constructor args.
|
|
||||||
manager.QueueSceneChange<DeathScene>(collectedCount, this->isMuted);
|
manager.QueueSceneChange<DeathScene>(collectedCount, this->isMuted);
|
||||||
};
|
};
|
||||||
context.AddCollectiblePickedListener([this](Entity &collectible) {
|
context.AddCollectiblePickedListener([this](Entity &collectible) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue