SDL Application Not Responding

Hey Everyone! I’ve been trying to solve this problem on my own for a few days now, but it’s just confusing to do so. For the past month this hasn’t been a problem and only occurred about a week ago.

Here’s The Code:

Window.h

#pragma once

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

#include <iostream>

class Window {
  private:
    // Declaring SDL Window
    SDL_Window *window;

    // Declaring SDL_Renderer To Display Things On Screen
    SDL_Renderer *Renderer;

    // Static SDL Event Variable
    static inline SDL_Event Event;
      
    int framesPerSec;
    int frameDelay;
    int frameTime;
    Uint32 frameStart;

    // Boolean Variable That Checks If The Game Is Running Or Not
    bool isRunning;

   public:
     Window();
     virtual ~Window();

     // Game Functions 
     bool Init(const char *tt, int w, int h, int window_mode, int renderer_mode, int fps);
     bool EventHandler();
     void Render();
     int Clear();
     
     bool IsRunning();
};

Window.cpp

#include "Window.h"

Window::Window() {
  window = nullptr;
  Renderer = nullptr;
}

bool Window::Init(const char *tt, int w, int h, int window_mode, int renderer_mode, int fps) {
  framesPerSec = FPS;
  frameDelay = 1000 / framesPerSec;
  frameStart = 0;
  
  if(SDL_Init(SDL_INIT_EVERYTHING) == 0) {
    window = SDL_CreateWindow(TITLE, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, WINDOW_MODE);
    
    Renderer = SDL_CreateRenderer(window, -1, RENDERER_MODE);

    isRunning = true;
  } 
  else {
    std::cout << "ERROR: " << SDL_GetError << ".. Could Not Initialize Window." << std::endl;
     return false;
  }
  
  return true;
}

bool Window::EventHandler() {
  frameStart = SDL_GetTicks();

  SDL_PollEvent(&Event);
  if(Event.type == SDL_QUIT) { // This is the one that isn't working :/
    isRunning = false;
  } 
  else if(Event.type == SDL_KEYUP && Event.key.keysym.sym == SDLK_ESCAPE) {
    isRunning = false;
  }

  frameTime = SDL_GetTicks() - frameStart;

  if(frameDelay > frameTime || frameDelay < frameTime) {
    SDL_Delay(frameDelay - frameTime);
  }

  return true;
}

void Window::Render() {
  SDL_RenderClear(Renderer);
  SDL_RenderPresent(Renderer);
}

int Window::Clear() {
  SDL_DestroyRenderer(Renderer);
  SDL_DestroyWindow(window);
  IMG_Quit();
  SDL_Quit();

  return 0;
}

bool Window::IsRunning() {
  return isRunning;
}

Window::~Window() {
  
}

main.cpp

#include "Window.h"

Window *window = nullptr;

int main(int argc, char *argv[]) {
  window = new Window();

  window->Init("Game Title", 800, 600, SDL_WINDOW_SHOWN, SDL_RENDERER_ACCELERATED, 100);

  while(window->IsRunning()) {
    window->EventHandler();
    window->Render();
  }

  return window->Clear();
}

You see, whenever I press the ‘Esc’ key, the window quits properly. BUT when I click the ‘X’ button on the top right of the window, it lags / hangs and later on says that the window is not responding… why is that?

Thanks in advance for those who will be able to solve my problem.

You need to check the return value of SDL_PollEvent before accessing the event object.

while (SDL_PollEvent(&Event)) {
  if(Event.type == SDL_QUIT) {
    isRunning = false;
  } 
  else if(Event.type == SDL_KEYUP && Event.key.keysym.sym == SDLK_ESCAPE) {
    isRunning = false;
  }
}

This also looks a little bit suspicious:

if(frameDelay > frameTime || frameDelay < frameTime) {
    SDL_Delay(frameDelay - frameTime);
  }

If frameDelay is less than frameTime that means frameDelay - frameTime will result in a negative value which will be converted to a very big positive value when converted to Uint32 (which is the type that SDL_Delay expects as argument). If that happened it would sleep for days.

I also noticed you used FPS while the parameter is named fps. Is that a bug or just a copy-paste error?

bool Window::Init(const char *tt, int w, int h, int window_mode, int renderer_mode, int fps) {
  framesPerSec = FPS; // What is FPS? Did you mean fps?

Also note that the frame time that you calculate is only the time it takes to handle the events. It doesn’t take rendering and other things into account. Personally I would only call SDL_GetTicks() once per frame and use the previous value to calculate how much time has passed and I would not do it inside the event handler function because it has got nothing to do with events, has it?

That one, was just a copy-paste error, and

Thanks for the tip, didn’t know that because I just followed a tutorial for it, and pretty much edited the “less than” part, guess just me being stupid, so yeah.

Ok, I’ll try that one out.