SDL 2.0 – Rendering textures from an array

I have an array of textures that I want to render in the render loop. When I’m going through the array, I don’t get any of the textures actually displayed on the window.

Here’s how I’m initializing the textures I wanna use:

SDL_Texture* tracks[5];
SDL_Rect trackRects[5];
for (int i = 1; i < 6; i++) {
    char buf[20];
    snprintf(buf, 20, ".\\assets\\track%d.png", i);
        
    tracks[i-1] = IMG_LoadTexture(appRenderer, buf);
        
    trackRects[i-1].x = 15;
    trackRects[i-1].y = 28*(i-1) + 150;
}

To render all of these, I’m trying to do this:

for (int i = 0; i < 5; i++) {
    res = SDL_RenderCopy(appRenderer, tracks[i], NULL, &trackRects[i]);
    if (res < 0) printError();
}

This does not return any error, and it compiles, but when I start my program it displays none of the images.

Full code:

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>

int running = 1;
SDL_Window* appWindow = NULL;
SDL_Surface* appSurface = NULL;
SDL_Renderer* appRenderer = NULL;

int res;

int main(int argc, char* argv[]) {
    int videoerror = SDL_Init(SDL_INIT_VIDEO);
    if (videoerror < 0) printError();
    SDL_Window* appWindow = SDL_CreateWindow("name", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1000, 800, SDL_WINDOW_SHOWN);
    
    int imgerror = IMG_Init(IMG_INIT_PNG);
    if (imgerror < 0) printError();
    
    SDL_Renderer* appRenderer = SDL_CreateRenderer(appWindow, -1, SDL_RENDERER_SOFTWARE);
    
    SDL_Texture* tracks[5];
    SDL_Rect trackRects[5];
    for (int i = 1; i < 6; i++) {
        char buf[20];
        snprintf(buf, 20, ".\\assets\\track%d.png", i);
        
        tracks[i-1] = IMG_LoadTexture(appRenderer, buf);
        
        trackRects[i-1].x = 15;
        trackRects[i-1].y = 28*(i-1) + 150;
    }

    while (running == 1) {
        SDL_Event event;
        while (SDL_PollEvent(&event) != 0) {
            if (event.type == SDL_QUIT) {
                running = 0;
            }
        }
        
        SDL_RenderClear(appRenderer);
        
        for (int i = 0; i < 5; i++) {
            res = SDL_RenderCopy(appRenderer, tracks[i], NULL, &trackRects[i]);
            if (res < 0) printError();
        }
        SDL_RenderPresent(appRenderer);
        
        SDL_Delay(100);
    }
    
    SDL_DestroyWindow(appWindow);
    appWindow = NULL;

    IMG_Quit();
    SDL_Quit();
    
    return 0;
}

  • 1

    We really need to see more of your code. The real problem could be elsewhere. (e.g.) Where is your SDL_RenderPresent call? We would really like an MRE. For C, we would like a single .c file [with (e.g.) #include <stdio.h>]. But, no (e.g.) #include "myprogram.h". For runtime errors, it should compile cleanly. We should be able to download, build, and run it on our local systems [if we so choose].

    – 

  • @CraigEstey I added my full code.

    – 

  • 2

    After defining printError, setting w and h of the trackRects, and putting some random PNGs in the right place, it works fine for me. Make sure your assets directory is in the working directory when you launch the program. Basically this: https://stackoverflow.com/questions/53524216/sdl-image-cant-load-png-file-with-img-loadtexture.

    – 

  • I’ve replicated what Nelfeal did. I concur. I did not get any images until I added the setup of .w and .h Crudely, I used trackRects[i-1].w = 512; trackRects[i-1].h = 512; and got the images out (they overlapped/obscured each other). So, the full solution would be to look at the width/height of each image and set .x, .y, .w, .h so they don’t overlap (i.e. placement).

    – 




Prefaced by my top comments …

I’ve added the setup of .w and .h and added a [crude] placement:

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>

#define WID     1000
#define HGT     800

int running = 1;
SDL_Window *appWindow = NULL;
SDL_Surface *appSurface = NULL;
SDL_Renderer *appRenderer = NULL;

int res;

void
printError(void)
{
    exit(9);
}

int
main(int argc, char *argv[])
{
    int videoerror = SDL_Init(SDL_INIT_VIDEO);

    if (videoerror < 0)
        printError();
    SDL_Window *appWindow = SDL_CreateWindow("name", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WID, HGT, SDL_WINDOW_SHOWN);

    int imgerror = IMG_Init(IMG_INIT_PNG);

    if (imgerror < 0)
        printError();

    SDL_Renderer *appRenderer = SDL_CreateRenderer(appWindow, -1, SDL_RENDERER_SOFTWARE);

    SDL_Texture *tracks[5];
    SDL_Rect trackRects[5];

    int abs_y = 0;
    int abs_x = 0;
    int max_h = 0;

    for (int i = 0; i < 5; i++) {
        char buf[20];

        snprintf(buf, 20, "assets/track%d.png", i + 1);

        SDL_Texture *track = IMG_LoadTexture(appRenderer, buf);
        tracks[i] = track;

        SDL_Rect *rect = &trackRects[i];

        int w;
        int h;
        Uint32 fmt;
        int access;
        SDL_QueryTexture(track,&fmt,&access,&w,&h);

#if 0
        rect->x = 15;
        rect->y = 28 * (i - 1) + 150;

        rect->w = 512;
        rect->h = 512;
#else
        if ((abs_x + w) > WID) {
            abs_x = 0;
            abs_y += max_h;
            max_h = 0;
        }

        rect->x = abs_x;
        rect->y = abs_y;
        rect->w = w;
        rect->h = h;

        abs_x += w;
#endif

        if (h > max_h)
            max_h = h;
    }

    while (running == 1) {
        SDL_Event event;

        while (SDL_PollEvent(&event) != 0) {
            if (event.type == SDL_QUIT) {
                running = 0;
            }
        }

        SDL_RenderClear(appRenderer);

        for (int i = 0; i < 5; i++) {
            res = SDL_RenderCopy(appRenderer, tracks[i], NULL, &trackRects[i]);
            if (res < 0)
                printError();
        }
        SDL_RenderPresent(appRenderer);

        SDL_Delay(100);
    }

    SDL_DestroyWindow(appWindow);
    appWindow = NULL;

    IMG_Quit();
    SDL_Quit();

    return 0;
}

In the code above, I’ve used cpp conditionals to denote old vs. new code:

#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif

Note: this can be cleaned up by running the file through unifdef -k


I used random images on my system. Here is the output:
enter image description here

Leave a Comment