When I try to exit the window by clicking the X at the top corner, the program wouldn't end and just continue running. Only after repeatedly clicking the X button, the window managed to close. Why is this the case?
main.cpp:
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "window.hpp"
#include "utils.hpp"
int main(int argc, char *argv[]) {
if (SDL_Init(SDL_INIT_VIDEO) > 0){
std::cout << "SDL has failed to initialize." << std::endl;
std::cout << "SDL ERROR: " << SDL_GetError() << std::endl;
}
if (!(IMG_Init(IMG_INIT_PNG))) {
std::cout << "SDL image has failed to initialize." << std::endl;
std::cout << "SDL_image ERROR: " << IMG_GetError() << std::endl;
}
RenderWindow window("game", 950, 720);
bool gameLoopRunning = true;
SDL_Event event;
const float deltaTime = 0.01f;
float accumulator = 0.0f;
float currentTime = utils::timeInSeconds();
while (gameLoopRunning) {
int startTicks = SDL_GetTicks();
float newTime = utils::timeInSeconds();
float frameTime = newTime - currentTime;
currentTime = newTime;
accumulator = frameTime;
while (accumulator >= deltaTime) {
while (SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_QUIT:
gameLoopRunning = false;
}
accumulator -= deltaTime;
}
}
const float alpha = accumulator / deltaTime;
int frameTicks = SDL_GetTicks() - startTicks;
if (frameTicks < 1000/window.getRefreshRate()) {
SDL_Delay(1000/window.getRefreshRate() - frameTicks);
}
}
window.cleanUp();
SDL_Quit();
return 0;
}
window.cpp:
RenderWindow::RenderWindow(const char* p_title, int p_width, int p_height)
: window(NULL), renderer(NULL) {
window = SDL_CreateWindow(p_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
p_width, p_height, SDL_WINDOW_SHOWN);
if (window == NULL) {
std::cout << "Failed to create window: " << std::endl;
std::cout << "SDL Error: " << SDL_GetError() << std::endl;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
}
int RenderWindow::getRefreshRate() {
int displayIndex = SDL_GetWindowDisplayIndex(window);
SDL_DisplayMode mode;
SDL_GetDisplayMode(displayIndex, 0, &mode);
return mode.refresh_rate;
}
void RenderWindow::cleanUp() {
SDL_DestroyWindow(window);
}
void RenderWindow::clear() {
SDL_RenderClear(renderer);
}
utils.hpp:
namespace utils {
inline float timeInSeconds() {
float ticks = SDL_GetTicks();
ticks *= 0.001f;
return ticks;
}
}
CodePudding user response:
Those two loops will not exit just because you clicked exit:
while (accumulator >= deltaTime) {
while (SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_QUIT:
gameLoopRunning = false;
}
accumulator -= deltaTime;
}
}
The accumulator loop is especially likely to run for a while if you game is behind, in game time. You should make it explicit that you want to break out of those loops, and not just wait later:
while (accumulator >= deltaTime && gameLoopRunning) {
while (SDL_PollEvent(&event) && gameLoopRunning) {
switch(event.type) {
case SDL_QUIT:
gameLoopRunning = false;
}
accumulator -= deltaTime;
}
}
Notice the extra && gameLoopRunning
.