int main( int argc, char* args[] )
{
if( SDL_Init(SDL_INIT_EVERYTHING) < 0 )
std::cout<<"unable to init sdl";
SDL_Surface *screen = SDL_SetVideoMode(800,600,32,SDL_DOUBLEBUF);
std::cout<<"before while\n";
SDL_Event event;
while(SDL_PollEvent(&event))
{
std::cout<<"in while\n";
if(event.type == SDL_QUIT)
std::cout<<"SDL_QUIT\n";
}
std::cout<<"after while\n";
SDL_Quit();
}
For some unknown reason this SDL app quits after running in the while loop 4 times without me killing/closing/etc it and without printing "SDL_QUIT" to stdout.
Is there a reason for this? How do I fix it?
You need to keep your application alive by creating a main loop for it. As of now, your application just quits after you poll all the initial events:
int main( int argc, char* args[] )
{
if( SDL_Init(SDL_INIT_EVERYTHING) < 0 )
std::cout<<"unable to init sdl";
SDL_Surface *screen = SDL_SetVideoMode(800,600,32,SDL_DOUBLEBUF);
SDL_Event event;
bool active = true;
while(active)
{
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
std::cout<<"SDL_QUIT\n";
active = false;
}
}
// TODO: add drawing to screen
SDL_Flip(screen);
}
SDL_Quit();
}
SDL_PollEvent will return false when there are no more events to handle, which is right after application startup in this case.
You need to nest the poll loop inside another loop that keeps the application alive:
int running = 1;
while (running)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
running = 0;
}
// Update and draw here usually
}
Related
Pressing CTRL+C while in the terminal sometimes fails to end the program:
int main(int argc, char *argv[]) {
DrawingWindow window = DrawingWindow(WIDTH, HEIGHT, false);
SDL_Event event;
while(true) {
if (window.pollForInputEvents(event)) handleEvent(event);
draw();
window.renderFrame();
}
}
}
bool DrawingWindow::pollForInputEvents(SDL_Event &event) {
if (SDL_PollEvent(&event)) {
if ((event.type == SDL_QUIT) || ((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_ESCAPE))) {
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
printMessageAndQuit("Exiting", nullptr);
}
SDL_Event dummy;
// Clear the event queue by getting all available events
// This seems like bad practice (because it will skip some events) however preventing backlog is paramount !
while (SDL_PollEvent(&dummy));
return true;
}
return false;
}
void printMessageAndQuit(const std::string &message, const char *error) {
if (error == nullptr) {
std::cout << message << std::endl;
exit(0);
} else {
std::cout << message << " " << error << std::endl;
exit(1);
}
}
When CTRL+C succeeds (which is most of the time), it does print "Exiting".
I don't know what handleEvent supposed to do, and your code have braces mismatch so looks like it isn't even your actual code. As written, pollForInputEvents fetches one event, checks if it could be considered a quit condition, and then discards all other events in the queue regardless. If event you're looking for happens to be non-first (e.g. as first event you may have keydown of 'ctrl' or mouse move, or window close event, ...), then it never gets processed. handleEvent has the same problem - it gets only first event in frame.
Generally speaking, event processing have to happen in a fast non-blocking loop, which handles events faster than new events are getting in. Processing only one event per frame is a not fast enough, and there is absolutely no reason to process only one event. Events gets accumulated in a queue, you process all events, draw your image frame (potentially slow), present on screen (potentially blocking on vsync), then repeat.
It looks counterintuitive that your event processing is split into two functions.
As I don't see the rest of your code, with "minimal" changes it should be something like:
#include <SDL2/SDL.h>
#include <iostream>
#define WIDTH 640
#define HEIGHT 480
static void handleEvent(SDL_Event &event) {}
static void draw(SDL_Renderer *renderer) {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
}
class DrawingWindow {
public:
DrawingWindow(int width, int height, bool fs) {
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("test",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
width, height, 0);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
}
bool pollForInputEvents(SDL_Event &event);
void renderFrame() {
SDL_RenderPresent(renderer);
}
SDL_Window *window;
SDL_Renderer *renderer;
};
void printMessageAndQuit(const std::string &message, const char *error) {
if (error == nullptr) {
std::cout << message << std::endl;
exit(0);
} else {
std::cout << message << " " << error << std::endl;
exit(1);
}
}
bool DrawingWindow::pollForInputEvents(SDL_Event &event) {
if (SDL_PollEvent(&event)) {
if ((event.type == SDL_QUIT) || ((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_ESCAPE))) {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
printMessageAndQuit("Exiting", nullptr);
}
return true;
}
return false;
}
int main(int argc, char *argv[]) {
DrawingWindow window = DrawingWindow(WIDTH, HEIGHT, false);
SDL_Event event;
while(true) {
while(window.pollForInputEvents(event)) handleEvent(event);
draw(window.renderer);
window.renderFrame();
}
}
I want to create a little program, which should draw some Math Functions.
At first a just wrote the code, that should create a little Window, that should just be visisble until I hit the X at the window.
#include <iostream>
#include <SDL2/SDL.h>
SDL_Window* window;
SDL_Renderer* renderer;
bool running = true;
bool init() {
if(SDL_Init(SDL_INIT_EVERYTHING) < 0) return false;
window = SDL_CreateWindow("Visual Functions", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 100, 200, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if(window == NULL) return false;
if(renderer == NULL) return false;
std::cout << "App and SDL init success" << std::endl;
return true;
}
void onEvent(SDL_Event* event) {
switch (event->type)
{
case SDL_QUIT:
running = false;
break;
default:
break;
}
}
void loop() {
SDL_Event* event;
while(SDL_PollEvent(event)) onEvent(event);
}
void cleanUp() {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
int main(int, char**) {
if(!init()) {
std::cout << "SDL or/and App init failed" << std::endl;
exit(-1);
}
while(running) loop();
cleanUp();
}
But the window pops so fast up and again down, that I couldn't even see it and in the command is at first App and SDL init success but then there stands Segmentation fault.
In a other code, which has the same Initialization and Loop code runs very well and everything is displayed displayed normally (at least for the SDL part).
I found out with some debug messages, that the loop comes not to the Event Function, but also not to the end of the Loop Function, so the problem is SDL_PollEvent(event), but what is the prolem and how to I fix it ?
You never create the SDL_Event struct that you are using:
void loop() {
SDL_Event* event;
while(SDL_PollEvent(event)) onEvent(event);
}
should be this
void loop() {
SDL_Event event;
while(SDL_PollEvent(&event)) onEvent(&event);
}
My program generates an image. I want to close the window by clicking on any key or by clicking with my pointer on the window cross.
It works only by clicking on the cross (Use of SDL_QUIT) but not with SDL_KEYDOWN. I tried also with SDL_SPACE, SDL_KEYUP but the result is the same.
So what am I missing in my code ?
I am using xcode.
int main(int argc, char *argv[])
{
SDL_Surface *ecran = NULL, *imageDeFond = NULL, *zozor = NULL;
SDL_Rect positionFond, positionZozor;
SDL_Event event;
int continuer = 1;
SDL_Init(SDL_INIT_VIDEO);
ecran = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
imageDeFond = SDL_LoadBMP("lac_en_montagne.bmp");
SDL_BlitSurface(imageDeFond, NULL, ecran, &positionFond);
SDL_Flip(ecran);
while (continuer)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_KEYDOWN:
{
printf("use of SDL_KEYDOWN");
continuer=0;
break;
}
case SDL_QUIT:
{
printf("use of SDL_QUIT");
continuer = 0;
break;
}
}
}
SDL_FreeSurface(imageDeFond);
SDL_Quit();
return EXIT_SUCCESS;
}
I have this simple code for SDL.
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2_image/SDL_image.h>
using namespace std;
int main(int argc, char * argv[]){
if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
return 1;
}
SDL_Window * win = SDL_CreateWindow("Window", 0, 0, 1920, 1080, SDL_WINDOW_FULLSCREEN_DESKTOP);
if(win == nullptr){
return 1;
}
SDL_Quit();
return 0;
}
None of this shows a window, I have error checked everything. It was working previously, but now it just opens and closes. I'm running on Xcode, if that helps.
Like the others state, your program terminates immediately so the window should "flash" momentarily. You can have the window appear for a few seconds by using SDL_Delay:
SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (win == nullptr){
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Delay(2000);
SDL_DestroyWindow(win);
SDL_Quit();
And remember to call SDL_DestroyWindow.
A while(true) {} loop will just cause your program to freeze. You probably want something like the following so that it listens for events, and you can close the window at your leisure.
SDL_Event e;
bool quit = false;
while (!quit){
while (SDL_PollEvent(&e)){
if (e.type == SDL_QUIT){
quit = true;
}
if (e.type == SDL_KEYDOWN){
quit = true;
}
if (e.type == SDL_MOUSEBUTTONDOWN){
quit = true;
}
}
}
Can someone write up a source for a program that just has a "game loop", which just keeps looping until you press Esc, and the program shows a basic image. Heres the source I have right now but I have to use SDL_Delay(2000); to keep the program alive for 2 seconds, during which the program is frozen.
#include "SDL.h"
int main(int argc, char* args[]) {
SDL_Surface* hello = NULL;
SDL_Surface* screen = NULL;
SDL_Init(SDL_INIT_EVERYTHING);
screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);
hello = SDL_LoadBMP("hello.bmp");
SDL_BlitSurface(hello, NULL, screen, NULL);
SDL_Flip(screen);
SDL_Delay(2000);
SDL_FreeSurface(hello);
SDL_Quit();
return 0;
}
I just want the program to be open until I press Esc. I know how the loop works, I just don't know if I implement inside the main() function, or outside of it. I've tried both, and both times it failed. If you could help me out that would be great :P
Here is a complete and working example. Instead of using a frame-time regulation you can also use SDL_WaitEvent.
#include <SDL/SDL.h>
#include <cstdlib>
#include <iostream>
using namespace std;
const Uint32 fps = 40;
const Uint32 minframetime = 1000 / fps;
int main (int argc, char *argv[])
{
if (SDL_Init (SDL_INIT_VIDEO) != 0)
{
cout << "Error initializing SDL: " << SDL_GetError () << endl;
return 1;
}
atexit (&SDL_Quit);
SDL_Surface *screen = SDL_SetVideoMode (640, 480, 32, SDL_DOUBLEBUF);
if (screen == NULL)
{
cout << "Error setting video mode: " << SDL_GetError () << endl;
return 1;
}
SDL_Surface *pic = SDL_LoadBMP ("hello.bmp");
if (pic == NULL)
{
cout << "Error loading image: " << SDL_GetError () << endl;
return 1;
}
bool running = true;
SDL_Event event;
Uint32 frametime;
while (running)
{
frametime = SDL_GetTicks ();
while (SDL_PollEvent (&event) != 0)
{
switch (event.type)
{
case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE)
running = false;
break;
}
}
if (SDL_GetTicks () - frametime < minframetime)
SDL_Delay (minframetime - (SDL_GetTicks () - frametime));
}
SDL_BlitSurface (pic, NULL, screen, NULL);
SDL_Flip (screen);
SDL_FreeSurface (pic);
SDL_Delay (2000);
return 0;
}
Tried with something like
SDL_Event e;
while( SDL_WaitEvent(&e) )
{
if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE) break;
}
? You can find many tutorials and example out there; just a fast-search example.
Added note: WaitEvent "freezes" the program so you can't do anything .. you just wait; other waiting technics can be desired (as PollEvent, or WaitEvent again after the initializtion of a timer).
Since you're already using SDL, you could use the SDL_PollEvent function to run an event loop, checking to see if the key press event was ESC. Looks like this would be along the lines of mySDL_Event.key.keysym.sym == SDLK_ESCAPE.
#include <conio.h>
...
while (!kbhit())
{
hello = SDL_LoadBMP("hello.bmp");
SDL_BlitSurface(hello, NULL, screen, NULL);
SDL_Flip(screen);
}
...