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;
}
Related
SDL_TTF 2.20.0 (with Harfbuzz enabled) introduced TTF_SetFontDirection() and TTF_SetFontScriptName() "for additional control over fonts using HarfBuzz".
I am trying to render some Arabic text, and I have set the font direction to RTL and the script name to "arSA\0", but the glyphs aren't joining up correctly.
Both TTF_SetFontDirection(ttf_font, TTF_DIRECTION_RTL) and TTF_SetFontScriptName(ttf_font, "arSA\0") return 0, which indicates success.
This is how I expected the text to appear:
And this is how it is appearing instead:
Can anybody tell me what I'm doing wrong?
Edit: Minimal reproducible example:
(Adapted from https://github.com/aminosbh/sdl2-ttf-sample/blob/master/src/main.c)
#include <SDL.h>
#include <SDL_ttf.h>
#include <string>
int main(int argc, char* argv[])
{
// Unused argc, argv
(void)argc;
(void)argv;
// Initialize SDL2
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL2 could not be initialized!\n"
"SDL2 Error: %s\n", SDL_GetError());
return 0;
}
// Initialize SDL2_ttf
TTF_Init();
// Create window
SDL_Window* window = SDL_CreateWindow("SDL2_ttf sample",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
if (!window)
{
printf("Window could not be created!\n"
"SDL_Error: %s\n", SDL_GetError());
}
else
{
// Create renderer
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!renderer)
{
printf("Renderer could not be created!\n"
"SDL_Error: %s\n", SDL_GetError());
}
else
{
// Declare rect of square
SDL_Rect squareRect;
// Square dimensions: Half of the min(SCREEN_WIDTH, SCREEN_HEIGHT)
squareRect.w = MIN(SCREEN_WIDTH, SCREEN_HEIGHT) / 2;
squareRect.h = MIN(SCREEN_WIDTH, SCREEN_HEIGHT) / 2;
// Square position: In the middle of the screen
squareRect.x = SCREEN_WIDTH / 2 - squareRect.w / 2;
squareRect.y = SCREEN_HEIGHT / 2 - squareRect.h / 2;
TTF_Font* font = TTF_OpenFont(FONT_PATH, 40);
if (!font) {
printf("Unable to load font: '%s'!\n"
"SDL2_ttf Error: %s\n", FONT_PATH, TTF_GetError());
return 0;
}
const auto fontDirectionSuccess = TTF_SetFontDirection(font, TTF_DIRECTION_RTL);
const auto fontScriptNameSuccess = TTF_SetFontScriptName(font, "arSA\0");
SDL_Color textColor = { 0x00, 0x00, 0x00, 0xFF };
SDL_Color textBackgroundColor = { 0xFF, 0xFF, 0xFF, 0xFF };
SDL_Texture* text = NULL;
SDL_Rect textRect;
// Arabic text to display
const wchar_t * wstr = L"كسول الزنجبيل القط";
// Convert unicode to multibyte
int wstr_len = (int)wcslen(wstr);
int num_chars = WideCharToMultiByte(CP_UTF8, 0, wstr, wstr_len, NULL, 0, NULL, NULL);
CHAR* strTo = (CHAR*)malloc((num_chars + 1) * sizeof(CHAR));
if (strTo)
{
WideCharToMultiByte(CP_UTF8, 0, wstr, wstr_len, strTo, num_chars, NULL, NULL);
strTo[num_chars] = '\0';
}
// Render text to surface
SDL_Surface* textSurface = TTF_RenderUTF8_Blended(font, strTo, textColor);
if (!textSurface) {
printf("Unable to render text surface!\n"
"SDL2_ttf Error: %s\n", TTF_GetError());
}
else {
// Create texture from surface pixels
text = SDL_CreateTextureFromSurface(renderer, textSurface);
if (!text) {
printf("Unable to create texture from rendered text!\n"
"SDL2 Error: %s\n", SDL_GetError());
return 0;
}
// Get text dimensions
textRect.w = textSurface->w;
textRect.h = textSurface->h;
SDL_FreeSurface(textSurface);
}
textRect.x = (SCREEN_WIDTH - textRect.w) / 2;
textRect.y = squareRect.y - textRect.h - 10;
// Event loop exit flag
bool quit = false;
// Event loop
while (!quit)
{
SDL_Event e;
// Wait indefinitely for the next available event
SDL_WaitEvent(&e);
// User requests quit
if (e.type == SDL_QUIT)
{
quit = true;
}
// Initialize renderer color white for the background
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
// Clear screen
SDL_RenderClear(renderer);
// Draw text
SDL_RenderCopy(renderer, text, NULL, &textRect);
// Update screen
SDL_RenderPresent(renderer);
}
// Destroy renderer
SDL_DestroyRenderer(renderer);
}
// Destroy window
SDL_DestroyWindow(window);
}
// Quit SDL2_ttf
TTF_Quit();
// Quit SDL
SDL_Quit();
return 0;
}
Edit 2:
I've replaced
TTF_SetFontDirection(font, TTF_DIRECTION_RTL);
TTF_SetFontScriptName(font, "arSA\0");
with the depracated:
TTF_SetDirection(HB_DIRECTION_RTL);
TTF_SetScript(HB_SCRIPT_ARABIC);
And everything works fine. I suspect "arSA\0" might be wrong, but the only documentation I can find says it should be a "null-terminated string of exactly 4 characters", with no indication or example of which 4 characters.
Instead of "arSA", you should use "Arab".
See https://github.com/harfbuzz/harfbuzz/blob/7a219ca9f0f8140906cb7fd3b879b5bf5259badc/src/hb-common.h#L514
Credits to commenters "1.8e9-where's-my-share m" & "skink".
I'm adding the answer here so you can accept is as answered.
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
}
I'm trying to simply create a window and blit an image to the screen but for some reason the image is not showing up and the screen remains white. I've been using lazyfoo's tutorial for reference in order to figure this out. I posted all my code below, hopefully it's readable enough. Help would be appreciated as I've been stuck on this for an hour or two, thank you.
#include <SDL.h>
#include <SDL_audio.h>
#include <cstdio>
#include <iostream>
#include <Windows.h>
// creates Load_surface function
SDL_Surface *loadSurface(std::string path) {
SDL_Surface *loadedSurface = SDL_LoadBMP(path.c_str());
if (loadedSurface == NULL) {
printf("Unable to load image %s! SDL Error: %s\n", path.c_str(),
SDL_GetError());
}
return loadedSurface;
}
int main(int argc, char ** argv)
{
// pointer variable for window
SDL_Window *window;
SDL_Surface *surface = NULL;
SDL_Surface *media =
loadSurface("C:\\Users\\nickl\\Desktop\\buttonpressed.bmp");
// initialize and test for failure
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) == -1) {
return 1;
}
// create the window
window = SDL_CreateWindow(
"Ice Cream Boys Software",
48,
48,
640,
480,
SDL_WINDOW_OPENGL
);
// safety check, see if window was created, otherwise throw an error
if (window = NULL) {
printf("Could not create window: %s", SDL_GetError());
return 1;
}
else {
OutputDebugString(TEXT("Surface loaded.\n"));
surface = SDL_GetWindowSurface(window);
}
SDL_BlitSurface(media, NULL, surface, NULL);
SDL_UpdateWindowSurface(window);
/* ************************************** loop **************************** */
// bool to keep window open and event handler
bool quit = false;
SDL_Event e;
// loop to keep window open
while (!quit) {
while (SDL_PollEvent(&e) != 0) {
if (e.type == SDL_QUIT) {
quit = true;
}
else if (e.type == SDL_KEYDOWN) {
OutputDebugString(TEXT("My output string.\n"));
}
}
}
/* ************************************************************************** */
// close and destroy window
SDL_DestroyWindow(window);
// quit
SDL_Quit();
return 0;
}
I have a problem with SDL lib. I'm using VS2012 Ultimate and i was actually using this tutorial: http://lazyfoo.net/tutorials/SDL/01_hello_SDL/index2.php to set everything and i did it step by step few times, but I still have problems this is my code, very simple:
#include <iostream>
#include <SDL.h>
SDL_Surface * ekran = NULL;
int main (int argc, char *args [] )
{
SDL_Init( SDL_INIT_EVERYTHING );
ekran = SDL_SetVideoMode( 640, 480, 32, SDL_SWSURFACE );
SDL_Flip( ekran );
SDL_Delay( 2000 );
SDL_Quit();
return 0;
}
and im having this errors:
error C3861: 'SDL_SetVideoMode': identifier not found
error C3861: 'SDL_Flip': identifier not found
Here below is an example how to replace SDL_SetVideoMode() in SDL2. The old way to init SDL is commented and left along with the new way for comparison purposes. Basically, SDL2 creates a window with a title, then a surface attached to it, while SDL1 creates a surface alone and then calls the window manager to give it a name.
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "SDL video init failed: %s\n", SDL_GetError());
return 1;
}
// SDL_Surface *screenSurface = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_SWSURFACE);
SDL_Window* window = NULL;
SDL_Surface* screenSurface = NULL;
window = SDL_CreateWindow("Sphere Rendering",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL) {
fprintf(stderr, "Window could not be created: %s\n", SDL_GetError());
return 1;
}
screenSurface = SDL_GetWindowSurface(window);
if (!screenSurface) {
fprintf(stderr, "Screen surface could not be created: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
// SDL_WM_SetCaption("Sphere Rendering", NULL);
Take a look at that tutorial page again. Your code does not match it (e.g. SDL_SetVideoMode() no longer exists). Your code uses SDL 1.2 and the (updated) tutorial uses SDL 2.0. Are you using an old cached version of that page?
So I'm learning C++ with SDL (on Visual Studio 2013). I'm following Lazy Foo's tutorials (specifically: http://lazyfoo.net/tutorials/SDL/02_getting_an_image_on_the_screen/index.php).
My image won't render. In contrast to the tutorial (which works) I do not have global surface variables. Instead I declared them in the main and passed the pointers around.
Code:
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string>
const int SCREEN_WIDTH = 600;
const int SCREEN_HEIGHT = 480;
//SDL init.
bool initialiseSDL(SDL_Window* gWindow, SDL_Surface* gWindowSurface)
{
bool success = true;
/*SDL_Init() initisalises SDL library. Returning 0 or less signifies an error.
SDL_INIT_VIDEO flag refers to graphics sub system.*/
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialise. SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Create the window
gWindow = SDL_CreateWindow("Asteroids", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (gWindow == NULL)
{
printf("Could not create window. SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Get the window surface.
gWindowSurface = SDL_GetWindowSurface(gWindow);
}
}
return success;
}
bool loadMedia(SDL_Surface* surface, std::string path)
{
//Success flag
bool success = true;
surface = SDL_LoadBMP(path.c_str());
if (surface == NULL)
{
printf("SDL surface failed to load. SDL Error: %s\n", SDL_GetError());
success = false;
}
return success;
}
void close()
{
}
int main(int argc, char* argv[])
{
SDL_Window* gWindow = NULL;
SDL_Surface* gWindowSurface = NULL;
SDL_Surface* gImageSurface = NULL;
if (!initialiseSDL(gWindow, gWindowSurface))
{
printf("Failed to initialise.\n");
}
else
{
if (!loadMedia(gImageSurface, "hw.bmp"))
{
printf("Failed to load inital media.");
}
else
{
//Apply the image
SDL_BlitSurface(gImageSurface, NULL, gWindowSurface, NULL);
//Update the surface
SDL_UpdateWindowSurface(gWindow);
//Wait two seconds
SDL_Delay(2000);
}
}
return 0;
}
Your program exhibits undefined behavior, because the pointers inside the main function are not initialized.
When you pass them to the initialiseSDL function you pass them by value, meaning they are copied and the function only operates on the copies and not the original pointers, which will still be uninitialized after the call.
What you need to do is to pass the pointers by reference instead:
bool initialiseSDL(SDL_Window*& gWindow, SDL_Surface*& gWindowSurface)
You of course need to do the same with the loadMedia function.