0
\$\begingroup\$

As an attempt to learn SDL on C, I decided to try and create a simple Pong program using it. My problem now is that of the textures I've given it, two paddles and a ball, only the ball is rendered. It fails to render anything else even if it is the only thing I give. I have no idea why this happens. I've spend more than an hour trying to fix this, scanning each line of code line by line multiple times. I even went as far as renaming a paddle image to ball, and only then did it render. I think there is a deep and most likely stupid flaw to how I implemented it, so I attached some of the code below:

texRacquet1 = SDL_CreateTextureFromSurface(rend, racquet1);
SDL_FreeSurface(racquet1);
texRacquet2 = SDL_CreateTextureFromSurface(rend, racquet2);
SDL_FreeSurface(racquet2);
texBall = SDL_CreateTextureFromSurface(rend, ball);
SDL_FreeSurface(ball);

This creates textures from the images and sets them to the pointers I defined.

SDL_Rect sracquet1;
SDL_Rect sracquet2;
SDL_Rect sball;

//Gets scale and dimensions of textures
SDL_QueryTexture(texRacquet1, NULL, NULL, &sracquet1.w, &sracquet1.h);
sracquet1.w * 6;
sracquet1.h * 6;
SDL_QueryTexture(texRacquet2, NULL, NULL, &sracquet2.w, &sracquet2.h);
sracquet2.w * 6;
sracquet2.h * 6;
SDL_QueryTexture(texBall, NULL, NULL, &sball.w, &sball.h);
sball.w * 6;
sball.h * 6;

This queries the textures and finds the dimensions of the shape, adding them to their respective structure members from the rectangle structures set for each texture. It also dilates it by 6 so it can be seen.

    //Copies textures to buffer and presents them to screen
    SDL_RenderCopy(rend, texRacquet1, NULL, &sracquet1);
    SDL_RenderCopy(rend, texRacquet2, NULL, &sracquet2);
    SDL_RenderCopy(rend, texBall, NULL, &sball);
    SDL_RenderPresent(rend);

Finally, this draws the textures and presents them to the screen. Or it should. It only renders the ball, and if I remove that line, it just does nothing.

Full code:

//Speed of ball in pixels per second
const int SPEED = 300;
const int WINDOW_WIDTH = 640;
const int WINDOW_HEIGHT = 480;

