sdl2 – Delta Time FPS with SDL 2 in C++

I have tried achieving a good delta time and fps counter over the last few days, read and watched a lot about it, but still can’t seem to get it to work.

Here is an example:

#include <iostream>
#include <SDL.h>
#include <SDL_image.h>

int main(int argc, char* argv()) {

    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("error initializing SDL: %sn", SDL_GetError());
    }

    SDL_Window* window = SDL_CreateWindow("Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 900, SDL_WINDOW_SHOWN);

    if (!window) {
        printf("error creating window: %sn", SDL_GetError());
    }

    Uint32 renderFlags = SDL_RENDERER_ACCELERATED;
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, renderFlags);
    if (!renderer) {
        printf("error creating renderer");
        SDL_DestroyWindow(window);
        SDL_Quit();
    }

    SDL_Surface* surface = IMG_Load("dot.bmp");

    if (!surface) {
        printf("Error creating surface: %sn", SDL_GetError());
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
        SDL_Quit();
    }

    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
    SDL_FreeSurface(surface);
    if (!texture) {
        printf("error creating texture: %sn", SDL_GetError());
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
        SDL_Quit();
    }

    SDL_Rect dest;

    dest.x = 0;
    dest.y = 0;

    SDL_QueryTexture(texture, NULL, NULL, &dest.w, &dest.h);

    Uint64 NOW = SDL_GetPerformanceCounter();
    Uint64 LAST = 0;
    double deltaTime = 0;

    while (true) {
        LAST = NOW;
        NOW = SDL_GetPerformanceCounter();
        deltaTime = (double)((NOW - LAST) / (double)SDL_GetPerformanceFrequency());
        
        SDL_RenderClear(renderer);

        dest.x += 50 * deltaTime;
        dest.y += 50 * deltaTime;

        SDL_RenderCopy(renderer, texture, NULL, &dest);

        SDL_RenderPresent(renderer);    

        std::cout << "Delta Time: " << deltaTime << std::endl;
        std::cout << "FPS: " << 60.0 - deltaTime << std::endl;

        SDL_Delay(1000.0f / (60.0 - deltaTime));
    }


    return 0;
}

I used the suggestion from this post: How to calculate delta time with SDL?

I print out “delta time” and “FPS” to the console and, while the deltaTime is slightly different each time, the FPS is stable 60 (which is the same value that I use in SDL_Delay to calculate delay in ms).
But the test image is clearly moving not smoothly, it stutters and moves at inconsistent speed, and I can’t understand why.

Please help me understand what I am doing wrong. I just can’t understand it even after looking through many examples.

sdl2 – How can I directly write pixel data in an SDL window using surfaces?

I’d like to directly modify pixels in my window in SDL 2. I expect this code to display an entirely red window, but instead I’m getting an all black window.

I’m able to get it working if I directly write to window_surface with the same technique, but not by blitting another surface. I’d like to get it working this way at least just for the purposes of understanding.

#include <SDL.h>

int main()
{
    SDL_Init(SDL_INIT_EVERYTHING);

    SDL_Window *window = SDL_CreateWindow("Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1600, 900, 0);

    SDL_Surface *window_surface = SDL_GetWindowSurface(window);

    SDL_Surface *canvas = SDL_CreateRGBSurfaceWithFormat(
        0, 1600, 900, 32, SDL_PIXELFORMAT_RGBA8888
    );

    Uint32 *buffer = (Uint32*) canvas->pixels;
    int row    = 0;
    int column = 0;
    int offset;
    Uint32 color;
    SDL_UnlockSurface(canvas);
    while (row < 900)
    {
        column = 0;
        while (column < 1600)
        {
            offset = row * 1600 + column;
            color = SDL_MapRGBA(canvas->format, 255, 0, 0, 255);
            buffer(offset) = color;
            column++;
        }
        row++;
    }
    SDL_LockSurface(canvas);

    int quit = 0;
    SDL_Event event;
    while (!quit)
    {
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
            {
                quit = 1;
            }
        }

        SDL_BlitSurface(canvas, 0, window_surface, 0);
        SDL_UpdateWindowSurface(window);

        SDL_Delay(10);
    }

    SDL_Quit();

    return 0;
}

c++ – SDL Lag / Super slow

Soo im new to SDL, i have created a simple test program.

i have a game loop which measures the ms it takes to finish.
before entering the loop i call a “Init” function which looks like this:

