latest state

This commit is contained in:
2025-12-06 09:43:33 +01:00
parent 294e935344
commit b44de25113
19 changed files with 2451 additions and 524 deletions

View File

@ -20,6 +20,8 @@ void SpaceWarp::init(int w, int h, int starCount) {
for (auto& star : stars) {
respawn(star, true);
}
comets.clear();
cometSpawnTimer = randomRange(settings.cometSpawnIntervalMin, settings.cometSpawnIntervalMax);
}
void SpaceWarp::resize(int w, int h) {
@ -33,6 +35,7 @@ void SpaceWarp::resize(int w, int h) {
void SpaceWarp::setSettings(const SpaceWarpSettings& newSettings) {
settings = newSettings;
warpFactor = std::max(width, height) * settings.warpFactorScale;
cometSpawnTimer = std::clamp(cometSpawnTimer, settings.cometSpawnIntervalMin, settings.cometSpawnIntervalMax);
}
void SpaceWarp::setFlightMode(SpaceWarpFlightMode mode) {
@ -69,6 +72,7 @@ void SpaceWarp::setAutoPilotEnabled(bool enabled) {
flightMode = SpaceWarpFlightMode::Custom;
motionTarget = motion;
autoTimer = 0.0f;
scheduleNewAutoTarget();
}
}
@ -82,6 +86,32 @@ void SpaceWarp::scheduleNewAutoTarget() {
autoTimer = randomRange(autoMinInterval, autoMaxInterval);
}
void SpaceWarp::spawnComet() {
WarpComet comet;
float aspect = static_cast<float>(width) / static_cast<float>(std::max(1, height));
float normalizedAspect = std::max(aspect, MIN_ASPECT);
float xRange = settings.baseSpawnRange * 1.2f * (aspect >= 1.0f ? aspect : 1.0f);
float yRange = settings.baseSpawnRange * 1.2f * (aspect >= 1.0f ? 1.0f : (1.0f / normalizedAspect));
comet.x = randomRange(-xRange, xRange);
comet.y = randomRange(-yRange, yRange);
comet.z = randomRange(minDepth + 4.0f, maxDepth);
float baseSpeed = randomRange(settings.minSpeed, settings.maxSpeed);
float multiplier = randomRange(settings.cometSpeedMultiplierMin, settings.cometSpeedMultiplierMax);
comet.speed = baseSpeed * multiplier;
comet.size = randomRange(settings.cometMinSize, settings.cometMaxSize);
comet.trailLength = randomRange(settings.cometMinTrail, settings.cometMaxTrail);
comet.life = randomRange(1.8f, 3.4f);
comet.maxLife = comet.life;
float shade = randomRange(0.85f, 1.0f);
Uint8 c = static_cast<Uint8>(std::clamp(220.0f + shade * 35.0f, 0.0f, 255.0f));
comet.color = SDL_Color{c, Uint8(std::min(255.0f, c * 0.95f)), 255, 255};
comet.prevScreenX = centerX;
comet.prevScreenY = centerY;
comet.screenX = centerX;
comet.screenY = centerY;
comets.push_back(comet);
}
float SpaceWarp::randomRange(float min, float max) {
std::uniform_real_distribution<float> dist(min, max);
return dist(rng);
@ -112,12 +142,16 @@ void SpaceWarp::respawn(WarpStar& star, bool randomDepth) {
}
bool SpaceWarp::project(const WarpStar& star, float& outX, float& outY) const {
if (star.z <= minDepth) {
return projectPoint(star.x, star.y, star.z, outX, outY);
}
bool SpaceWarp::projectPoint(float x, float y, float z, float& outX, float& outY) const {
if (z <= minDepth) {
return false;
}
float perspective = warpFactor / (star.z + 0.001f);
outX = centerX + star.x * perspective;
outY = centerY + star.y * perspective;
float perspective = warpFactor / (z + 0.001f);
outX = centerX + x * perspective;
outY = centerY + y * perspective;
const float margin = settings.spawnMargin;
return outX >= -margin && outX <= width + margin && outY >= -margin && outY <= height + margin;
}
@ -127,6 +161,14 @@ void SpaceWarp::update(float deltaSeconds) {
return;
}
if (settings.cometSpawnIntervalMax > 0.0f) {
cometSpawnTimer -= deltaSeconds;
if (cometSpawnTimer <= 0.0f) {
spawnComet();
cometSpawnTimer = randomRange(settings.cometSpawnIntervalMin, settings.cometSpawnIntervalMax);
}
}
if (autoPilotEnabled) {
autoTimer -= deltaSeconds;
if (autoTimer <= 0.0f) {
@ -188,6 +230,51 @@ void SpaceWarp::update(float deltaSeconds) {
star.prevScreenY = star.screenY - dy * scale;
}
}
for (auto it = comets.begin(); it != comets.end();) {
auto& comet = *it;
comet.life -= deltaSeconds;
comet.z -= comet.speed * deltaSeconds * forwardScale;
bool expired = comet.life <= 0.0f;
if (!movingBackward) {
if (comet.z <= minDepth * 0.35f) expired = true;
} else {
if (comet.z >= maxDepth + 40.0f) expired = true;
}
float closeness = 1.0f - std::clamp(comet.z / maxDepth, 0.0f, 1.0f);
float driftScale = (0.45f + closeness * 1.6f);
comet.x += lateralSpeed * deltaSeconds * driftScale;
comet.y += verticalSpeed * deltaSeconds * driftScale;
float sx = 0.0f;
float sy = 0.0f;
if (!projectPoint(comet.x, comet.y, comet.z, sx, sy)) {
expired = true;
} else {
comet.prevScreenX = comet.screenX;
comet.prevScreenY = comet.screenY;
comet.screenX = sx;
comet.screenY = sy;
float dx = comet.screenX - comet.prevScreenX;
float dy = comet.screenY - comet.prevScreenY;
float lenSq = dx * dx + dy * dy;
float maxTrail = std::max(comet.trailLength, 0.0f);
if (maxTrail > 0.0f && lenSq > maxTrail * maxTrail) {
float len = std::sqrt(lenSq);
float scale = maxTrail / len;
comet.prevScreenX = comet.screenX - dx * scale;
comet.prevScreenY = comet.screenY - dy * scale;
}
}
if (expired) {
it = comets.erase(it);
} else {
++it;
}
}
}
void SpaceWarp::draw(SDL_Renderer* renderer, float alphaScale) {
@ -224,5 +311,16 @@ void SpaceWarp::draw(SDL_Renderer* renderer, float alphaScale) {
SDL_RenderFillRect(renderer, &dot);
}
for (const auto& comet : comets) {
float lifeNorm = std::clamp(comet.life / comet.maxLife, 0.0f, 1.0f);
Uint8 alpha = static_cast<Uint8>(std::clamp(220.0f * lifeNorm, 0.0f, 255.0f));
SDL_SetRenderDrawColor(renderer, comet.color.r, comet.color.g, comet.color.b, alpha);
SDL_RenderLine(renderer, comet.prevScreenX, comet.prevScreenY, comet.screenX, comet.screenY);
float size = comet.size * (0.8f + (1.0f - lifeNorm) * 0.6f);
SDL_FRect head{comet.screenX - size * 0.5f, comet.screenY - size * 0.5f, size, size};
SDL_RenderFillRect(renderer, &head);
}
SDL_SetRenderDrawBlendMode(renderer, previous);
}