← index
cplusplus2x.Examples/C++20/random_pixels/main.cpp
Source: cplusplus2x.Examples/C++20/random_pixels/main.cpp
#include "SDL.h"
#include "argz.hpp"
#include <iostream>

void rand_pixels(SDL_Texture *tex, SDL_Surface *surface) {
    SDL_LockTexture(tex, 0, &surface->pixels, &surface->pitch);
    for (unsigned int i = 0; i < surface->w; ++i) {
        for (unsigned int z = 0; z < surface->h; ++z) {
            unsigned int *ptr = reinterpret_cast<unsigned int *>(surface->pixels) + (i + z * surface->w);
            *ptr = SDL_MapRGB(surface->format, rand() % 255, rand() % 255, rand() % 255);
        }
    }
    SDL_UnlockTexture(tex);
}

// RAII + Rule of Five (from Core Guidlines)
// only allow move
class Texture {
  public:
    Texture(SDL_Renderer *renderer, int width, int height) : ren{renderer} {
        tex = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
        if (!tex) {
            std::cerr << "Fatal Error could not create texture....\n";
            SDL_Quit();
            exit(EXIT_FAILURE);
        }
    }
    Texture(const Texture &t) = delete;
    Texture(Texture &&t) : ren{t.ren}, tex{t.tex} {}
    Texture &operator=(const Texture &t) = delete;
    Texture &operator=(Texture &&t) {
        ren = t.ren;
        t.ren = nullptr; // moved value set old to nullptr
        // release old pointer
        if (tex)
            SDL_DestroyTexture(tex);

        tex = t.tex;     // copy pointeirs
        t.tex = nullptr; // moved value
        return *this;
    }
    SDL_Texture *texture() const { return tex; };
    ~Texture() {
        if (tex != nullptr)
            SDL_DestroyTexture(tex);
    }

  protected:
    SDL_Renderer *ren;
    SDL_Texture *tex = nullptr;
};

// RAII - Resource Acquisition is Initialization
// Rule of Five - Core Guidelines
// No Copy/Move
class ScopedSurface {
  public:
    explicit ScopedSurface(SDL_Surface *s) : surf{s} {}
    ~ScopedSurface() {
        if (surf != nullptr) {
            SDL_FreeSurface(surf);
            surf = nullptr;
        }
    }
    ScopedSurface(const ScopedSurface &) = delete;
    ScopedSurface(ScopedSurface &&) = delete;
    ScopedSurface &operator=(const ScopedSurface &) = delete;
    ScopedSurface &operator=(ScopedSurface &&) = delete;
    SDL_Surface *surface() { return surf; }

  protected:
    SDL_Surface *surf = nullptr;
};

int main(int argc, char **argv) {
    int width = 1080, height = 1080;
    try {
        Argz<std::string> args(argc, argv);
        args.addOptionSingleValue('w', "width").addOptionSingleValue('h', "height");
        int value{};
        Argument<std::string> arg;

        while ((value = args.proc(arg)) != -1) {
            switch (value) {
            case 'w':
                width = atoi(arg.arg_value.c_str());
                break;
            case 'h':
                height = atoi(arg.arg_value.c_str());
                break;
            }
        }
    } catch (ArgException<std::string> &e) {
        std::cerr << e.text() << "\n";
    }

    if (width <= 0 || height <= 0) {
        std::cerr << "Invalid width/height";
        return EXIT_FAILURE;
    }

    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        std::cout << SDL_GetError() << "\n";
        return EXIT_FAILURE;
    }
    SDL_Window *window = SDL_CreateWindow("Hello , World!", 0, 0, width, height, SDL_WINDOW_SHOWN);
    SDL_Renderer *ren = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (ren == 0) {
        std::cout << SDL_GetError() << "\n";
        SDL_Quit();
        return EXIT_FAILURE;
    }
    Texture tex(ren, width, height);
    SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(NULL, width, height, 32, 0, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
    ScopedSurface surface1{surface};
    bool active = true;
    SDL_Event e;
    while (active) {
        while (SDL_PollEvent(&e)) {
            switch (e.type) {
            case SDL_KEYDOWN:
                if (e.key.keysym.sym == SDLK_ESCAPE)
                    active = false;
                break;
            case SDL_QUIT:
                active = false;
                break;
            }
        }
        SDL_RenderClear(ren);
        rand_pixels(tex.texture(), surface1.surface());
        SDL_RenderCopy(ren, tex.texture(), 0, 0);
        SDL_RenderPresent(ren);
    }
    SDL_DestroyRenderer(ren);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return EXIT_SUCCESS;
}