void screen::Init()
{
    if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
        m_window = SDL_CreateWindow("TITLE", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH*SIZE, HEIGHT*SIZE, NULL);

        m_renderer = SDL_CreateRenderer(m_window, -1, NULL);
        if(m_renderer)
            SDL_SetRenderDrawColor(m_renderer, 0,0,0,0);

        m_Texture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT);

    }
}

The thing is that when i call the function one execution of the loop takes 70 to 90 ms!
if i leave the “init” function call out (so no window shown) its only 2-4 ms.

The loop does nothing other than calling one function which looks like the following:

void screen::handleEvents()
{
    SDL_PollEvent(&m_event);
    switch(m_event.type)
    {
        case SDL_QUIT:
            screen->Clean();
            break;
        default:
            break;
    }
}

leaving the handleEvents function out results in 0-2ms, but the window crashes the moment i click on it.

not sure what im doing wrong but im pretty sure it shouldnt slow down to ~10 FPS lol

rendering – SDL 2 SDL_BLENDMODE_BLEND way faster. Why?

I was just tinkering around with a simple ecs, when I noticed drawing like 20,000 rectangles killed my
framerate (~10 FPS). I thought ok, maybe it’s just too many.

Later I wanted to draw them transparent and set the blend mode to SDL_BLENDMODE_BLEND. Now I can draw
around 60,000 of them with 60 FPS.

I figured maybe it’s because of pixel format conversion or something alike. When I use getWindowPixelFormat I get RGB888. No I’m even more confused because of the lacking alpha channel.

Code (abbreviated):

SDL_Window *window  = SDL_CreateWindow("Test",
                                       SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                       1280, 720,
                                       wndFlags);

SDL_Renderer *renderer  = SDL_CreateRenderer( window, -1,
                                             SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
while(running) {
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0xFF, 0xFF);
SDL_RenderFillRect(renderer, &rect);
SDL_RenderPresent(renderer)
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
}

Could someone enlighten me please?

C++, SDL, and RAII – Code Review Stack Exchange

Learning Modern C++ patterns and this ended up being the direction I went to to create an encapsulation of SDL’s window management, while trying to stay with RAII practices. This is meant to be a base for a software renderer (and possibly expanding to OpenGL after that).

window/input.h

#pragma once

#include <map>

// State of a keyboard key
enum class KeyboardKeyState {
    Up,
    Down,
    Pressed, // Key was previously down last check and just changed to the up state
};

// Keyboard keys that we are listening for events for
enum class KeyboardKey {
    W, S, A, D, LeftArrow, RightArrow, UpArrow, DownArrow
};

struct InputState {
    std::map<KeyboardKey, KeyboardKeyState> Keys{
            {KeyboardKey::W, KeyboardKeyState::Up},
            {KeyboardKey::S, KeyboardKeyState::Up},
            {KeyboardKey::A, KeyboardKeyState::Up},
            {KeyboardKey::D, KeyboardKeyState::Up},
            {KeyboardKey::LeftArrow, KeyboardKeyState::Up},
            {KeyboardKey::UpArrow, KeyboardKeyState::Up},
            {KeyboardKey::DownArrow, KeyboardKeyState::Up},
            {KeyboardKey::RightArrow, KeyboardKeyState::Up},
    };

    bool LeftMouseClicked{};
    bool RightMouseClicked{};
    int MouseDragX{};
    int MouseDragY{};
    int MouseScrollAmount{};
};

window/window_state.h

#pragma once

struct WindowState {
    bool quitRequested{false};
};

window/window_settings.h

#pragma once

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

// How the window will be rendered to (e.g. manually via a pixel buffer, OGL context, Vulkan context, etc...)
enum class WindowRenderMode {
    Unspecified, // No render mode selected.  Will throw exceptions
    ByPixelBuffer, // Rendered using software rendering directly to a window's pixel buffer
};

// Contains options for the window display
struct WindowSettings {
    // How many pixels wide the window should be. If unspecified it will match the display's width.
    std::optional<int> Width;

    // How many pixels tall the window should be. If unspecified it will match the display's height
    std::optional<int> Height;

    // If the window should be borderless or not
    bool Borderless{false};

    // The title to give the window
    std::string Title{};

    // How we intend to render to the window
    WindowRenderMode RenderMode{WindowRenderMode::Unspecified};
};

