Loading and Displaying Images

Efficient Parallax Scrolling

What's the most efficient way to implement parallax scrolling using multiple image layers?

Abstract art representing computer programming

Implementing efficient parallax scrolling with multiple image layers in SDL2 involves carefully managing image rendering and movement. Here's an approach that balances performance and visual quality:

Parallax Layer Class

First, let's create a ParallaxLayer class to manage each layer:

#include <SDL.h>
#include <string>
#include <vector>

class ParallaxLayer {
public:
  ParallaxLayer(SDL_Renderer* renderer,
                const std::string& imagePath,
                float scrollSpeed)
    : ScrollSpeed{scrollSpeed}, Offset{0} {
    SDL_Surface* surface = SDL_LoadBMP(
      imagePath.c_str());
    Texture = SDL_CreateTextureFromSurface(
      renderer, surface);
    SDL_FreeSurface(surface);
    SDL_QueryTexture(Texture, nullptr, nullptr,
                     &Width, &Height);
  }

  void Update(float deltaTime) {
    Offset += ScrollSpeed * deltaTime;
    if (Offset > Width) Offset -= Width;
    if (Offset < 0) Offset += Width;
  }

  void Render(SDL_Renderer* renderer,
              int screenWidth,
              int screenHeight) {
    int x = static_cast<int>(-Offset);
    while (x < screenWidth) {
      SDL_Rect destRect{
        x, 0, Width, screenHeight};
      SDL_RenderCopy(renderer, Texture, nullptr,
                     &destRect);
      x += Width;
    }
  }

  ~ParallaxLayer() {
    SDL_DestroyTexture(Texture);
  }

private:
  SDL_Texture* Texture;
  int Width, Height;
  float ScrollSpeed;
  float Offset;
};

Main Implementation

Now, let's use this class to create a parallax effect:

#include <SDL.h>

#include <chrono>
#include <vector>

int main(int argc, char* argv[]) {
  SDL_Init(SDL_INIT_VIDEO);
  SDL_Window* window =
    SDL_CreateWindow("Parallax Scrolling",
                     SDL_WINDOWPOS_UNDEFINED,
                     SDL_WINDOWPOS_UNDEFINED,
                     800, 600, 0);
  SDL_Renderer* renderer =
    SDL_CreateRenderer(window, -1,
                       SDL_RENDERER_ACCELERATED);

  std::vector<ParallaxLayer> layers;
  layers.emplace_back(renderer,
                      "background.bmp", 10);
  layers.emplace_back(renderer, "midground.bmp",
                      30);
  layers.emplace_back(renderer,
                      "foreground.bmp", 60);

  bool quit = false;
  SDL_Event e;
  auto lastTime =
    std::chrono::high_resolution_clock::now();

  while (!quit) {
    while (SDL_PollEvent(&e) != 0) {
      if (e.type == SDL_QUIT) quit = true;
    }

    auto currentTime =
      std::chrono::high_resolution_clock::now();
    float deltaTime =
      std::chrono::duration<float>(
        currentTime - lastTime).count();
    lastTime = currentTime;

    for (auto& layer : layers) {
      layer.Update(deltaTime);
    }

    SDL_SetRenderDrawColor(renderer, 0, 0, 0,
                           255);
    SDL_RenderClear(renderer);

    for (auto& layer : layers) {
      layer.Render(renderer, 800, 600);
    }

    SDL_RenderPresent(renderer);
  }

  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(window);
  SDL_Quit();
  return 0;
}

This implementation is efficient because:

  1. It uses SDL's hardware-accelerated rendering with SDL_Renderer and SDL_Texture.
  2. Each layer is rendered only twice at most per frame, regardless of scroll speed.
  3. The Update() method uses time-based movement, ensuring smooth scrolling on different devices.

To further optimize:

  • Use spritesheets to reduce texture switches.
  • Implement view culling to skip rendering off-screen layers.
  • For very large backgrounds, consider using tiled maps instead of large images.

Remember, the key to efficient parallax scrolling is minimizing draw calls and texture switches while maintaining the illusion of depth and movement.

Answers to questions are automatically generated and may not have been reviewed.

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 51 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved