Cannot move Rect

Hey, I’m trying to move some rectangles by pressing s
Except when I press s it’s not moving.

Here’s the relevant chunks of code:

SDL_Rect paddle1;

int paddle1h = 120;
int paddle1y = Height/2 - paddle1h / 2;

if(e.type == SDL_KEYDOWN) {
  if(e.key.keysym.sym == SDLK_s) {
    paddle1y += 5;
  }
}

You have to check events in a loop, since you may get more than one event per frame, and you don’t want to be poking around in the event struct if there weren’t any new events.

void update()
{
    // whatever
    ...
    SDL_Event event;
    while(SDL_PollEvent(&event)) {
        // check events in here
    }

    // more stuff
}

This was in an event loop that I was calling from main. This code might help

int event() {
    if(SDL_PollEvent(&e)) {
        if(e.type == SDL_QUIT) {
            running = false;
        }
        
        if(e.type == SDL_KEYDOWN) {
            if(e.key.keysym.sym == SDLK_ESCAPE) {
                running = false;
            }
            if(e.key.keysym.sym == SDLK_s) {
                paddle1y += 5;
            }
        }
    }
}

I know this is setup right as the escape key works

Update: I did a check to see if the key was pressed by adding a print statement. It does get pressed but the rect doesn’t move.

Do you redraw the “rect” using this paddle1y coordinate every frame?

Note that paddle1.y and paddle1y are two independent objects. Modifying one of them will not automatically affect the other.

This seems to be the problem, except when I try to call draw() in my loop function, the window just goes white with black trying to clip in.

I don’t quite understand how you mean. I think the normal procedure is to first call SDL_RenderClear, and then use “Render” functions such as SDL_RenderCopy or SDL_RenderFillRect to draw the stuff that you want to display, and finally you call SDL_RenderPresent to update the screen. This is done every frame.

This is all the current code in my draw function.

screenSurface = SDL_GetWindowSurface(window);
    SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0x00, 0x00, 0x00));
    SDL_UpdateWindowSurface(window);

    SDL_RenderClear(renderer);

    //Paddle 1

    paddle1.w = 15;
    paddle1.h = paddle1h;
    paddle1.x = 30 - paddle1.w / 2;
    paddle1.y = paddle1y;

    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_RenderFillRect(renderer, &paddle1);

    //Paddle 2

    paddle2.w = 15;
    paddle2.h = 120;
    paddle2.x = 1250 - paddle2.w / 2;
    paddle2.y = Height/2 - paddle2.h / 2;

    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_RenderFillRect(renderer, &paddle2);

    //Ball

    ballSurface = IMG_Load("assets/ball.png");
    ballTexture = SDL_CreateTextureFromSurface(renderer, ballSurface);
    SDL_FreeSurface(ballSurface);

    destR.h = 16;
    destR.w = 16;
    destR.x = Width/2 - destR.w / 2;
    destR.y = Height/2;

    SDL_RenderCopy(renderer, ballTexture, NULL, &destR);

    //Text

    char *fontPath;
    fontPath = "assets/font.ttf";

    font = TTF_OpenFont(fontPath, 48);
    if(font == NULL) printf("Couldn't find font!\n");

    getTextRect(renderer, Width / 4, 50, "00", font, &fontScore1Texture, &fontScore1Rect);
    getTextRect(renderer, 960, 50, "00", font, &fontScore2Texture, &fontScore2Rect);

    SDL_RenderCopy(renderer, fontScore1Texture, NULL, &fontScore1Rect);
    SDL_RenderCopy(renderer, fontScore2Texture, NULL, &fontScore2Rect);

    SDL_RenderPresent(renderer);

But when I call draw() in my loop function, it just makes the screen white with black trying to clip in, and it doesnt manage memory correctly as its just… goes up (Does not do this when not called every frame)

I don’t understand what this means, but perhaps it doesn’t matter because I see some problems…

The documentation for SDL_GetWindowSurface says:

You may not combine this with 3D or the rendering API on this window.

I think you should remove the following lines:

screenSurface = SDL_GetWindowSurface(window);
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0x00, 0x00, 0x00));
SDL_UpdateWindowSurface(window);

Drawing the background colour is the job of SDL_RenderClear. Just make sure to call SDL_SetRenderDrawColor to specify what background colour you want before calling SDL_RenderClear.

It’s because you are not freeing the ball texture using SDL_DestroyTexture and you are not freeing the font using TTF_CloseFont.

Creating surfaces, textures and fonts is relatively slow. It’s probably not something you want to do every frame. Instead I would suggest that you do it once at the start and then you keep reusing the same textures and fonts for the rest of the game (or until you don’t need them anymore).

Thanks it works now :slight_smile:

I updated my cleanup function to this, however it still doesnt manage memory correctly.

int cleanup() {
    TTF_CloseFont(font);
    SDL_DestroyTexture(ballTexture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    TTF_Quit();
    IMG_Quit();
    SDL_Quit();

    return 0;
}

Have you updated your draw() function so that it doesn’t create a new texture and font each time it’s called? If it’s still the same as before then you are only freeing the last texture and font that you created. The ones you created earlier are “leaked”.

It’s of course also possible that there are other memory leaks in the code that you haven’t shown (e.g. in getTextRect).

Yeah I updated the draw function:

int draw() {
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);

    //Paddle 1

    paddle1.w = 15;
    paddle1.h = paddle1h;
    paddle1.x = 30 - paddle1.w / 2;
    paddle1.y = paddle1y;

    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_RenderFillRect(renderer, &paddle1);

    //Paddle 2

    paddle2.w = 15;
    paddle2.h = paddle1h;
    paddle2.x = 1250 - paddle2.w / 2;
    paddle2.y = paddle2y;

    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_RenderFillRect(renderer, &paddle2);

    //Ball

    destR.h = 16;
    destR.w = 16;
    destR.x = Width/2 - destR.w / 2;
    destR.y = Height/2;

    SDL_RenderCopy(renderer, ballTexture, NULL, &destR);

    //Text

    getTextRect(renderer, Width / 4, 50, "00", font, &fontScore1Texture, &fontScore1Rect);
    getTextRect(renderer, 960, 50, "00", font, &fontScore2Texture, &fontScore2Rect);

    SDL_RenderCopy(renderer, fontScore1Texture, NULL, &fontScore1Rect);
    SDL_RenderCopy(renderer, fontScore2Texture, NULL, &fontScore2Rect);

    SDL_RenderPresent(renderer);

With an init function

font = TTF_OpenFont("assets/font.ttf", 48);
    if(font == NULL) printf("Couldn't find font!\n");

    ballSurface = IMG_Load("assets/ball.png");
    ballTexture = SDL_CreateTextureFromSurface(renderer, ballSurface);
    SDL_FreeSurface(ballSurface);

And here’s getTextRect:

int textWidth;
    int textHeight;
    SDL_Color textColor = {255, 255, 255, 255};
    SDL_Surface* surface = TTF_RenderText_Solid(font, text, textColor);

    *texture = SDL_CreateTextureFromSurface(renderer, surface);
    textWidth = surface->w;
    textHeight = surface->h;
    SDL_FreeSurface(surface);
    rect->x = x;
    rect->y = y;
    rect->w = textWidth;
    rect->h = textHeight;

You create a texture inside getTextRect. Do you free it?

I updated my cleanup to do this, it’s still having memory problems

int cleanup() {
    TTF_CloseFont(font);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyTexture(ballTexture);
    SDL_DestroyTexture(fontScore1Texture);
    SDL_DestroyTexture(fontScore2Texture);
    SDL_DestroyWindow(window);
    TTF_Quit();
    IMG_Quit();
    SDL_Quit();

    return 0;
}

I think it’s the same type of problem as I described earlier.

[…] you are only freeing the last texture […] The ones you created earlier are “leaked”.

How many times do you call SDL_CreateTextureFromSurface compared to SDL_DestroyTexture? If it’s not the same number of times then you definitly have a problem. Think about it.

I’m calling both 3 times. 1 time from ballTexture = SDL_CreateTextureFromSurface(renderer, ballSurface);, and two from getTextRect

But don’t you call getTextRect more than twice?

No, it’s only twice as of now

So you are only calling draw() once???

Note that I’m not talking about the number of times they are written in the code. I’m talking about the number of times that those functions gets called when you run your program.