window/sdl/sdl_raii.h

#pragma once

// C++ can't deal with classes that use forward declared types, so we need all these RAII types
// in it's own header to keep it out of sdl_app_window.h

#include <memory>
#include <vector>
#include <SDL.h>
#include "window/window_settings.h"

namespace sdl_raii {
    class SdlWindow {
    public:
        std::unique_ptr<SDL_Window, void(*)(SDL_Window*)> pointer;

        explicit SdlWindow(const WindowSettings& windowSettings);
        SdlWindow(const SdlWindow& other) = delete;
        SdlWindow(SdlWindow&& other) = default;
    };

    class SdlRenderer {
    public:
        std::unique_ptr<SDL_Renderer, void(*)(SDL_Renderer*)> pointer;

        explicit SdlRenderer(const SdlWindow& window);
        SdlRenderer(const SdlRenderer& other) = delete;
        SdlRenderer(SdlRenderer&& other) = default;
    };

    class SdlFullWindowTexture {
    public:
        std::unique_ptr<SDL_Texture, void(*)(SDL_Texture*)> pointer;

        SdlFullWindowTexture(const WindowSettings& windowSettings, const SdlRenderer& renderer);
        SdlFullWindowTexture(const SdlFullWindowTexture& other) = delete;
        SdlFullWindowTexture(SdlFullWindowTexture&& other) = default;
    };
}

window/sdl/sdl_raii.cpp

#include <stdexcept>
#include "sdl_raii.h"

using namespace sdl_raii;

std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> CreateSdlWindowPointer(const WindowSettings &windowSettings) {
    if (windowSettings.RenderMode != WindowRenderMode::ByPixelBuffer) {
        std::string error = "Unsupported render mode: ";
        error += std::to_string((int) windowSettings.RenderMode);
        throw std::runtime_error{error};
    }

    if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
        std::string error{"Error initializing SDL: "};
        error += SDL_GetError();

        throw std::runtime_error{error};
    }

    unsigned int flags = windowSettings.Borderless ? SDL_WINDOW_BORDERLESS : 0;

    auto sdlWin = SDL_CreateWindow(windowSettings.Title.c_str(),
                                   SDL_WINDOWPOS_CENTERED,
                                   SDL_WINDOWPOS_CENTERED,
                                   windowSettings.Width.value(),
                                   windowSettings.Height.value(),
                                   flags);

    if (sdlWin == nullptr) {
        std::string error = "Error creating SDL window: ";
        error += SDL_GetError();
        throw std::runtime_error{error};
    }

    return std::unique_ptr<SDL_Window, void(*)(SDL_Window*)>(sdlWin, &SDL_DestroyWindow);
}

std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> CreateSdlRendererPointer(const SdlWindow& sdlWindow) {
    auto renderer = SDL_CreateRenderer(sdlWindow.pointer.get(), -1, 0);
    if (!renderer) {
        std::string error{"Error creating renderer: "};
        error += SDL_GetError();

        throw std::runtime_error{error};
    }

    return std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)>(renderer, &SDL_DestroyRenderer);
}

std::unique_ptr<SDL_Texture, void (*)(SDL_Texture*)>
CreateSdlTexturePointer(const WindowSettings &windowSettings, const SdlRenderer& sdlRenderer) {
    auto pointer = SDL_CreateTexture(sdlRenderer.pointer.get(),
                                     SDL_PIXELFORMAT_ARGB8888,
                                     SDL_TEXTUREACCESS_STREAMING,
                                     windowSettings.Width.value(),
                                     windowSettings.Height.value());

    return std::unique_ptr<SDL_Texture, void (*)(SDL_Texture*)>(pointer, &SDL_DestroyTexture);
}

SdlWindow::SdlWindow(const WindowSettings &windowSettings)
    : pointer{CreateSdlWindowPointer(windowSettings)} {
}

SdlRenderer::SdlRenderer(const SdlWindow& window)
    : pointer{CreateSdlRendererPointer(window)} {
}

SdlFullWindowTexture::SdlFullWindowTexture(const WindowSettings &windowSettings, const SdlRenderer &renderer)
    : pointer{CreateSdlTexturePointer(windowSettings, renderer)}{
}

window/sdl/sdl_app_window.h

#pragma once

