I have just set up the SDL2 framework on my mac but however compilation and running the program succeeds, the window is not responding (I copied code that creates some rectangle).
I use xcode and I followed tutorial from here http://lazyfoo.net/tutorials/SDL/01_hello_SDL/mac/xcode/index.php
step by step.
SDL_Window* window = NULL;
//The surface contained by the window
SDL_Surface* screenSurface = NULL;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
}
else
{
//Create window
window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
}
else
{
//Get window surface
screenSurface = SDL_GetWindowSurface( window );
//Fill the surface white
SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF ) );
//Update the surface
SDL_UpdateWindowSurface( window );
cout << " Ok" << endl;
//Wait two seconds
SDL_Delay( 20000 );
}
}
//Destroy window
SDL_DestroyWindow( window );
//Quit SDL subsystems
SDL_Quit();
return 0;
Why could that problem happen?
Thank you in advance
In order for a program written SDL to "respond" to operating system, you should give control back to SDL for it to process system messages and give them back to you as SDL events (mouse events, keyboard events and so on).
To do that, you have to add a loop that uses SDL_PollEvent, that should look something
while(true)
{
SDL_Event e;
while (SDL_PollEvent(&e))
{
// Decide what to do with events here
}
// Put the code that is executed every "frame".
// Under "frame" I mean any logic that is run every time there is no app events to process
}
There are some special events such as SDL_QuiEvent that you would need to handle to have a way to close your application. If you want to handle it, you should modify your code to look something like this:
while(true)
{
SDL_Event e;
while (SDL_PollEvent(&e))
{
if(e.type == SDL_QUIT)
{
break;
}
// Handle events
}
// "Frame" logic
}
Related
I'm trying to test a simple SDL2 application. The app runs without any errors. However, no window shows up.
I'm using Ubuntu18.04 on a VMWare machine. I also tried to compile SDL from the source but got the same result. I am unsure if the cause of the problem is related to my OS or because of executing from a virtual machine.
Here is a simple application from docs (I just added SDL_GetNumDisplayModes to make sure the display mode is OK- returns 1)
// Using SDL and standard IO
#include <SDL2/SDL.h>
#include <stdio.h>
// Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
int main(int argc, char *args[])
{
// The window we'll be rendering to
SDL_Window *window = NULL;
// The surface contained by the window
SDL_Surface *screenSurface = NULL;
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
}
else
{
int res = SDL_GetNumDisplayModes(0);
printf("SDL_GetNumDisplayModes: %d\r\n", res);
// Create window
window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL)
{
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
}
else
{
// Get window surface
screenSurface = SDL_GetWindowSurface(window);
// Fill the surface white
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0xFF, 0xFF, 0xFF));
// Update the surface
SDL_UpdateWindowSurface(window);
// Hack to get window to stay up
SDL_Event e;
bool quit = false;
while (quit == false)
{
while (SDL_PollEvent(&e))
{
if (e.type == SDL_QUIT)
{
quit = true;
}
}
}
}
}
// Destroy window
SDL_DestroyWindow(window);
// Quit SDL subsystems
SDL_Quit();
return 0;
}
Summary:
I've been looking for the answer everywhere and cannot find it. Maybe someone can help. Basically I am following a tutorial series on YouTube for game dev using sdl2, and I've come to a point where I need to add and download the sdl_image libraries. I didn't have trouble linking sdl, but I am having big issues trying to link sdl_image. All the tutorials are on windows. I am desperate for a solution.
What I've tried:
adding -lSDL2_image to link settings, adding SDL_image.h to the SDL2 folder, and include it in my cpp file. I've tried adding the file path to the SDL2_image-2.0.5 folder on codeblocks and no dice. I've tried ./configure and sudo make install in the file directory, and it sent a .o and .so file to /usr/include/lib, and then I tried adding the search directory /usr/include/lib just to get a segmentation fault error.
Code:
/*This source code copyrighted by Lazy Foo' Productions (2004-2020)
and may not be redistributed without written permission.*/
//Using SDL, SDL_image, standard IO, and strings
#include <SDL2/SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
//Starts up SDL and creates window
bool init();
//Loads media
bool loadMedia();
//Frees media and shuts down SDL
void close();
//Loads individual image
SDL_Surface* loadSurface( std::string path );
//The window we'll be rendering to
SDL_Window* gWindow = NULL;
//The surface contained by the window
SDL_Surface* gScreenSurface = NULL;
//Current displayed PNG image
SDL_Surface* gPNGSurface = NULL;
bool init()
{
//Initialization flag
bool success = true;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Create window
gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( gWindow == NULL )
{
printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) )
{
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
success = false;
}
else
{
//Get window surface
gScreenSurface = SDL_GetWindowSurface( gWindow );
}
}
}
return success;
}
bool loadMedia()
{
//Loading success flag
bool success = true;
//Load PNG surface
gPNGSurface = loadSurface( "/home/zues/Desktop/Entities/Space.png" );
if( gPNGSurface == NULL )
{
printf( "Failed to load PNG image!\n" );
success = false;
}
return success;
}
void close()
{
//Free loaded image
SDL_FreeSurface( gPNGSurface );
gPNGSurface = NULL;
//Destroy window
SDL_DestroyWindow( gWindow );
gWindow = NULL;
//Quit SDL subsystems
IMG_Quit();
SDL_Quit();
}
SDL_Surface* loadSurface( std::string path )
{
//The final optimized image
SDL_Surface* optimizedSurface = NULL;
//Load image at specified path
SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
if( loadedSurface == NULL )
{
printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() );
}
else
{
//Convert surface to screen format
optimizedSurface = SDL_ConvertSurface( loadedSurface, gScreenSurface->format, 0 );
if( optimizedSurface == NULL )
{
printf( "Unable to optimize image %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
}
//Get rid of old loaded surface
SDL_FreeSurface( loadedSurface );
}
return optimizedSurface;
}
int main( int argc, char* args[] )
{
//Start up SDL and create window
if( !init() )
{
printf( "Failed to initialize!\n" );
}
else
{
//Load media
if( !loadMedia() )
{
printf( "Failed to load media!\n" );
}
else
{
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//While application is running
while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit = true;
}
}
//Apply the PNG image
SDL_BlitSurface( gPNGSurface, NULL, gScreenSurface, NULL );
//Update the surface
SDL_UpdateWindowSurface( gWindow );
}
}
}
//Free resources and close SDL
close();
return 0;
}
And finally I want to ask... Am I wasting my time learning sdl2? Should I be learning something else? The ultimate goal is to release a successful game and built a handsome community. Kind of hard to find 2020 resources... especially since games have gotten so big and advanced i.e fortnite, cod warzone, halo infinity... I can list hundreds more.
Thanks in advance :)
Im running this on MacOS 10.12 using Xcode 8.3.3 with SDL2 installed via Homebrew as Dylibs.
Below is some slightly modified sample code from lazy foo.
I just added a second texture gTexture2 and the function loadMedia2 to be able to reproduce the issue. The second time IMG_Load is executed it crashes with the following message:
EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
Searching on how to solve a "General Protection Fault" problem did also not get me further, the crash seems to happen inside SDL. I probably really misunderstand here something that leads to this issue and would really welcome any help.
The really confusing thing is, it does not crash always, only about 2 of 3 times.
The crash seem to happen inside SDL_AllocFormat_REAL ():
Here is the code sample.
/*This source code copyrighted by Lazy Foo' Productions (2004-2015)
and may not be redistributed without written permission.*/
//Using SDL, SDL_image, standard IO, and strings
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
//Starts up SDL and creates window
bool init();
//Loads media
bool loadMedia();
//Frees media and shuts down SDL
void close();
//Loads individual image as texture
SDL_Texture* loadTexture( std::string path );
//The window we'll be rendering to
SDL_Window* gWindow = NULL;
//The window renderer
SDL_Renderer* gRenderer = NULL;
//Current displayed texture
SDL_Texture* gTexture = NULL;
SDL_Texture* gTexture2 = NULL;
bool init()
{
//Initialization flag
bool success = true;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Set texture filtering to linear
if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) )
{
printf( "Warning: Linear texture filtering not enabled!" );
}
//Create window
gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( gWindow == NULL )
{
printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Create renderer for window
gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED );
if( gRenderer == NULL )
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Initialize renderer color
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) )
{
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
success = false;
}
}
}
}
return success;
}
bool loadMedia()
{
//Loading success flag
bool success = true;
//Load PNG texture
gTexture = loadTexture( "../assets/player.png" );
if( gTexture == NULL )
{
printf( "Failed to load texture image!\n" );
success = false;
}
return success;
}
bool loadMedia2()
{
//Loading success flag
bool success = true;
//Load PNG texture
gTexture2 = loadTexture( "../assets/scene_main/background.png" );
if( gTexture == NULL )
{
printf( "Failed to load texture image!\n" );
success = false;
}
return success;
}
void close()
{
//Free loaded image
SDL_DestroyTexture( gTexture );
SDL_DestroyTexture( gTexture2 );
gTexture = NULL;
gTexture2 = NULL;
//Destroy window
SDL_DestroyRenderer( gRenderer );
SDL_DestroyWindow( gWindow );
gWindow = NULL;
gRenderer = NULL;
//Quit SDL subsystems
IMG_Quit();
SDL_Quit();
}
SDL_Texture* loadTexture( std::string path )
{
//The final texture
SDL_Texture* newTexture = NULL;
//Load image at specified path
SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
if( loadedSurface == NULL )
{
printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() );
}
else
{
//Create texture from surface pixels
newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface );
if( newTexture == NULL )
{
printf( "Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
}
//Get rid of old loaded surface
SDL_FreeSurface( loadedSurface );
}
return newTexture;
}
int main( int argc, char* args[] )
{
//Start up SDL and create window
if( !init() )
{
printf( "Failed to initialize!\n" );
}
else
{
//Load media
if( !loadMedia() || !loadMedia2() )
{
printf( "Failed to load media!\n" );
}
else
{
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//While application is running
while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit = true;
}
}
//Clear screen
SDL_RenderClear( gRenderer );
//Render texture to screen
SDL_RenderCopy( gRenderer, gTexture, NULL, NULL );
//Update screen
SDL_RenderPresent( gRenderer );
}
}
}
//Free resources and close SDL
close();
return 0;
}
Little Update:
I've tried it on windows, there it runs completely fine. So I guess the issue is related to MacOs.
I already tried to reinstall all libraries.
I'm using C++14.
The solution
Well its just half of a solution its more a workaround.
Thanks to #Sahib Yar he pointed out to try to put the images in the same directory. Which resolves the issue.
But I think this is really weird, you should be able to load resources from different directories or at least subdirectory.
The final question
Now I would really love an explanation why we can't load images from multiple directories using SDL on MacOS. Is that just a bug, known thing or did I make a big mistake?
It seems that you are not destroying texture2 that is not needed.
SDL_DestroyTexture( gTexture );
SDL_DestroyTexture( gTexture2 );
gTexture = NULL;
gTexture2 = NULL;
In this lazyfoo tutorial, it is mentioned that
In our clean up function, we have to remember to deallocate our
textures using SDL_DestroyTexture.
Edit 1:
Try to put all your images in the same directory.
Edit 2:
It is not related to directory in MacOS From this tutorial, it seems like compiler is doing some optimization with std::string path as the std::string is mutable.
Try to clear the std::string path object at end of function to clear up all the memory reserved by its objects.
add this line.
std::string().swap(path);
Your issue is a dangling pointer. EXC_BAD_ACCESS is the CPU moaning that you are addressing non-existent memory or memory which is outside of your access rights area. The cause is a lack of reatainment of an object which causes early deallocation and then is overwritten. At which time (which may be delayed), the pointer will point to garbage whose dereference causes an EXC_BAD_ACCESS to be thrown.
Edit 3:
It is not something related to SDL2. After Googling, I have found that in Xcode, everything is eventually packed into 1 single directory. I have found multiple questions regarding this. It may be something related to folder reference and groups. To my guess it could be something related to blue folders. If this is the case you can consult this answer and use accordingly for SDL.
I'm trying to load an image from file without using the entire file path. Like in C#, However everything I try just throws my sdl error in the console when it gets to loading the image.
bool loadMedia()
{
//Loading success flag
bool success = true;
//Load splash image
gHelloWorld = SDL_LoadBMP( "SDL2_tutorials02/hello_world.bmp" );
if( gHelloWorld == NULL )
{
printf( "Unable to load image %s! SDL Error: %s\n", "SDL2_tutorials02/hello_world.bmp", SDL_GetError() );
success = false;
}
return success;
}
This is part of my original code that I learned from an online tutorial, trying to teach myself SDL and more about c++
edit for InternetAussie, this is my entire source code from what I think I have learned from the tutorial is below:
//Using SDL and standard IO
#include <SDL.h>
#include <stdio.h>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
//Starts up SDL and creates window
bool init();
//Loads media
bool loadMedia();
//Frees media and shuts down SDL
void close();
//The window we'll be rendering to
SDL_Window* gWindow = NULL;
//The surface contained by the window
SDL_Surface* gScreenSurface = NULL;
//The image we will load and show on the screen
SDL_Surface* gHelloWorld = NULL;
bool init()
{
//Initialization flag
bool success = true;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Create window
gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( gWindow == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Get window surface
gScreenSurface = SDL_GetWindowSurface( gWindow );
}
}
return success;
}
bool loadMedia()
{
//Loading success flag
bool success = true;
//Load splash image
gHelloWorld = SDL_LoadBMP( "SDL2_tutorials02/hello_world.bmp" );
if( gHelloWorld == NULL )
{
printf( "Unable to load image %s! SDL Error: %s\n", "SDL2_tutorials02/hello_world.bmp", SDL_GetError() );
success = false;
}
return success;
}
void close()
{
//Deallocate surface
SDL_FreeSurface( gHelloWorld );
gHelloWorld = NULL;
//Destroy window
SDL_DestroyWindow( gWindow );
gWindow = NULL;
//Quit SDL subsystems
SDL_Quit();
}
int main( int argc, char* args[] )
{
//Start up SDL and create window
if( !init() )
{
printf( "Failed to initialize!\n" );
}
else
{
//Load media
if( !loadMedia() )
{
printf( "Failed to load media!\n" );
}
else
{
//Apply the image
SDL_BlitSurface( gHelloWorld, NULL, gScreenSurface, NULL );
//Update the surface
SDL_UpdateWindowSurface( gWindow );
//Wait two seconds
SDL_Delay( 2000 );
}
}
//system halt for testing
system("pause");
//Free resources and close SDL
close();
return 0;
}
and if it helps I followed the instructions in tutorial 1 at Lazy Foo' Productions. The hyperlink that I hope I have appropriately added is just the setup part after clicking through the steps on how to setup sdl on a windows machine using visual studios 2010 ultimate. I went with the system 32 setup using the console as my output source for errors.
As InternetAussie already said if you are running the compiled executable all the paths are relative to the directory your executable runs from.
What your problem seems to be is related to your IDE. When you build and run code from your IDE the working directory is taken from somewhere else. It can be some default path where your IDE builds debug versions of your program. It's hard to tell exactly because it's different for all of them.
If you want to debug your SDL project you should set the working directory for compiler to the directory you are compiling your executable into and where you also have your files you want to read saved.
F. e. : if you are using visual studio you can set this by right clicking on a project > settings > debugging > working path option or if you build your project with cmake you can also set it with SET_PROPERTY(TARGET Project_name PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "path").
If this didn't solve your problem, feel free to ask questions. Also if you are using cmake and VS, I can provide you with a complete cmakelists.txt that generates SDL2 project for VisualStudio and set's up all required settings.
I have recently been breaking up a large source file into headers and smaller source files. I have never done this before, and largely because of scope, I had to rewrite some of the functions to accept pointers and then call them from main().
This is still a work in progress, however, I've ran into a problem that I have been trying for hours to fix. The code is developed from Lazy Foos excellent SDL tutorial series.
I have moved this function into a header file. Ingeniously titled misc.cpp/misc.h.
bool init(SDL_Window *gWindow, SDL_Renderer *gRenderer)
{
//Initialization flag
bool success = true;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Set texture filtering to linear
if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) )
{
printf( "Warning: Linear texture filtering not enabled!" );
}
//Create window
gWindow = SDL_CreateWindow( "Roulette Testing", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( gWindow == NULL )
{
printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Create renderer for window
gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if( gRenderer == NULL )
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Initialize renderer color
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) )
{
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
success = false;
}
std::cout << gRenderer << "renderer not NULL" << std::endl; //This is where I am checking the value of gRenderer within the function.
}
}
}
std::cout << "initialization success" << std::endl;
return success;
}
Now I am trying to call this function from my main() after having included the header and compiled the cpp into object code. This worked fine for the texture header file.
Unfortunately, now when I'm passing a SDL_Renderer pointer to this init function, it's becoming local, and I'm left with a NULL pointer when I return. I have tried the "&" address of operator, but it won't accept it!
init(gWindow, gRenderer);
I'm unsure why, but I'm guessing it's to do with the type.
Any ideas guy??
In response to comments... In my main I fire off a
cout << gRenderer << endl;
and it comes back NULL both before and after the function call.
I have highlighted in the function where I fire off another cout.
Make the function signature a reference to a pointer and it will return the value returned from SDL_CreateRenderer to the calling function (assuming gRenderer is a pointer when passed in):
bool init(SDL_Window *gWindow, SDL_Renderer *&gRenderer)
Looks like you should also pass gWindow in the same way.