Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
ParallaxLayerManager.cpp
Go to the documentation of this file.
1/*
2 * ParallaxLayerManager.cpp - Parallax layer management
3 */
4
5#include "../include/ParallaxLayerManager.h"
6#include "../../ECS_Systems.h"
7#include "../../GameEngine.h"
8#include <SDL3/SDL.h>
9#include <algorithm>
10#include <cmath>
11
12namespace Olympe {
13namespace Tiled {
14
15
19
21 {
22 // Clean up textures
23 for (auto& layer : layers_)
24 {
25 if (layer.texture)
26 {
27 SDL_DestroyTexture(layer.texture);
28 layer.texture = nullptr;
29 }
30 }
31 }
32
38
40 {
41 layers_.push_back(layer);
42 }
43
45 {
46 // Clean up textures
47 for (auto& layer : layers_)
48 {
49 if (layer.texture)
50 {
51 SDL_DestroyTexture(layer.texture);
52 layer.texture = nullptr;
53 }
54 }
55 layers_.clear();
56 }
57
59 const ParallaxLayer& layer,
60 float cameraX, float cameraY,
61 float zoom,
62 float& outX, float& outY) const
63 {
64 // Calculate position based on parallax scroll factors
65 // A scroll factor of 0.0 means the layer doesn't move (distant background)
66 // A scroll factor of 1.0 means the layer moves with the camera (normal)
67 // A scroll factor > 1.0 means the layer moves faster (foreground)
68
69 // Calculate world position of the layer (applying parallax factor)
70 float worldX = layer.offsetX - (cameraX * layer.scrollFactorX);
71 float worldY = layer.offsetY - (cameraY * layer.scrollFactorY);
72
73 // Apply zoom to the relative position (consistent with entity rendering)
74 outX = worldX * zoom;
75 outY = worldY * zoom;
76 }
77
79 {
80 if (index >= layers_.size()) {
81 return nullptr;
82 }
83 return &layers_[index];
84 }
85
87 {
88 if (!layer.visible || !layer.texture) return;
89
91 if (!renderer) return;
92
93 float texW, texH;
95
96 // Calculate parallax-adjusted world position
97 float worldX = layer.offsetX - (cam.worldPosition.x * layer.scrollFactorX);
98 float worldY = layer.offsetY - (cam.worldPosition.y * layer.scrollFactorY);
99
100 // Calculate screen position with zoom only (no rotation)
101 // Rotation is applied separately via SDL_RenderTextureRotated with viewport-centered pivot
102 float screenX = worldX * cam.zoom - cam.screenOffset.x + cam.viewport.w / 2.0f;
103 float screenY = worldY * cam.zoom - cam.screenOffset.y + cam.viewport.h / 2.0f;
104
105 // Apply zoom to dimensions
106 texW *= cam.zoom;
107 texH *= cam.zoom;
108
109 SDL_SetTextureAlphaMod(layer.texture, static_cast<Uint8>(layer.opacity * 255));
110
111 int screenW = (int)cam.viewport.w;
112 int screenH = (int)cam.viewport.h;
113
114 if (layer.repeatX || layer.repeatY)
115 {
116 // Tiled rendering with zoom-aware calculations
117 float tileOffsetX = layer.repeatX ? fmod(screenX, texW) : screenX;
118 float tileOffsetY = layer.repeatY ? fmod(screenY, texH) : screenY;
119
120 // Adjust for negative values
121 if (tileOffsetX > 0) tileOffsetX -= texW;
122 if (tileOffsetY > 0) tileOffsetY -= texH;
123
124 // Calculate number of tiles needed (using zoomed dimensions)
125 int tilesX = layer.repeatX ? (int)ceil(screenW / texW) + 2 : 1;
126 int tilesY = layer.repeatY ? (int)ceil(screenH / texH) + 2 : 1;
127
128 // Render each tile WITH rotation around viewport center
129 for (int tileY = 0; tileY < tilesY; ++tileY)
130 {
131 for (int tileX = 0; tileX < tilesX; ++tileX)
132 {
134 tileOffsetX + tileX * texW,
135 tileOffsetY + tileY * texH,
136 texW,
137 texH
138 };
139
140 // Pivot = viewport center in tile's coordinate space
141 // This makes the tile rotate around the camera center (not its own center)
143 cam.viewport.w / 2.0f - destRect.x,
144 cam.viewport.h / 2.0f - destRect.y
145 };
146
149 }
150 }
151 }
152 else
153 {
154 // Single image with zoom
156
157 // Rotate around viewport center
159 cam.viewport.w / 2.0f - destRect.x,
160 cam.viewport.h / 2.0f - destRect.y
161 };
162
165 }
166 }
167
169 {
170 // Create a sorted copy of layers by z-order
172 sortedLayers.reserve(layers_.size());
173
174 for (const auto& layer : layers_)
175 {
176 sortedLayers.push_back(&layer);
177 }
178
179 // Sort by z-order (back to front)
180 sort(sortedLayers.begin(), sortedLayers.end(),
181 [](const ParallaxLayer* a, const ParallaxLayer* b) {
182 return a->zOrder < b->zOrder;
183 });
184
185 // Render in sorted order
186 for (const auto* layer : sortedLayers)
187 {
188 RenderLayer(*layer, cam);
189 }
190 }
191
192} // namespace Tiled
193} // namespace Olympe
RenderLayer
Render layer enumeration for Z-ordering.
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
static SDL_Renderer * renderer
static SDL_Renderer * renderer
Main SDL renderer.
Definition GameEngine.h:129
const ParallaxLayer * GetLayer(size_t index) const
void AddLayer(const ParallaxLayer &layer)
void RenderAllLayers(const CameraTransform &cam) const
void RenderLayer(const ParallaxLayer &layer, const CameraTransform &cam) const
static ParallaxLayerManager & Get()
void CalculateRenderPosition(const ParallaxLayer &layer, float cameraX, float cameraY, float zoom, float &outX, float &outY) const