int main(int argc, char* argv[])
{
    //Creates pointers to various game elements
    const char *window1_title = "Pong";

    Uint32 render_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;

    SDL_Window  *window1 = NULL;
    SDL_Renderer*rend = NULL;
    SDL_Surface *racquet1 = NULL;
    SDL_Surface *racquet2 = NULL;
    SDL_Surface *ball = NULL;
    SDL_Texture *texRacquet1 = NULL;
    SDL_Texture *texRacquet2 = NULL;
    SDL_Texture *texBall = NULL;
    int request_quit = 0;

    //Initializes SDL
    SDL_Init(SDL_INIT_EVERYTHING);

    //Prints error message if SDL fails to initalize
    if(SDL_Init(SDL_INIT_EVERYTHING) != 0)
    {
        printf("Failed to initialize SDL: %s\n", SDL_GetError());

        //Quits SDL
        SDL_Quit();
        return 1;
    }
    /*
    Creates centered window with the window title pointer, width, height, and
    no flags
    */
    window1 = SDL_CreateWindow(window1_title, SDL_WINDOWPOS_CENTERED,
                                              SDL_WINDOWPOS_CENTERED,
                                      WINDOW_WIDTH, WINDOW_HEIGHT, 0);

    //Prints error message if SDL failed to create window1
    if(!window1)
    {
        printf("Failed to initalize window: %s\n", SDL_GetError());
        SDL_Quit();
        return 1;
    }

    //Initializes renderer
    rend = SDL_CreateRenderer(window1, -1, render_flags);
    if(!rend)
    {
        printf("Failed to initialize renderer: %s\n", SDL_GetError());

        //Destroys window
        SDL_DestroyWindow(window1);
        SDL_Quit();
        return 1;
    }

    SDL_SetRenderDrawColor(rend, 255, 255, 255, 255);

    //Loads images
    racquet1 = IMG_Load("resources/raquet1.png");
    racquet2 = IMG_Load("resources/raquet2.png");
    ball = IMG_Load("resources/ball.png");

    //Tests if an image didn't load
    if(!racquet1 && !racquet2 && !ball)
    {
        printf("Failed to load images\n");

        //Destroys initalized components and quits
        SDL_DestroyRenderer(rend);
        SDL_DestroyWindow(window1);
        SDL_Quit();
        return 1;
    }

    //Texturizes loaded images

    texRacquet1 = SDL_CreateTextureFromSurface(rend, racquet1);
    SDL_FreeSurface(racquet1);

    texRacquet2 = SDL_CreateTextureFromSurface(rend, racquet2);
    SDL_FreeSurface(racquet2);

    texBall = SDL_CreateTextureFromSurface(rend, ball);
    SDL_FreeSurface(ball);

    // Errors if sprites fail to texturize
    if(!texRacquet1 && !texRacquet2 && !texBall)
    {
        printf("Failed to texturize images\n");
        SDL_DestroyRenderer(rend);
        SDL_DestroyWindow(window1);
        SDL_Quit();
        return 1;
    }

    // Structs to hold coordinate positions
    SDL_Rect xracquet1 = {0, 0, 0, 0};
    SDL_Rect xracquet2 = {0, 0, 0, 0};
    SDL_Rect xball = {0, 0, 0, 0};

    //Gets scale and dimensions of textures
    SDL_QueryTexture(texRacquet1, NULL, NULL, &xracquet1.w, &xracquet1.h);
    SDL_QueryTexture(texRacquet2, NULL, NULL, &xracquet2.w, &xracquet2.h);
    SDL_QueryTexture(texBall, NULL, NULL, &xball.w, &xball.h);

    // Set ball to the middle of the window
    xball.x = (WINDOW_WIDTH - xball.w) / 2;
    xball.y = (WINDOW_HEIGHT - xball.h) / 2;

    // Set racquet 1 to the left side of the window
    xracquet1.x = 0;
    xracquet1.y = (WINDOW_HEIGHT - xracquet1.h) / 2;

    // Set racquet 2 to the right side of the window
    xracquet2.x = (WINDOW_WIDTH - xracquet2.w);
    xracquet2.y = (WINDOW_HEIGHT - xracquet2.h) / 2;

    //Initializes game loop
    while(!request_quit)
    {
        //Processes events
        SDL_Event event;
        while(SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                    request_quit = 1;
                    break;
            }
        }

        //Clears screen for renderer
        SDL_RenderClear(rend);

        //Copies textures to buffer and presents them to screen
        SDL_RenderCopy(rend, texRacquet1, NULL, &xracquet1);
        SDL_RenderCopy(rend, texRacquet2, NULL, &xracquet2);
        SDL_RenderCopy(rend, texBall, NULL, &xball);
        SDL_RenderPresent(rend);

        //Waits 1/60th of a second for a 60 fps lock
        SDL_Delay(1000 / 60);
    }
    SDL_DestroyTexture(texRacquet1);
    SDL_DestroyRenderer(rend);
    SDL_DestroyWindow(window1);
    SDL_Quit();
    return 0;
}
\$\endgroup\$
  • \$\begingroup\$ Check that the surfaces and textures are not nullptr, check that sracquet1- and sracquet2's X and Y value is correctly set. I can't see that you're actually setting those in your code so unclear what value they'll have if you don't set them. Try setting them to the middle of the window to see if they renders. Also dont forget to do SDL_RenderClear(rend); in the beginning of the render loop, i.e before your SDL_RenderCopy() calls. \$\endgroup\$ – Daniel_1985 Aug 6 '18 at 10:46
  • \$\begingroup\$ @Naith I realized that one of my problems was that I accidentally set the width and height of racquet1 equal to that of the ball, but even after correcting it my problem isn't fixed :( \$\endgroup\$ – C͝͡e̷͢pt̡̕i̴̸͘u͜͠͝m Aug 6 '18 at 11:04
  • \$\begingroup\$ I just checked the full code and I can't see anything strange, besides you setting both sracquet1 and sracquet2 to the same position. You should see one of them in the window though. Try to render only one of the textures, so only texRacquet1 as a start, then the next etc. Also set out breakpoint(s) and check each pointer, each position and size etc. \$\endgroup\$ – Daniel_1985 Aug 6 '18 at 11:12
  • \$\begingroup\$ To make sure that it's actually not the actual images that are causing the error, try loading ball.png into the racquet1 SDL_Surface instead of raquet1.png. If the ball is rendered while doing SDL_RenderCopy() on the texRacquet1, you'll know it's something wrong with the actual png image. \$\endgroup\$ – Daniel_1985 Aug 6 '18 at 11:15
  • \$\begingroup\$ @Naith If I stop ball from rendering then nothing happens. I renamed racquet1 ball and it rendered correctly as ball, so it isn't a problem with the image itself. It seems that as long as an image is named ball, it renders. \$\endgroup\$ – C͝͡e̷͢pt̡̕i̴̸͘u͜͠͝m Aug 6 '18 at 11:20