#include <SDL.h>
#include <memory>
#include <vector>
#include <span>
#include "window/input.h"
#include "window/window_state.h"
#include "window/window_settings.h"
#include "sdl_raii.h"

// A window that's managed by SDL
class SdlAppWindow {
public:
    explicit SdlAppWindow(WindowSettings settings);
    SdlAppWindow(const SdlAppWindow& other) = delete;
    SdlAppWindow(SdlAppWindow&& other) = default;

    // Retrieves a mutable view of the raw full screen pixel buffer.
    std::span<unsigned int> GetPixelBuffer();

    // Performs any work that needs to be done at the beginning of a frame.
    void BeginFrame();

    // Called after all render operations have occurred, in order to push the renderings to the window
    void PresentFrame();

    void HandleWindowEvents(WindowState& windowState, InputState& inputState);

private:
    const WindowSettings windowSettings;
    sdl_raii::SdlWindow sdlWindow;
    sdl_raii::SdlRenderer sdlRenderer;
    sdl_raii::SdlFullWindowTexture sdlFullWindowTexture;

    // Full screen render buffer for use in the ByPixelBuffer render mode
    std::vector<unsigned int> pixelBuffer;

    static WindowSettings GetUpdatedWindowSettings(WindowSettings windowSettings);
    std::vector<unsigned int> CreatePixelBuffer();
};

window/sdl/sdl_app_window.cpp

#include <utility>
#include <stdexcept>
#include "sdl_app_window.h"

using std::vector;

SdlAppWindow::SdlAppWindow(WindowSettings settings) :
        windowSettings{GetUpdatedWindowSettings(std::move(settings))},
        sdlWindow{windowSettings},
        sdlRenderer{sdlWindow},
        sdlFullWindowTexture(windowSettings, sdlRenderer),
        pixelBuffer{CreatePixelBuffer()} {
}

void SdlAppWindow::BeginFrame() {
    switch (windowSettings.RenderMode) {
        case WindowRenderMode::ByPixelBuffer:
            // fill to black
            std::fill(pixelBuffer.begin(), pixelBuffer.end(), 0xFF000000);
            break;

        default:
            std::string error{"No begin frame support for render mode: "};
            error += std::to_string((int) windowSettings.RenderMode);
            throw std::runtime_error{error};
    }
}

void SdlAppWindow::PresentFrame() {
    int pitch = windowSettings.Width.value() * (int) sizeof (int);
    SDL_UpdateTexture(sdlFullWindowTexture.pointer.get(),
                      nullptr,
                      pixelBuffer.data(),
                      pitch);

    SDL_RenderCopy(sdlRenderer.pointer.get(), sdlFullWindowTexture.pointer.get(), nullptr, nullptr);
    SDL_RenderPresent(sdlRenderer.pointer.get());
}

WindowSettings SdlAppWindow::GetUpdatedWindowSettings(WindowSettings windowSettings) {
    SDL_DisplayMode displayMode;
    SDL_GetCurrentDisplayMode(0, &displayMode);

    if (!windowSettings.Width.has_value()) {
        windowSettings.Width = displayMode.w;
    }

    if (!windowSettings.Height.has_value()) {
        windowSettings.Height = displayMode.h;
    }

    return windowSettings;
}

std::vector<unsigned int> SdlAppWindow::CreatePixelBuffer() {
    std::vector<unsigned int> result(windowSettings.Width.value() * windowSettings.Height.value());

    return result;
}

std::span<unsigned int> SdlAppWindow::GetPixelBuffer() {
    return std::span<unsigned int>{pixelBuffer};
}

void SdlAppWindow::HandleWindowEvents(WindowState& windowState, InputState &inputState) {
    SDL_Event sdlEvent;
    while (SDL_PollEvent(&sdlEvent))
    {
        switch (sdlEvent.type) {
            case SDL_QUIT:
                windowState.quitRequested = true;
                break;

            // todo: add case statements for keyboard/mouse processing
        }
    }
}

main.cpp

#include <iostream>
#include <SDL.h>
#include "window/window_settings.h"
#include "window/sdl/sdl_app_window.h"

