Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
OlympeEffectSystem.cpp
Go to the documentation of this file.
1/*
2Olympe Engine V2 - 2025
3Nicolas Chereau
4nchereau@gmail.com
5
6This file is part of Olympe Engine V2.
7
8OlympeEffectSystem: Plasma bloom background effect system
9Autonomous visual effect system (no entity required)
10*/
11
12#include "ECS_Systems.h"
13#include "GameEngine.h"
14#include "DataManager.h"
16#include "drawing.h"
17#include "vector.h"
18#include <SDL3/SDL.h>
19#include <cmath>
20#include <cstdlib>
21
22// Configuration constants
23#define NUM_ORBS 4
24#define BLUR_PASSES 3
25#define ORB_BASE_RADIUS 120.0f
26#define ORB_SPEED_MIN 15.0f
27#define ORB_SPEED_MAX 35.0f
28
29// Mathematical constants
30#ifndef M_PI
31#define M_PI 3.14159265358979323846f
32#endif
33
34// Blur effect constants
35#define BLUR_ALPHA_CENTER 100
36#define BLUR_ALPHA_OFFSET 50
37
38// Bloom effect constants
39#define BLOOM_ALPHA_BLUR 180
40#define BLOOM_ALPHA_PLASMA 120
41#define BLOOM_ALPHA_LOGO 255
42
43// Structure for glowing orbs
54
55//-------------------------------------------------------------
56// Implementation structure (pimpl pattern)
57//-------------------------------------------------------------
96
97//-------------------------------------------------------------
99 : pImpl(new Implementation())
100{
101 // No required signature - autonomous system
102}
103
104//-------------------------------------------------------------
106{
107 // Clean up all textures
108 if (pImpl)
109 {
115 // Don't destroy logoTexture - managed by DataManager
116 delete pImpl;
117 }
118}
119
120//-------------------------------------------------------------
122{
125
126 // Create render target textures
137
138 // Set blend modes
143
144 // Load logo texture
145 pImpl->logoTexture = DataManager::Get().GetSprite("Olympe_Logo", "Resources/olympe_logo.png", ResourceCategory::GameEntity);
146 if (!pImpl->logoTexture)
147 {
148 SYSTEM_LOG << "OlympeEffectSystem: Failed to load logo texture\n";
149 }
150
151 // Initialize orbs with random positions and velocities
152 for (int i = 0; i < NUM_ORBS; ++i)
153 {
154 pImpl->orbs[i].position.x = SDL_randf() * static_cast<float>(pImpl->width);
155 pImpl->orbs[i].position.y = SDL_randf() * static_cast<float>(pImpl->height);
156
157 // Random velocity
158 float speed = ORB_SPEED_MIN + SDL_randf() * (ORB_SPEED_MAX - ORB_SPEED_MIN);
159 float angle = SDL_randf() * 2.0f * M_PI;
160 pImpl->orbs[i].velocity.x = cosf(angle) * speed;
161 pImpl->orbs[i].velocity.y = sinf(angle) * speed;
162
163 // Generate plasma color
165
166 // Pulse parameters
168 pImpl->orbs[i].pulsePhase = SDL_randf() * 2.0f * M_PI;
169 pImpl->orbs[i].pulseSpeed = 0.5f + SDL_randf() * 0.5f; // 0.5-1.0 Hz
170 pImpl->orbs[i].pulseAmplitude = 0.15f + SDL_randf() * 0.10f; // 15-25%
171 }
172
173 SYSTEM_LOG << "OlympeEffectSystem initialized\n";
174}
175
176//-------------------------------------------------------------
178{
179 // Harmonious plasma colors: blue, violet, cyan, pink
181 {60, 100, 255, 255}, // Blue
182 {150, 80, 255, 255}, // Violet
183 {80, 200, 255, 255}, // Cyan
184 {255, 100, 200, 255} // Pink
185 };
186 return colors[index % NUM_ORBS];
187}
188
189//-------------------------------------------------------------
191{
192 for (int i = 0; i < NUM_ORBS; ++i)
193 {
194 GlowOrb& orb = orbs[i];
195
196 // Update position
197 orb.position.x += orb.velocity.x * deltaTime;
198 orb.position.y += orb.velocity.y * deltaTime;
199
200 // Update pulse
201 orb.pulsePhase += orb.pulseSpeed * 2.0f * M_PI * deltaTime;
202 float pulseFactor = 1.0f + orb.pulseAmplitude * sinf(orb.pulsePhase);
204
205 // Bounce off edges
206 BounceOffEdges(orb);
207 }
208}
209
210//-------------------------------------------------------------
212{
213 const float margin = orb.radius;
214
215 // Left/Right edges
216 if (orb.position.x < margin)
217 {
218 orb.position.x = margin;
219 orb.velocity.x = fabsf(orb.velocity.x);
220 }
221 else if (orb.position.x > width - margin)
222 {
223 orb.position.x = width - margin;
224 orb.velocity.x = -fabsf(orb.velocity.x);
225 }
226
227 // Top/Bottom edges
228 if (orb.position.y < margin)
229 {
230 orb.position.y = margin;
231 orb.velocity.y = fabsf(orb.velocity.y);
232 }
233 else if (orb.position.y > height - margin)
234 {
235 orb.position.y = height - margin;
236 orb.velocity.y = -fabsf(orb.velocity.y);
237 }
238}
239
240//-------------------------------------------------------------
242{
243 SDL_SetRenderTarget(GameEngine::renderer, backgroundTexture);
244
245 // Dark gradient background (black → night blue)
246 /* for (int y = 0; y < height; ++y)
247 {
248 float t = static_cast<float>(y) / static_cast<float>(height);
249 Uint8 r = static_cast<Uint8>(0 + t * 10);
250 Uint8 g = static_cast<Uint8>(0 + t * 15);
251 Uint8 b = static_cast<Uint8>(0 + t * 30);
252
253 SDL_SetRenderDrawColor(GameEngine::renderer, r, g, b, 255);
254 SDL_RenderLine(GameEngine::renderer, 0, y, width, y);
255 }/**/
256 SDL_SetRenderDrawColor(GameEngine::renderer, 230, 255, 230, 255);
258
260}
261
262//-------------------------------------------------------------
264{
268
269 // Render each orb as concentric circles with fading alpha
270 for (int i = 0; i < NUM_ORBS; ++i)
271 {
272 const GlowOrb& orb = orbs[i];
273 int cx = static_cast<int>(orb.position.x);
274 int cy = static_cast<int>(orb.position.y);
275
276 // Draw 30 concentric circles with decreasing alpha
277 /*const int numCircles = 4;
278 for (int j = 0; j < numCircles; ++j)
279 {
280 float t = static_cast<float>(j) / static_cast<float>(numCircles - 1);
281 float radiusFactor = 1.0f - t;
282 int currentRadius = static_cast<int>(orb.radius * (1.0f - radiusFactor * radiusFactor));
283
284 // Quadratic falloff for smooth edges
285 float alphaFactor = radiusFactor * radiusFactor;
286 Uint8 alpha = static_cast<Uint8>(180.0f * alphaFactor);
287
288 SDL_SetRenderDrawColor(GameEngine::renderer, orb.color.r, orb.color.g, orb.color.b, alpha);
289 Draw_FilledCircle(GameEngine::renderer, cx, cy, currentRadius);
290 }/**/
291 // debug to disply the circles outline
292
294 Draw_Circle(GameEngine::renderer, cx, cy, (int)orb.radius);
295 }
296
298}
299
300//-------------------------------------------------------------
302{
303 // Multi-pass gaussian blur
304 for (int pass = 0; pass < BLUR_PASSES; ++pass)
305 {
306 int offset = (pass + 1) * 2; // 2, 4, 6 pixels
307
308 // Horizontal blur pass: plasmaTexture → blurTexture1
312
314 SDL_SetTextureAlphaMod(plasmaTexture, BLUR_ALPHA_CENTER); // Center
315 SDL_RenderTexture(GameEngine::renderer, plasmaTexture, nullptr, nullptr);
316
317 SDL_SetTextureAlphaMod(plasmaTexture, BLUR_ALPHA_OFFSET); // Left offset
318 SDL_FRect leftRect = {-static_cast<float>(offset), 0, static_cast<float>(width), static_cast<float>(height)};
319 SDL_RenderTexture(GameEngine::renderer, plasmaTexture, nullptr, &leftRect);
320
321 SDL_SetTextureAlphaMod(plasmaTexture, BLUR_ALPHA_OFFSET); // Right offset
322 SDL_FRect rightRect = {static_cast<float>(offset), 0, static_cast<float>(width), static_cast<float>(height)};
323 SDL_RenderTexture(GameEngine::renderer, plasmaTexture, nullptr, &rightRect);
324
325 // Vertical blur pass: blurTexture1 → blurTexture2
329
331 SDL_SetTextureAlphaMod(blurTexture1, BLUR_ALPHA_CENTER); // Center
332 SDL_RenderTexture(GameEngine::renderer, blurTexture1, nullptr, nullptr);
333
334 SDL_SetTextureAlphaMod(blurTexture1, BLUR_ALPHA_OFFSET); // Top offset
335 SDL_FRect topRect = {0, -static_cast<float>(offset), static_cast<float>(width), static_cast<float>(height)};
336 SDL_RenderTexture(GameEngine::renderer, blurTexture1, nullptr, &topRect);
337
338 SDL_SetTextureAlphaMod(blurTexture1, BLUR_ALPHA_OFFSET); // Bottom offset
339 SDL_FRect bottomRect = {0, static_cast<float>(offset), static_cast<float>(width), static_cast<float>(height)};
340 SDL_RenderTexture(GameEngine::renderer, blurTexture1, nullptr, &bottomRect);
341
342 // Copy back to plasmaTexture for next pass
344 SDL_SetTextureAlphaMod(blurTexture2, 255);
346 SDL_RenderTexture(GameEngine::renderer, blurTexture2, nullptr, nullptr);
347 }
348
350}
351
352//-------------------------------------------------------------
354{
356
357 // Step 1: Draw background (no blending)
359 SDL_RenderTexture(GameEngine::renderer, backgroundTexture, nullptr, nullptr);
360 /*
361 // Step 2: Add blurred glow (additive blending)
362 SDL_SetTextureBlendMode(blurTexture2, SDL_BLENDMODE_ADD);
363 SDL_SetTextureAlphaMod(blurTexture2, BLOOM_ALPHA_BLUR);
364 SDL_RenderTexture(GameEngine::renderer, blurTexture2, nullptr, nullptr);
365
366 // Step 3: Add original plasma orbs (additive blending)
367 SDL_SetTextureBlendMode(plasmaTexture, SDL_BLENDMODE_ADD);
368 SDL_SetTextureAlphaMod(plasmaTexture, BLOOM_ALPHA_PLASMA);
369 SDL_RenderTexture(GameEngine::renderer, plasmaTexture, nullptr, nullptr);
370 /**/
371 // Step 4: Render logo (optional)
372 if (logoTexture)
373 {
376 SDL_FRect logoRect = {(width - 300.0f) / 2.0f, (height - 121.0f) / 2.0f, 300.0f, 121.0f};
377 SDL_RenderTexture(GameEngine::renderer, logoTexture, nullptr, &logoRect);
378 }
379
381}
382
383//-------------------------------------------------------------
385{
386 // Update orbs
388
389 // Render background gradient
391
392 // Render plasma orbs
393 // pImpl->RenderPlasmaOrbs();
394
395 // Apply gaussian blur
396 // pImpl->ApplyGaussianBlur();
397
398 // Compose final bloom effect
399 pImpl->ApplyBloom();
400}
401
402//-------------------------------------------------------------
404{
405 // Get camera offset for rendering using ECS camera system
406 CameraTransform cam = GetActiveCameraTransform(-1); // Get default camera
407 Vector vPos = -cam.worldPosition;
408 SDL_FRect destRect = {vPos.x, vPos.y, static_cast<float>(pImpl->width), static_cast<float>(pImpl->height)};
409
410 // Render the final bloom composite to screen
412}
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
CameraTransform GetActiveCameraTransform(short playerID)
Core game engine class.
#define ORB_BASE_RADIUS
#define BLUR_PASSES
#define ORB_SPEED_MAX
#define BLOOM_ALPHA_LOGO
#define BLUR_ALPHA_CENTER
#define BLUR_ALPHA_OFFSET
#define ORB_SPEED_MIN
#define M_PI
#define NUM_ORBS
static DataManager & Get()
Definition DataManager.h:87
Sprite * GetSprite(const std::string &id, const std::string &path, ResourceCategory category=ResourceCategory::GameEntity)
static int screenWidth
Screen width in pixels.
Definition GameEngine.h:123
static float fDt
Delta time between frames in seconds.
Definition GameEngine.h:120
static int screenHeight
Screen height in pixels.
Definition GameEngine.h:126
static SDL_Renderer * renderer
Main SDL renderer.
Definition GameEngine.h:129
virtual void Process() override
virtual void Render() override
Implementation * pImpl
float y
Definition vector.h:27
float x
Definition vector.h:27
void Draw_Circle(int cx, int cy, int radius)
Definition drawing.cpp:69
SDL_Color color
#define SYSTEM_LOG