fireworks updated
This commit is contained in:
@ -44,11 +44,19 @@ void GlobalState::shutdown() {
|
|||||||
void GlobalState::updateFireworks(double frameMs) {
|
void GlobalState::updateFireworks(double frameMs) {
|
||||||
const Uint64 currentTime = SDL_GetTicks();
|
const Uint64 currentTime = SDL_GetTicks();
|
||||||
|
|
||||||
// Create new fireworks less frequently for subtle background effect
|
// Check if we have any active fireworks
|
||||||
if (currentTime - lastFireworkTime > 1200 + (rand() % 1800)) { // Less frequent: 1200-3000ms
|
bool hasActiveFirework = false;
|
||||||
// Spawn across wider area for better coverage
|
for (const auto& fw : fireworks) {
|
||||||
float x = Config::Logical::WIDTH * (0.15f + (rand() % 70) / 100.0f); // 15% - 85%
|
if (fw.active) {
|
||||||
float y = Config::Logical::HEIGHT * (0.20f + (rand() % 60) / 100.0f); // 20% - 80%
|
hasActiveFirework = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only create new firework if no active ones exist
|
||||||
|
if (!hasActiveFirework && currentTime - lastFireworkTime > 1500 + (rand() % 2000)) {
|
||||||
|
float x = Config::Logical::WIDTH * (0.15f + (rand() % 70) / 100.0f);
|
||||||
|
float y = Config::Logical::HEIGHT * (0.20f + (rand() % 60) / 100.0f);
|
||||||
createFirework(x, y);
|
createFirework(x, y);
|
||||||
lastFireworkTime = currentTime;
|
lastFireworkTime = currentTime;
|
||||||
}
|
}
|
||||||
@ -58,25 +66,61 @@ void GlobalState::updateFireworks(double frameMs) {
|
|||||||
if (!firework.active) continue;
|
if (!firework.active) continue;
|
||||||
|
|
||||||
bool hasActiveParticles = false;
|
bool hasActiveParticles = false;
|
||||||
|
std::vector<BlockParticle> newParticles;
|
||||||
|
newParticles.reserve(20); // Pre-allocate to avoid reallocation
|
||||||
|
|
||||||
for (auto& particle : firework.particles) {
|
for (auto& particle : firework.particles) {
|
||||||
if (particle.life <= 0) continue;
|
if (particle.life <= 0) continue;
|
||||||
|
|
||||||
// Update physics (gentler gravity, slight friction)
|
// Update physics
|
||||||
float dt = float(frameMs / 1000.0f);
|
float dt = float(frameMs / 1000.0f);
|
||||||
particle.x += particle.vx * dt;
|
particle.x += particle.vx * dt;
|
||||||
particle.y += particle.vy * dt;
|
particle.y += particle.vy * dt;
|
||||||
particle.vx *= (1.0f - 0.5f * dt); // Less friction for longer travel
|
particle.vx *= (1.0f - 0.5f * dt);
|
||||||
particle.vy = particle.vy * (1.0f - 0.2f * dt) + 80.0f * dt; // Gentler gravity
|
particle.vy = particle.vy * (1.0f - 0.2f * dt) + 80.0f * dt;
|
||||||
particle.life -= frameMs;
|
particle.life -= frameMs;
|
||||||
|
|
||||||
// Smaller particles for subtle effect
|
// Update size
|
||||||
float lifeRatio = particle.life / particle.maxLife;
|
float lifeRatio = particle.life / particle.maxLife;
|
||||||
particle.size = 6.0f + 4.0f * lifeRatio; // Smaller particles
|
particle.size = (6.0f - particle.generation * 2.0f) + (4.0f - particle.generation) * lifeRatio;
|
||||||
|
|
||||||
|
// Only primary particles create secondary explosions (single cascade level)
|
||||||
|
if (!particle.hasExploded && particle.generation == 0 && lifeRatio < 0.5f) {
|
||||||
|
particle.hasExploded = true;
|
||||||
|
|
||||||
|
// Spawn only 3-4 secondary particles
|
||||||
|
int secondaryCount = 3 + (rand() % 2);
|
||||||
|
for (int i = 0; i < secondaryCount; ++i) {
|
||||||
|
BlockParticle secondary;
|
||||||
|
secondary.x = particle.x;
|
||||||
|
secondary.y = particle.y;
|
||||||
|
secondary.generation = 1; // Only one level of cascade
|
||||||
|
secondary.hasExploded = true; // Don't cascade further
|
||||||
|
|
||||||
|
float angle = (float)(rand() % 360) * 3.14159f / 180.0f;
|
||||||
|
float speed = 40.0f + (rand() % 40);
|
||||||
|
secondary.vx = cos(angle) * speed;
|
||||||
|
secondary.vy = sin(angle) * speed - 20.0f;
|
||||||
|
|
||||||
|
secondary.type = 1 + (rand() % 7);
|
||||||
|
secondary.maxLife = 700.0f + (rand() % 400);
|
||||||
|
secondary.life = secondary.maxLife;
|
||||||
|
secondary.size = 3.0f + (rand() % 2);
|
||||||
|
|
||||||
|
newParticles.push_back(secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (particle.life > 0) {
|
if (particle.life > 0) {
|
||||||
hasActiveParticles = true;
|
hasActiveParticles = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add secondary particles
|
||||||
|
for (auto& newParticle : newParticles) {
|
||||||
|
firework.particles.push_back(newParticle);
|
||||||
|
hasActiveParticles = true;
|
||||||
|
}
|
||||||
|
|
||||||
firework.active = hasActiveParticles;
|
firework.active = hasActiveParticles;
|
||||||
}
|
}
|
||||||
@ -108,6 +152,8 @@ void GlobalState::createFirework(float x, float y) {
|
|||||||
BlockParticle particle;
|
BlockParticle particle;
|
||||||
particle.x = x;
|
particle.x = x;
|
||||||
particle.y = y;
|
particle.y = y;
|
||||||
|
particle.generation = 0; // Primary explosion
|
||||||
|
particle.hasExploded = false;
|
||||||
|
|
||||||
// Random velocity in all directions
|
// Random velocity in all directions
|
||||||
float angle = (float)(rand() % 360) * 3.14159f / 180.0f;
|
float angle = (float)(rand() % 360) * 3.14159f / 180.0f;
|
||||||
@ -125,7 +171,9 @@ void GlobalState::createFirework(float x, float y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GlobalState::drawFireworks(SDL_Renderer* renderer, SDL_Texture* blocksTex) {
|
void GlobalState::drawFireworks(SDL_Renderer* renderer, SDL_Texture* blocksTex) {
|
||||||
if (!blocksTex) return;
|
(void)blocksTex; // Not using texture anymore
|
||||||
|
|
||||||
|
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||||
|
|
||||||
for (const auto& firework : fireworks) {
|
for (const auto& firework : fireworks) {
|
||||||
if (!firework.active) continue;
|
if (!firework.active) continue;
|
||||||
@ -133,31 +181,44 @@ void GlobalState::drawFireworks(SDL_Renderer* renderer, SDL_Texture* blocksTex)
|
|||||||
for (const auto& particle : firework.particles) {
|
for (const auto& particle : firework.particles) {
|
||||||
if (particle.life <= 0) continue;
|
if (particle.life <= 0) continue;
|
||||||
|
|
||||||
// Calculate alpha based on remaining life - more transparent for subtle effect
|
// Calculate alpha based on remaining life
|
||||||
float lifeRatio = particle.life / particle.maxLife;
|
float lifeRatio = particle.life / particle.maxLife;
|
||||||
// Reduced opacity: 50% of original for subtle background effect
|
|
||||||
Uint8 alpha = (Uint8)(128 * std::min(1.0f, lifeRatio * 1.6f));
|
Uint8 alpha = (Uint8)(128 * std::min(1.0f, lifeRatio * 1.6f));
|
||||||
|
|
||||||
// Set texture alpha
|
// Color based on particle type
|
||||||
SDL_SetTextureAlphaMod(blocksTex, alpha);
|
SDL_Color colors[] = {
|
||||||
SDL_SetTextureBlendMode(blocksTex, SDL_BLENDMODE_BLEND);
|
{0, 240, 240, alpha}, // Cyan
|
||||||
|
{240, 160, 0, alpha}, // Orange
|
||||||
// Draw particle as a small block
|
{0, 0, 240, alpha}, // Blue
|
||||||
SDL_FRect srcRect = {(particle.type - 1) * 90.0f, 0, 90.0f, 90.0f};
|
{240, 240, 0, alpha}, // Yellow
|
||||||
SDL_FRect dstRect = {
|
{0, 240, 0, alpha}, // Green
|
||||||
particle.x - particle.size / 2,
|
{160, 0, 240, alpha}, // Purple
|
||||||
particle.y - particle.size / 2,
|
{240, 0, 0, alpha} // Red
|
||||||
particle.size,
|
|
||||||
particle.size
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SDL_Color color = colors[(particle.type - 1) % 7];
|
||||||
|
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
SDL_RenderTexture(renderer, blocksTex, &srcRect, &dstRect);
|
// For small particles, just draw a filled rect (much faster)
|
||||||
|
if (particle.size <= 4.0f) {
|
||||||
|
SDL_FRect rect{particle.x - particle.size/2, particle.y - particle.size/2, particle.size, particle.size};
|
||||||
|
SDL_RenderFillRect(renderer, &rect);
|
||||||
|
} else {
|
||||||
|
// For larger particles, draw a simple circle approximation
|
||||||
|
float radius = particle.size / 2.0f;
|
||||||
|
int r = (int)radius;
|
||||||
|
for (int dy = -r; dy <= r; ++dy) {
|
||||||
|
int width = (int)sqrt(radius*radius - dy*dy) * 2;
|
||||||
|
if (width > 0) {
|
||||||
|
SDL_FRect line{particle.x - width/2.0f, particle.y + dy, (float)width, 1.0f};
|
||||||
|
SDL_RenderFillRect(renderer, &line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset texture alpha
|
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||||
SDL_SetTextureAlphaMod(blocksTex, 255);
|
|
||||||
SDL_SetTextureBlendMode(blocksTex, SDL_BLENDMODE_BLEND);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalState::resetGameState() {
|
void GlobalState::resetGameState() {
|
||||||
|
|||||||
@ -77,6 +77,8 @@ public:
|
|||||||
int type;
|
int type;
|
||||||
float life, maxLife;
|
float life, maxLife;
|
||||||
float size;
|
float size;
|
||||||
|
int generation = 0; // 0 = primary, 1 = secondary, 2 = tertiary
|
||||||
|
bool hasExploded = false; // Track if this particle has spawned children
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TetrisFirework {
|
struct TetrisFirework {
|
||||||
|
|||||||
Reference in New Issue
Block a user