Fading Rectangle Color on Hover in SDL2
What if I want the rectangle's color to change gradually when hovered (fade)?
Creating a gradual fade effect instead of an instant color change requires managing the transition over time. The current code jumps directly between Color
and HoverColor
based on the isPointerHovering
state. Fading involves calculating intermediate colors between these two states.
Core Concept: Interpolation
The key technique is linear interpolation (often shortened to "lerp"). Lerping allows you to find a value partway between a starting value and an ending value, based on a progress factor (usually a float t
ranging from 0.0 to 1.0).
The formula for lerp is:
interpolatedValue = startValue + (endValue - startValue) * t
- If
t
is 0.0, the result isstartValue
. - If
t
is 1.0, the result isendValue
. - If
t
is 0.5, the result is halfway betweenstartValue
andendValue
.
We need to apply this formula to each color channel (Red, Green, Blue) independently.
Implementing the Fade
Add State for Fade Progress: The Rectangle
class needs a member variable to track the current progress of the fade, typically a float. Let's call it hoverFadeProgress
, ranging from 0.0 (fully normal color) to 1.0 (fully hover color).
// Rectangle.h
// ...
private:
// ... existing members ...
SDL_Color Color{255, 0, 0};
SDL_Color HoverColor{0, 0, 255};
bool isPointerHovering{false};
float hoverFadeProgress{0.0f}; // Add this
Add an Update()
Method: The fade needs to progress over time. This typically happens in an Update()
method that gets called each frame, often receiving the time elapsed since the last frame (deltaTime
) for smooth, frame-rate-independent animation.
// Rectangle.h
// ...
public:
// ... existing methods ...
void Update(float deltaTime) {
const float fadeSpeed{4.0f}; // Adjust speed as needed
if (isPointerHovering) {
// Fade towards hover color (increase progress)
hoverFadeProgress += fadeSpeed * deltaTime;
if (hoverFadeProgress > 1.0f) {
hoverFadeProgress = 1.0f;
}
} else {
// Fade towards normal color (decrease progress)
hoverFadeProgress -= fadeSpeed * deltaTime;
if (hoverFadeProgress < 0.0f) {
hoverFadeProgress = 0.0f;
}
}
}
// ...
You would need to call Rect.Update(deltaTime)
in your main loop, which requires calculating deltaTime
(a more advanced topic involving timing).
We cover Update()
methods (sometimes also called Tick()
methods) and timing in detail later in the course.
Modify Render()
to Interpolate: Instead of instantly choosing Color
or HoverColor
, the Render()
function now calculates the intermediate color based on hoverFadeProgress
.
// Rectangle.h
// ...
// Helper function for lerping unsigned chars (like color channels)
Uint8 LerpColorChannel(Uint8 start, Uint8 end, float t) {
// Perform calculation in float, then cast back
return static_cast<Uint8>(
static_cast<float>(start) +
(static_cast<float>(end) - static_cast<float>(start)) * t
);
}
void Render(SDL_Surface* Surface) const {
// Interpolate each channel based on progress
Uint8 r = LerpColorChannel(
Color.r, HoverColor.r, hoverFadeProgress);
Uint8 g = LerpColorChannel(
Color.g, HoverColor.g, hoverFadeProgress);
Uint8 b = LerpColorChannel(
Color.b, HoverColor.b, hoverFadeProgress);
// Use the interpolated color
SDL_FillRect(
Surface, &Rect,
SDL_MapRGB(Surface->format, r, g, b)
);
}
// ...
Considerations
- Timing (
deltaTime
): Implementing a smooth, frame-rate-independent fade requires calculating the time elapsed between frames (deltaTime
). This involves using SDL timing functions likeSDL_GetTicks()
orSDL_GetPerformanceCounter()
. - Complexity: As you can see, adding smooth fading significantly increases the complexity compared to an instant switch. It requires managing state (
hoverFadeProgress
) and adding time-based update logic. - Easing Functions: For more visually appealing transitions than simple linear interpolation, you can explore "easing functions" which modify the
hoverFadeProgress
value non-linearly (e.g., ease-in, ease-out).
While this provides the structure, a fully working implementation requires integrating the Update()
call and deltaTime
calculation into your main loop.
Rectangles and SDL_Rect
Learn to create, render, and interact with basic rectangles using the SDL_Rect
and SDL_Color
types.