2
\$\begingroup\$

The problem was that the SDL_Rect objects that's supposed to hold position and size data for the textures were receiving incorrect data. Because of this, the textures were rendered outside the window borders (with incorrect sizes) and were therefore not visible at the execution of the program.

Code below has been tested and fully works.

If the error remains, check with other image file(s), re-download SDL, SDL_Image etc.

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

#include <iostream>

//Speed of ball in pixels per second
const int SPEED = 300;
const int WINDOW_WIDTH = 640;
const int WINDOW_HEIGHT = 480;

int main(int argc, char* argv[])
{
    //Creates pointers to various game elements
    const char *window1_title = "Pong";

    Uint32 render_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;

    SDL_Window  *window1 = nullptr;
    SDL_Renderer*rend = nullptr;
    SDL_Surface *racquet1 = nullptr;
    SDL_Surface *racquet2 = nullptr;
    SDL_Surface *ball = nullptr;
    SDL_Texture *texRacquet1 = nullptr;
    SDL_Texture *texRacquet2 = nullptr;
    SDL_Texture *texBall = nullptr;
    int request_quit = 0;

    //Initializes SDL
    SDL_Init(SDL_INIT_EVERYTHING);

    //Prints error message if SDL fails to initalize
    if(SDL_Init(SDL_INIT_EVERYTHING) != 0)
    {
        printf("Failed to initialize SDL: %s\n", SDL_GetError());

        //Quits SDL
        SDL_Quit();
        return 1;
    }
    /*
    Creates centered window with the window title pointer, width, height, and
    no flags
    */
    window1 = SDL_CreateWindow(window1_title, SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        WINDOW_WIDTH, WINDOW_HEIGHT, 0);

    //Prints error message if SDL failed to create window1
    if(!window1)
    {
        printf("Failed to initalize window: %s\n", SDL_GetError());
        SDL_Quit();
        return 1;
    }

    //Initializes renderer
    rend = SDL_CreateRenderer(window1, -1, render_flags);
    if(!rend)
    {
        printf("Failed to initialize renderer: %s\n", SDL_GetError());

        //Destroys window
        SDL_DestroyWindow(window1);
        SDL_Quit();
        return 1;
    }

    SDL_SetRenderDrawColor(rend, 255, 255, 255, 255);

    //Loads images
    racquet1 = IMG_Load("resources/raquet1.png");
    racquet2 = IMG_Load("resources/raquet2.png");
    ball = IMG_Load("resources/ball.png");

    //Tests if an image didn't load
    if(!racquet1 && !racquet2 && !ball)
    {
        printf("Failed to load images\n");

        //Destroys initalized components and quits
        SDL_DestroyRenderer(rend);
        SDL_DestroyWindow(window1);
        SDL_Quit();
        return 1;
    }

    //Texturizes loaded images

    texRacquet1 = SDL_CreateTextureFromSurface(rend, racquet1);
    SDL_FreeSurface(racquet1);

    texRacquet2 = SDL_CreateTextureFromSurface(rend, racquet2);
    SDL_FreeSurface(racquet2);

    texBall = SDL_CreateTextureFromSurface(rend, ball);
    SDL_FreeSurface(ball);

    // Errors if sprites fail to texturize
    if(!texRacquet1 && !texRacquet2 && !texBall)
    {
        printf("Failed to texturize images\n");
        SDL_DestroyRenderer(rend);
        SDL_DestroyWindow(window1);
        SDL_Quit();
        return 1;
    }

    // Structs to hold coordinate positions
    SDL_Rect xracquet1 = {0, 0, 0, 0};
    SDL_Rect xracquet2 = {0, 0, 0, 0};
    SDL_Rect xball = {0, 0, 0, 0};

    //Gets scale and dimensions of textures
    SDL_QueryTexture(texRacquet1, NULL, NULL, &xracquet1.w, &xracquet1.h);
    SDL_QueryTexture(texRacquet2, NULL, NULL, &xracquet2.w, &xracquet2.h);
    SDL_QueryTexture(texBall, NULL, NULL, &xball.w, &xball.h);

    // Set ball to the middle of the window
    xball.x = (WINDOW_WIDTH - xball.w) / 2;
    xball.y = (WINDOW_HEIGHT - xball.h) / 2;

    // Set racket 1 to the left side of the window
    xracquet1.x = 0;
    xracquet1.y = (WINDOW_HEIGHT - xracquet1.h) / 2;
    xracquet1.w = xracquet1.w;
    xracquet1.h = xracquet1.h;

    // Set racket 2 to the right side of the window
    xracquet2.x = (WINDOW_WIDTH - xracquet2.w);
    xracquet2.y = (WINDOW_HEIGHT - xracquet2.h) / 2;
    xracquet2.w = xracquet2.w;
    xracquet2.h = xracquet2.h;

    //Initializes game loop
    while(!request_quit)
    {
        //Processes events
        SDL_Event event;
        while(SDL_PollEvent(&event))
        {
            switch(event.type)
            {
            case SDL_QUIT:
                request_quit = 1;
                break;
            }
        }

        //Clears screen for renderer
        SDL_RenderClear(rend);

        //Copies textures to buffer and presents them to screen
        SDL_RenderCopy(rend, texRacquet1, NULL, &xracquet1);
        SDL_RenderCopy(rend, texRacquet2, NULL, &xracquet2);
        SDL_RenderCopy(rend, texBall, NULL, &xball);
        SDL_RenderPresent(rend);

        //Waits 1/60th of a second for a 60 fps lock
        SDL_Delay(1000 / 60);
    }
    SDL_DestroyTexture(texRacquet1);
    SDL_DestroyRenderer(rend);
    SDL_DestroyWindow(window1);
    SDL_Quit();
    return 0;
}
\$\endgroup\$
  • \$\begingroup\$ I'm trying my best to test it out, but its instantly closing every time I try to open it. Trying to figure out why. If it works I'll accept your answer. \$\endgroup\$ – C͝͡e̷͢pt̡̕i̴̸͘u͜͠͝m Aug 6 '18 at 13:16
  • \$\begingroup\$ I figured it out!!!! The reason it didn't work was because I misspelled racquet as raquet in the IMG_Load function! That was it! \$\endgroup\$ – C͝͡e̷͢pt̡̕i̴̸͘u͜͠͝m Aug 6 '18 at 13:21
  • \$\begingroup\$ There's often the simple errors that are missed, hehe. Great that it finally works. :) \$\endgroup\$ – Daniel_1985 Aug 6 '18 at 13:25
0
\$\begingroup\$

After careful examination, the (extremely stupid) answer to my problem was a simple misspelling.

racquet1 = IMG_Load("resources/raquet1.png");

Should've been:

racquet1 = IMG_Load("resources/racquet1.png");

Everything works now. Thank you @Naith for helping me figure this out.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.