int main(int argc, char* argv()) {
    constexpr unsigned int targetFps = 30;
    constexpr unsigned int targetFrameTime = 1000 / targetFps;

    WindowSettings settings{
        1024,
        768,
        false,
        std::string{"Test Window"},
        WindowRenderMode::ByPixelBuffer,
    };

    SdlAppWindow appWindow{settings};

    InputState inputState;
    WindowState windowState;

    unsigned int previousFrameTime = 0;
    bool isRunning = true;
    while(isRunning) {
        unsigned int timeSinceLastFrame = SDL_GetTicks() - previousFrameTime;
        int timeToWait = targetFrameTime - timeSinceLastFrame;
        if (timeToWait > 0 && timeToWait <= targetFrameTime) {
            SDL_Delay(timeToWait);
        }

        previousFrameTime = SDL_GetTicks();

        appWindow.HandleWindowEvents(windowState, inputState);
        appWindow.BeginFrame();

        auto buffer = appWindow.GetPixelBuffer();
        std::fill(buffer.begin(), buffer.end(), 0xFFFF0000);

        appWindow.PresentFrame();

        isRunning = !windowState.quitRequested;
    }

    return 0;
}
```

sdl – Getting a surface compatible with the texture / renderer

I’m trying to convert my emulator to SDL2 (from SDL 1.2).

As I’m drawing pixel per pixel, I follow “If your game just wants to get fully rendered frames to the screen” in the migration guide:
https://wiki.libsdl.org/MigrationGuide#If_your_game_just_wants_to_get_fully-rendered_frames_to_the_screen

I basically do:

SDL_CreateWindowAndRenderer(...);
vid = SDL_CreateRGBSurface(..., bpp, ...);
texture = SDL_CreateTextureFromSurface(renderer, vid);

// ... and then later, when "blitting" ...

SDL_UpdateTexture(texture, NULL, vid->pixels, vid->pitch);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);

It works fine if I use 32bpp but this doesn’t work for other bpp: the colors are not as expected. This is because the surface has a pixel format with the BPP I want but the texture has a different pixel format.
This is problematic because:

  • I have some (optional) specific scaling algorithms that require 16bpp surfaces
  • I’m not sure whether it will behave the same for all users
  • When not scaling with my own algorithms, the performance is better if I directly use the bpp of the display

The reason why the bpp doesn’t match is that the SDL_UpdateTexture accesses the surface data (pixels) without even looking at the pixel format and SDL_CreateTextureFromSurface creates a texture compatible with the renderer, not caring about the surface format.

So my questions are:

  • Is there a simple way to get a surface that is compatible with the renderer? (1)
  • Is there a way to blit the surface on the texture that does the color conversion? (2)

(1) I found:

SDL_RendererInfo infos;
SDL_GetRendererInfo(renderer, &infos);
vid = SDL_CreateRGBSurfaceWithFormat(0, w, h, SDL_BITSPERPIXEL(infos.texture_formats(0)), infos.texture_formats(0));

but it’s a bit heavy, there are multiple supported so I’m not sure which one to choose and I also had some display issues that suggest the result is not really what I want.

(2) One idea I had is to have another surface with the format taken from (1) and to blit to it first for the conversion, before copying it to the texture, but I’m surprised there’s no simpler way to do it.

sdl2 – Game loop in C for SDL game

I need to create a menu for my game but in game loop this is where i get stuck and don’t know where to put my menu and where game a how to do when i click play the menu dissapears and game shows up.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#include <SDL.h>
#include <SDL_image.h>

#include "./constants.h"


int game_is_running = FALSE;
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;


struct button {
    float x;
    float y;
    float width;
    float height;
} button;


int initialize_window(void)
{
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
    {
        fprintf(stderr, "Error initializing SDL.n");
        return FALSE;
    }
    window = SDL_CreateWindow
    (
     NULL,
     SDL_WINDOWPOS_CENTERED,
     SDL_WINDOWPOS_CENTERED,
     WINDOW_WIDTH,
     WINDOW_HEIGHT,
     SDL_WINDOW_BORDERLESS
    );
    if (!window)
    {
        fprintf(stderr, "Error creating SDL Window.n");
        return FALSE;
    }

    renderer = SDL_CreateRenderer(window, -1,0);
    if(!renderer)
    {
        fprintf(stderr, "Error creating SDL Renderer.n");
        return FALSE;
    }

    return TRUE;
}


void process_input()
{
    SDL_Event event;
    SDL_PollEvent(&event);


    switch (event.type)
    {
    case SDL_QUIT:
        game_is_running = FALSE;
        break;
    case SDL_KEYDOWN:
        if (event.key.keysym.sym == SDLK_ESCAPE)
            game_is_running = FALSE;
        break;
    }
}

void update()
{

}

void render()
{
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);


    SDL_RenderPresent(renderer);
}

void destroy_window()
{
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
}

void setup()
{

}

int main( int argc, char* argv() )
{
    game_is_running = initialize_window();

    setup();

    while (game_is_running)
    {
        process_input();
        update();
        render();
    }

    destroy_window();


    return TRUE;
}

game loop – Why does the triangle rendered by OpenGL ES 2.0 , with SDL 2.0 context, vanishes after a single render, if events are not polled?

I was experimenting with OpenGL ES 2.0 and being new to OpenGL, I was trying to render a simple triangle. But I was shocked to see that, if I do not call SDL_PollEvent(...) after glDrawArrays(...) in the game loop, I see the triangle render on the screen for a split second and then it vanishes altogether ! But, if I call SDL_PollEvent then everything is fine ! Can anyone explain to me the reason for this abnormal behavior???

However, this is the interesting part of my code:

This code works perfectly, if I uncomment the commented block of code:

uint32_t vbo; 
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 
glEnableVertexAttribArray(pos);
glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);

bool run = true;
SDL_Event e;
while (run)
{
    glDrawArrays(GL_TRIANGLES, 0, 3);
  SDL_GL_SwapWindow(window); 

/*while(SDL_PollEvent(&e))
{
      switch(e.type)
      {
           case SDL_QUIT:
                run = false;
                break; 
      }
} */

}

Vertex Shader:

precision mediump float; 
attribute vec3 pos;
void main()
{
    gl_Position = vec4(pos.xyz, 1.0); 
}

Fragment Shader:

precision mediump float; 
void main()
{
      gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0); 
}

Every help will be greatly appreciated, Thankyou everyone in advance !

Testing and coding conventions for testing C with SDL

I finished my first real C project and it was Conways Game of Life. The code is working fine and the game runs. Since this was my first project though I don’t know any of the real code conventions for writing C. I wanted to implement some tests so I had to split up the functionality from the main file into a new one.

I couldn’t really figure out though how to write the tests to maybe refactor the code in the future and just for educational purposes since this is my first time also writing any real tests. Since I implemented many functions that work together with the ones from SDL I have no clue how to test these. This is the file containing all functions:

#include "./main.h"

multi_arr Field = {0,};
multi_arr nextState = {0,};

SDL_Color blue = {0,0,255,255};
SDL_Color black = {0,0,0,255};
SDL_Color white = {244,244,244,50};

int getLastMultiple(int number){
    int multiple = RECT_SIZE;
    float remainder;
    if ((remainder = (number % multiple)) == 0)
        return number;
    else{
        number -= remainder;
    }
    return number;
}

void colorRect(SDL_Renderer *renderer, SDL_Rect r,SDL_Color color){
    SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b ,255);

    // Render rect
    SDL_RenderFillRect(renderer, &r);
}


void drawGrid(SDL_Renderer *renderer,SDL_Color color){
    SDL_SetRenderDrawColor(renderer, color.r,color.g,color.b,color.a);
    for (int i = 20; i < SCREEN_WIDTH; i += 20){
        SDL_RenderDrawLine(renderer, i,0,i,SCREEN_HEIGHT);
    }
    for (int i = 20; i < SCREEN_HEIGHT;i += 20){
        SDL_RenderDrawLine(renderer, 0,i,SCREEN_WIDTH,i);
    }
}

void displayImg(SDL_Renderer *renderer,char* path){
    SDL_Surface *image = SDL_LoadBMP(path);
    if (image == NULL){
        printf("cant load imagen");
    }
    SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, image);

    SDL_Rect image_pos = { 6,SCREEN_HEIGHT-55, 50, 50 };
    SDL_Rect rect = {0,SCREEN_HEIGHT-59,60,60};

    colorRect(renderer, rect, white);
    SDL_RenderCopy(renderer, texture, NULL,&image_pos);
}

void updateGame(SDL_Window *window,SDL_Renderer *renderer, SDL_Rect r,bool paused){
    //Loop through field-array and show rectangles if cell alive
    char *path;
    
    if (paused){
        path = "./assets/start.bmp";
    } else{
        path = "./assets/pause.bmp";
    }

    for (int i = 0; i < WIDTH;i++){
        for (int j = 0; j < HEIGHT;j++){
            if (Field(i)(j) == true){
                r.x = i * 20;
                r.y = j * 20;
                colorRect(renderer, r, blue);
            } else {
                r.x = i * 20;
                r.y = j * 20;
                colorRect(renderer, r, white);
            }
        }
    }

    drawGrid(renderer,black);
    displayImg(renderer, path);

    SDL_RenderPresent(renderer);
}

int countAliveNeighbors(int x, int y){
    int count = 0;

    for (int rows = -1; rows < 2; rows++){
        for (int columns = -1; columns < 2;columns++){
            if ((x+columns) >= 0 && (x+columns) < WIDTH && (y+rows) >= 0 && (y+rows) < HEIGHT){
                if (Field(x+columns)(y+rows) == true){
                    count++;
                }
            }
        }
    }
    if (Field(x)(y) == true){
        return count -1;
    }
    return count;
}

void copyArray(multi_arr arr1,multi_arr arr2){
    for (int i = 0; i < WIDTH;i++){
        for (int j = 0; j < HEIGHT;j++){
            arr1(i)(j) = arr2(i)(j);
        }
    }
}

void nextEpoch(){
    for (int i = 0; i < WIDTH;i++){
        for (int j = 0; j < HEIGHT;j++){
            if (Field(i)(j) == true && (countAliveNeighbors(i, j) == 3 || countAliveNeighbors(i, j) == 2)){
                nextState(i)(j) = true;               
            } else if (Field(i)(j) == false && countAliveNeighbors(i, j) == 3){
                nextState(i)(j) = true;
            } else {
                nextState(i)(j) = false;
            }
        }
    }
    copyArray(Field, nextState);
}


bool buttonPress(int x,int y){
    if (x <= 2 && x >= 0 && y >= (HEIGHT - 3) && y <= HEIGHT){
        return true;
    }
    return false;
}

Uint32 my_callbackfunc( Uint32 interval, void *param ){
    SDL_Event e;

    e.user.type = SDL_USEREVENT;
    e.user.code = 0;
    e.user.data1 = NULL;
    e.user.data2 = NULL;

    SDL_PushEvent(&e);

    return interval;
}

These are the tests I have written so far:

#include "./include/criterion/criterion.h"
#include "include/criterion/assert.h"
#include "include/criterion/internal/test.h"
#include "main.h" 

extern multi_arr Field;

Test(getLastMultiple,test_getLastMultiple_if_multiple_20){
    cr_assert(getLastMultiple(58) == 40);
    cr_assert(getLastMultiple(29) == 20);
    cr_assert(getLastMultiple(640) == 640);
}

Test(aliveNeighbors,test_count_alive_neighbors_if_cell_active){
    Field(20)(10) = true;
    Field(19)(10) = true;
    Field(21)(11) = true;

    cr_assert(countAliveNeighbors(20, 10) == 2);
}

Test(aliveNeighbors,test_count_alive_neighbors_if_cell__not_active){
    Field(20)(10) = true;
    Field(19)(10) = true;
    Field(21)(11) = true;

    cr_assert(countAliveNeighbors(20, 11) == 3);
}

Test(buttonPress,test_button_press_detected){
    cr_assert(buttonPress(2, HEIGHT) == true);
    cr_assert(buttonPress(5, HEIGHT) == false);
}

Test(copyArray,test_array_copied){
    Field(20)(10) = true;
    Field(19)(10) = true;
    Field(21)(11) = true;

    multi_arr copied = {0,};

    copyArray(copied,Field);
    /*cr_assert_arrays_eq_cmp(copied,Field);*/
}

Test(nextEpoch,test_if_next_epoch_cells_correct_pos){
    int active_cells = 0;
    multi_arr nextState = {0,};

    Field(20)(10) = true;
    Field(19)(10) = true;
    Field(21)(11) = true;

    nextEpoch();
    for (int i = 0;i < WIDTH;i++){
        for (int j = 0; j < HEIGHT;j++){
            active_cells += (Field(i)(j) == true) ? 1 : 0;
        }
    }
    cr_assert(active_cells == 2);
    cr_assert(Field(20)(10) == true && Field(20)(11) == true);
}

Thanks for the help and sorry if I didn’t use the community in the correct way. Any help is appreciated. This is all the code: https://github.com/PhilippRados/GameOfLife