I'm trying to display the string "hey" using a true type font in SDL, but there are glitches. Here is the text as it should appear (I took a screen recording, so the lower part in this shot is just the control for the video player):
And here it is with a glitch:
As you can see the upper part of the letter "h" is missing.
Here is the code that I used:
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <iostream>
#include <string>
int fatal( std::string m ) {
std::cout << "Fatal error: " << m << "\n";
exit(-1);
}
void drawText(TTF_Font* font,SDL_Renderer* r, std::string message) {
SDL_Color c = {255,255,255,255};
SDL_Surface *temp = TTF_RenderText_Blended( font, message.c_str(), c);
if ( temp == NULL )
fatal("failed to create surface");
SDL_Texture *txt = SDL_CreateTextureFromSurface( r, temp );
if ( txt == NULL )
fatal("failed to create texture");
SDL_FreeSurface( temp );
SDL_Rect src;
src.x = 0;
src.y = 0;
SDL_QueryTexture( txt, NULL, NULL, &src.w, &src.h );
SDL_Rect pos;
pos.x = 80;
pos.y = 80;
pos.w = src.w;
pos.h = src.h;
if ( SDL_RenderCopy(r,txt,&src,&pos) != 0)
fatal("SDL_RenderCopy failed");
SDL_DestroyTexture(txt);
}
extern "C" int main( int argc, char** argv ) {
SDL_Renderer *renderer;
SDL_Window *window;
if ( SDL_Init( SDL_INIT_VIDEO ) != 0 )
fatal("sdl_init failed");
if ( TTF_Init() != 0 )
fatal("ttf_init failed");
if ( SDL_CreateWindowAndRenderer ( 200, 200, 0, &window, &renderer ) != 0 )
fatal("sdl_createwindowandrenderer failed");
TTF_Font* font = TTF_OpenFont( "Arial.ttf", 30 );
if ( font == NULL )
fatal("failed to open font");
SDL_Event e;
while ( 1 ) {
if ( SDL_PollEvent(&e) ) {
if (e.type == SDL_QUIT)
break;
}
// clear back buffer
SDL_SetRenderDrawColor(renderer,0,0,255,255);
SDL_RenderClear(renderer);
drawText(font,renderer,"hey");
SDL_RenderPresent(renderer);
}
return 0;
}
Which I compiled on macOS 10.15.6 using the following command
g++ -std=c++17 textTest.cpp -lSDL2 -lSDL2_ttf
Related
I am new into SDL2(version 2.0.10) and I teach it from Lazy Foo tutorial. In Lesson of The ViewPort example code render me only first image in left viewport and others not. Render of rects in different viewports don't work either. What I am doing wrong when I want render rects in different viewports like this:
while( !quit ){
while( SDL_PollEvent( &e ) != 0 ){
if( e.type == SDL_QUIT ){
quit = true;
}
}
//Clear screen
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
SDL_RenderClear( gRenderer );
//Top left corner viewport
SDL_Rect topLeftViewport;
topLeftViewport.x = 0;
topLeftViewport.y = 0;
topLeftViewport.w = SCREEN_WIDTH / 2;
topLeftViewport.h = SCREEN_HEIGHT / 2;
SDL_RenderSetViewport( gRenderer, &topLeftViewport );
SDL_Rect fillRect = { 10, 10, 100, 100 };
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0x00, 0x00, 0xFF );
SDL_RenderFillRect( gRenderer, &fillRect );
SDL_Rect topRightViewport;
topRightViewport.x = SCREEN_WIDTH / 2;
topRightViewport.y = 0;
topRightViewport.w = SCREEN_WIDTH / 2;
topRightViewport.h = SCREEN_HEIGHT / 2;
SDL_RenderSetViewport( gRenderer, &topRightViewport );
SDL_Rect fillRect2 = { 10, 10, 100, 100 };
SDL_SetRenderDrawColor( gRenderer, 0x00, 0xFF, 0x00, 0xFF );
SDL_RenderFillRect( gRenderer, &fillRect2 );
SDL_RenderPresent( gRenderer );
}
As I saw, you are drawing a rect at 10, 10 of 100x100 two times, this coordinates doesn't take account of the viewport coordinates. And in a way, if you want to do this by changing the viewport clipping is not relevant... just draw the square where you want.
UPDATE: I tried multiples viewports. Here is a working example. You can choose between the renderer (with viewports) or the classic way.
main.cpp :
#include "Application.hpp"
int
main (int argc, char * argv[])
{
Application app("SDL 2 Test", 800, 600, true);
return app.mainLoop();
}
Application.hpp :
#ifndef APPLICATION_HPP
#define APPLICATION_HPP
#include <SDL2/SDL.h>
class Application
{
public:
Application (const char * title = "UnknownApplication", int baseWidth = 640, int baseHeight = 480, bool useRenderer = false) noexcept;
~Application ();
int mainLoop () noexcept;
private:
int m_width = 0;
int m_height = 0;
SDL_Window * m_window = nullptr;
SDL_Renderer * m_renderer = nullptr;
bool m_useRenderer = false;
bool m_isRunning = false;
};
#endif /* APPLICATION_HPP */
Application.cpp :
#include "Application.hpp"
#include <iostream>
#include <SDL2/SDL_image.h>
Application::Application (const char * title, int baseWidth, int baseHeight, bool useRenderer) noexcept
: m_width(baseWidth), m_height(baseHeight), m_useRenderer(useRenderer)
{
if ( SDL_Init(SDL_INIT_VIDEO) != 0 )
{
std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
return;
}
m_window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_width, m_height, SDL_WINDOW_SHOWN);
if ( m_window == nullptr )
{
std::cerr << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl;
return;
}
if ( m_useRenderer )
{
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);
if ( m_renderer == nullptr )
{
std::cerr << "Renderer could not be created! SDL_Error: " << SDL_GetError() << std::endl;
return;
}
}
m_isRunning = true;
}
int
Application::mainLoop () noexcept
{
SDL_Event event;
const auto filepath = "SET_IMAGE_YOU_WANT_HERE";
auto surface = IMG_Load(filepath);
if ( surface == nullptr )
{
std::cerr << "Unable to read image file : " << filepath << std::endl;
return 1;
}
SDL_Rect logoPosition = {8, 8, 32, 32};
if ( m_useRenderer )
{
auto texture = SDL_CreateTextureFromSurface(m_renderer, surface);
SDL_Rect screenA = {0, 0, m_width / 2, m_height / 2};
SDL_Rect screenB = {m_width / 2, 0, m_width / 2, m_height / 2};
while ( m_isRunning )
{
while ( SDL_PollEvent(&event) != 0 )
{
if ( event.type == SDL_QUIT )
m_isRunning = false;
}
SDL_SetRenderDrawColor(m_renderer, 0, 0, 0, 255);
SDL_RenderClear(m_renderer);
SDL_RenderSetViewport(m_renderer, &screenA);
SDL_SetRenderDrawColor(m_renderer, 255, 0, 0, 255);
SDL_RenderFillRect(m_renderer, nullptr);
SDL_RenderCopy(m_renderer, texture, nullptr, &logoPosition);
SDL_RenderSetViewport(m_renderer, &screenB);
SDL_SetRenderDrawColor(m_renderer, 0, 255, 0, 255);
SDL_RenderFillRect(m_renderer, nullptr);
SDL_RenderCopy(m_renderer, texture, nullptr, &logoPosition);
SDL_RenderPresent(m_renderer);
}
SDL_DestroyTexture(texture);
}
else
{
auto windowSurface = SDL_GetWindowSurface(m_window);
while ( m_isRunning )
{
while ( SDL_PollEvent(&event) != 0 )
{
if ( event.type == SDL_QUIT )
m_isRunning = false;
}
SDL_FillRect(windowSurface, nullptr, SDL_MapRGB(windowSurface->format, 0xFF, 0x00, 0xFF));
//SDL_BlitSurface(surface, nullptr, windowSurface, &logoPosition);
SDL_BlitScaled(surface, nullptr, windowSurface, &logoPosition);
SDL_UpdateWindowSurface(m_window);
}
}
SDL_FreeSurface(surface);
return 0;
}
Application::~Application (void)
{
if ( m_renderer != nullptr )
SDL_DestroyRenderer(m_renderer);
if ( m_window != nullptr )
SDL_DestroyWindow(m_window);
SDL_Quit();
}
I'm going through the tutorial on Lazyfoo: 'Beginning Game Programming'. I've just completed tutorial number 4.
My problem is as follows:
The code works fine apart from the line:
SDL_Surface* loadSurface( std::string path );
The error reads:
error: expected ')' before ':' token
I've come to the conclusion that the error might have something to do with the headers. It's possible I should add something to the SDL.h header.
I also added the stdbool.h header to fix a separate problem. I wonder if that has caused issues.
Here's the full code, which is just the tutorial code (EDIT: I've put the problematic line in bold)
(or at least those stars have gone around it. Doesn't appear to be bolding within the code. It's near the beginning, line 33):
//Using SDL and standard IO
#include <SDL.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
//Key press surfaces constants
enum KeyPressSurfaces
{
KEY_PRESS_SURFACE_DEFAULT,
KEY_PRESS_SURFACE_UP,
KEY_PRESS_SURFACE_DOWN,
KEY_PRESS_SURFACE_LEFT,
KEY_PRESS_SURFACE_RIGHT,
KEY_PRESS_SURFACE_TOTAL
};
//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;
//The images that correspond to a keypress
SDL_Surface* gKeyPressSurfaces[ KEY_PRESS_SURFACE_TOTAL ];
//Current displayed image
SDL_Surface* gCurrentSurface = 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 default surface
gKeyPressSurfaces[ KEY_PRESS_SURFACE_DEFAULT ] = loadSurface( "04_key_presses/press.bmp" );
if( gKeyPressSurfaces[ KEY_PRESS_SURFACE_DEFAULT ] == NULL )
{
printf( "Failed to load default image!\n" );
success = false;
}
//Load up surface
gKeyPressSurfaces[ KEY_PRESS_SURFACE_UP ] = loadSurface( "04_key_presses/up.bmp" );
if( gKeyPressSurfaces[ KEY_PRESS_SURFACE_UP ] == NULL )
{
printf( "Failed to load up image!\n" );
success = false;
}
//Load down surface
gKeyPressSurfaces[ KEY_PRESS_SURFACE_DOWN ] = loadSurface( "04_key_presses/down.bmp" );
if( gKeyPressSurfaces[ KEY_PRESS_SURFACE_DOWN ] == NULL )
{
printf( "failed to load down image!\n" );
success = false;
}
//Load left surface
gKeyPressSurfaces[ KEY_PRESS_SURFACE_LEFT ] = loadSurface( "04_key_presses/left.bmp" );
if( gKeyPressSurfaces[ KEY_PRESS_SURFACE_LEFT ] == NULL )
{
printf( "failed to load left image!\n" );
success = false;
}
//Load right surface
gKeyPressSurfaces[ KEY_PRESS_SURFACE_RIGHT ] = loadSurface( "04_key_presses/right.bmp" );
if( gKeyPressSurfaces[ KEY_PRESS_SURFACE_LEFT ] == NULL )
{
printf( "Failed to load left image!\n" );
success = false;
}
return success;
}
void close()
{
int i;
//Deallocate surface
for( i < KEY_PRESS_SURFACE_TOTAL; ++i; )
{
SDL_FreeSurface( gKeyPressSurfaces[ i ] );
gKeyPressSurfaces[ i ] = NULL;
}
//Destroy window
SDL_DestroyWindow( gWindow );
gWindow = NULL;
//Quit SDL subsystems
SDL_Quit();
}
SDL_Surface* loadSurface( std::string path )
{
//Load image at specified 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* 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;
//Set default current surface
gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_DEFAULT ];
//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;
}
//User presses a key
else if( e.type == SDL_KEYDOWN )
{
//Select surfaces based on key press
switch( e.key.keysym.sym )
{
case SDLK_UP:
gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_UP ];
break;
case SDLK_DOWN:
gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_DOWN ];
break;
case SDLK_LEFT:
gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_LEFT ];
break;
case SDLK_RIGHT:
gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_RIGHT ];
break;
default:
gCurrentSurface = gKeyPressSurfaces[ KEY_PRESS_SURFACE_DEFAULT ];
break;
}
}
}
//Apply the current image
SDL_BlitSurface( gCurrentSurface, NULL, gScreenSurface, NULL );
//Update the surface
SDL_UpdateWindowSurface( gWindow );
}
}
}
//Free resources and close SDL
close();
return 0;
}
Try:
#include <string>
instead of:
#include <string.h>
As already pointer out, you should try including C++'s string.
#include <string>
However, if that's your problem, the compiler should have said string is not in the std namespace.
To me it looks like the compiler doesn't know about the :: namespace operator.
The possible cause is that you're using a C compiler instead of a C++ compiler.
C doesn't have a notion of namespace, and it has no std::string.
Make sure your source file's extension is a C++ one (like .cpp) as opposed to C (.c).
Depending on your compiler, you might need to tell it you mean C++ and not C.
If you're using gcc, try g++ instead.
My Makefile -
all:
g++ main.cpp -I/usr/local/include -L/usr/local/lib -lSDL2 -lSDL_image
My Code I am using as taken from a tutorial -
/*This source code copyrighted by Lazy Foo' Productions (2004-2013) */
//Using SDL, SDL_image, standard IO, and strings
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
#include <string>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
//Texture wrapper class
class LTexture
{
public:
//Initializes variables
LTexture();
//Deallocates memory
~LTexture();
//Loads image at specified path
bool loadFromFile( std::string path );
#ifdef _SDL_TTF_H
//Creates image from font string
bool loadFromRenderedText( std::string textureText, SDL_Color textColor );
#endif
//Deallocates texture
void free();
//Set color modulation
void setColor( Uint8 red, Uint8 green, Uint8 blue );
//Set blending
void setBlendMode( SDL_BlendMode blending );
//Set alpha modulation
void setAlpha( Uint8 alpha );
//Renders texture at given point
void render( int x, int y, SDL_Rect* clip = NULL, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE );
//Gets image dimensions
int getWidth();
int getHeight();
private:
//The actual hardware texture
SDL_Texture* mTexture;
//Image dimensions
int mWidth;
int mHeight;
};
//The application time based timer
class LTimer
{
public:
//Initializes variables
LTimer();
//The various clock actions
void start();
void stop();
void pause();
void unpause();
//Gets the timer's time
Uint32 getTicks();
//Checks the status of the timer
bool isStarted();
bool isPaused();
private:
//The clock time when the timer started
Uint32 mStartTicks;
//The ticks stored when the timer was paused
Uint32 mPausedTicks;
//The timer status
bool mPaused;
bool mStarted;
};
//The dot that will move around on the screen
class Dot
{
public:
//The dimensions of the dot
static const int DOT_WIDTH = 20;
static const int DOT_HEIGHT = 20;
//Maximum axis velocity of the dot
static const int DOT_VEL = 10;
//Initializes the variables
Dot();
//Takes key presses and adjusts the dot's velocity
void handleEvent( SDL_Event& e );
//Moves the dot
void move();
//Shows the dot on the screen
void render();
private:
//The X and Y offsets of the dot
int mPosX, mPosY;
//The velocity of the dot
int mVelX, mVelY;
};
//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 window renderer
SDL_Renderer* gRenderer = NULL;
//Scene textures
LTexture gDotTexture;
LTexture::LTexture()
{
//Initialize
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
LTexture::~LTexture()
{
//Deallocate
free();
}
bool LTexture::loadFromFile( std::string path )
{
//Get rid of preexisting texture
free();
//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
{
//Color key image
SDL_SetColorKey( loadedSurface, SDL_TRUE, SDL_MapRGB( loadedSurface->format, 0, 0xFF, 0xFF ) );
//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() );
}
else
{
//Get image dimensions
mWidth = loadedSurface->w;
mHeight = loadedSurface->h;
}
//Get rid of old loaded surface
SDL_FreeSurface( loadedSurface );
}
//Return success
mTexture = newTexture;
return mTexture != NULL;
}
#ifdef _SDL_TTF_H
bool LTexture::loadFromRenderedText( std::string textureText, SDL_Color textColor )
{
//Get rid of preexisting texture
free();
//Render text surface
SDL_Surface* textSurface = TTF_RenderText_Solid( gFont, textureText.c_str(), textColor );
if( textSurface != NULL )
{
//Create texture from surface pixels
mTexture = SDL_CreateTextureFromSurface( gRenderer, textSurface );
if( mTexture == NULL )
{
printf( "Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError() );
}
else
{
//Get image dimensions
mWidth = textSurface->w;
mHeight = textSurface->h;
}
//Get rid of old surface
SDL_FreeSurface( textSurface );
}
else
{
printf( "Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
}
//Return success
return mTexture != NULL;
}
#endif
void LTexture::free()
{
//Free texture if it exists
if( mTexture != NULL )
{
SDL_DestroyTexture( mTexture );
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
}
void LTexture::setColor( Uint8 red, Uint8 green, Uint8 blue )
{
//Modulate texture rgb
SDL_SetTextureColorMod( mTexture, red, green, blue );
}
void LTexture::setBlendMode( SDL_BlendMode blending )
{
//Set blending function
SDL_SetTextureBlendMode( mTexture, blending );
}
void LTexture::setAlpha( Uint8 alpha )
{
//Modulate texture alpha
SDL_SetTextureAlphaMod( mTexture, alpha );
}
void LTexture::render( int x, int y, SDL_Rect* clip, double angle, SDL_Point* center, SDL_RendererFlip flip )
{
//Set rendering space and render to screen
SDL_Rect renderQuad = { x, y, mWidth, mHeight };
//Set clip rendering dimensions
if( clip != NULL )
{
renderQuad.w = clip->w;
renderQuad.h = clip->h;
}
//Render to screen
SDL_RenderCopyEx( gRenderer, mTexture, clip, &renderQuad, angle, center, flip );
}
int LTexture::getWidth()
{
return mWidth;
}
int LTexture::getHeight()
{
return mHeight;
}
Dot::Dot()
{
//Initialize the offsets
mPosX = 0;
mPosY = 0;
//Initialize the velocity
mVelX = 0;
mVelY = 0;
}
void Dot::handleEvent( SDL_Event& e )
{
//If a key was pressed
if( e.type == SDL_KEYDOWN && e.key.repeat == 0 )
{
//Adjust the velocity
switch( e.key.keysym.sym )
{
case SDLK_UP: mVelY -= DOT_VEL; break;
case SDLK_DOWN: mVelY += DOT_VEL; break;
case SDLK_LEFT: mVelX -= DOT_VEL; break;
case SDLK_RIGHT: mVelX += DOT_VEL; break;
}
}
//If a key was released
else if( e.type == SDL_KEYUP && e.key.repeat == 0 )
{
//Adjust the velocity
switch( e.key.keysym.sym )
{
case SDLK_UP: mVelY += DOT_VEL; break;
case SDLK_DOWN: mVelY -= DOT_VEL; break;
case SDLK_LEFT: mVelX += DOT_VEL; break;
case SDLK_RIGHT: mVelX -= DOT_VEL; break;
}
}
}
void Dot::move()
{
//Move the dot left or right
mPosX += mVelX;
//If the dot went too far to the left or right
if( ( mPosX < 0 ) || ( mPosX + DOT_WIDTH > SCREEN_WIDTH ) )
{
//Move back
mPosX -= mVelX;
}
//Move the dot up or down
mPosY += mVelY;
//If the dot went too far up or down
if( ( mPosY < 0 ) || ( mPosY + DOT_HEIGHT > SCREEN_HEIGHT ) )
{
//Move back
mPosY -= mVelY;
}
}
void Dot::render()
{
//Show the dot
gDotTexture.render( mPosX, mPosY );
}
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
{
//Enable VSync
if( !SDL_SetHint( SDL_HINT_RENDER_VSYNC, "1" ) )
{
printf( "Warning: VSync not enabled!" );
}
//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 dot texture
if( !gDotTexture.loadFromFile( "26_motion/dot.bmp" ) )
{
printf( "Failed to load dot texture!\n" );
success = false;
}
return success;
}
void close()
{
//Free loaded images
gDotTexture.free();
//Destroy window
SDL_DestroyRenderer( gRenderer );
SDL_DestroyWindow( gWindow );
gWindow = NULL;
gRenderer = NULL;
//Quit SDL subsystems
IMG_Quit();
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
{
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//The dot that will be moving around on the screen
Dot dot;
//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;
}
//Handle input for the dot
dot.handleEvent( e );
}
//Move the dot
dot.move();
//Clear screen
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
SDL_RenderClear( gRenderer );
//Render objects
dot.render();
//Update screen
SDL_RenderPresent( gRenderer );
}
}
}
//Free resources and close SDL
close();
return 0;
}
My Error -
g++ main.cpp -I/usr/local/include -L/usr/local/lib -lSDL2 -lSDL_image.lib
ld: library not found for -lSDL_image.lib
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [all] Error 1
I am unable to get this to load. I used brew to install SDL2_image and it appears to exist in usr/local/lib and such. I see libSDL_image.a and other assorted items.
Can someone please tell me how to edit my makefile for mac so that I can compile the code I am attempting to use. I am not sure why -lSDL_image would not work as it should do so.
To load SDL_image it should be
-lSDL_image
but your not using SDL 1.X your are using SDL 2 so it should be
-lSDL2_image
If it still says that it can't find it then you need to make sure it is in a path that ld searches in.
-L/Path/To/SDL_image
If that still doesn't work make sure that you have the development library and not just the runtime binaries
You can grab the development libraries for SDL_image here : http://www.libsdl.org/projects/SDL_image/
I have a project that uses SDL 1.2 and want to migrate it to SDL 2.0. To keep things simple I tried writing a simple program just to get familiar with the changes.
However, SDL_CreateWindow is failing, and SDL_GetError is not showing anything. So I don't know why creating the window isn't working.
The window is actually created, but then disappears.
#include <SDL.h>
#include <stdio.h> // printf etc
#include <stdlib.h> // abs, malloc, realloc
#include <stdint.h> // uint8_t, uint16_t, int32_t
#define WIDTH 853
#define HEIGHT 480
int main(int argc, char** argv) {
SDL_Renderer* renderer;
SDL_Window* window;
SDL_Texture* screenTexture;
SDL_Event event;
Uint8* screenBuffer;
FILE* fp;
int quit = 0;
fp = fopen("SDL2test.log", "w");
if (!fp) {
printf("\nCould not create log file");
return -1;
}
if (SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(fp, "\nCould not initialise SDL: %s\n", SDL_GetError() );
return -2;
}
window = NULL;
if ( NULL == ( window = SDL_CreateWindow("SDL2 test",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, 0)));{
fprintf(fp, "Could not create SDL window: %s\n", SDL_GetError() );
SDL_Delay(3000);
SDL_Quit();
return -3;
}
if ( !( renderer = SDL_CreateRenderer(window, -1, 0) ) ); {
SDL_Quit();
return -4;
}
if ( !( screenTexture = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STATIC, WIDTH, HEIGHT)));
screenBuffer = (Uint8*)malloc( sizeof(Uint8) * 3 * WIDTH * HEIGHT );
if (NULL == screenBuffer){
SDL_Quit();
return -5;
}
memset(screenBuffer, 0, 3 * WIDTH * HEIGHT); //set to black
SDL_UpdateTexture( screenTexture,
NULL,
screenBuffer,
WIDTH * sizeof(Uint8) );
while( !quit && ( SDL_WaitEvent(&event) ) ) {
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, screenTexture, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_Delay(3000);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
This is your create window if statement:
if ( NULL == ( window = SDL_CreateWindow( ...code... ) ) ); //what is ; doing here
{
fprintf(fp, "Could not create SDL window: %s\n", SDL_GetError() );
SDL_Delay(3000);
SDL_Quit();
return -3;
}
Did you notice the ; at the end of first line?
This means the part of the code in the brackets gets executed every time. Basically the code looks like this:
if ( NULL == ( window = SDL_CreateWindow( ...code... ) ) ); //end of if
{ //gets executed every time
fprintf(fp, "Could not create SDL window: %s\n", SDL_GetError() );
SDL_Delay(3000);
SDL_Quit();
return -3;
}
There is at least one such error in the code.
#include "SDL/SDL.h"
#include "SDL/SDL_Image.h"
#include <string>
using namespace std;
//Const screen variables
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
const char* SCREEN_CAPTION = "Pyro";
const float GRAVITY = 9.8; //Metres per second **NEEDS TO BE ADJUSTED BECAUSE IT'S IN METRES, NOT PIXELS**
const int jumpHeight = 10;
//Non-Const variables
bool running = true;
bool isJumping = true;
int jump = 0;
int frame = 0;
int level = 1;
SDL_Event event;
Uint8 *keystate = NULL;
//SDL Surfaces
SDL_Surface *screen = NULL;
SDL_Surface *background = NULL;
SDL_Surface *sprite = NULL;
SDL_Surface *bEnemy[10];
//Structs
typedef struct entity {
int health;
int damage;
SDL_Rect hitbox;
bool evolved;
} playerType, enemyType;
playerType player;
enemyType basicEnemy[10];
//Functions
SDL_Surface *loadImage( std::string filename )
{
SDL_Surface *loadedImage = NULL;
SDL_Surface *optimizedImage = NULL;
loadedImage = IMG_Load( filename.c_str() );
if( loadedImage != NULL )
{
optimizedImage = SDL_DisplayFormatAlpha( loadedImage );
SDL_FreeSurface( loadedImage );
}
return optimizedImage;
}
void applySurface( int x, int y, SDL_Surface* source, SDL_Surface* location )
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface( source, NULL, location, &offset );
}
//Main Function
int main( int argc, char* argv[] )
{
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
return 1;
}
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
if( screen == NULL )
{
return 1;
}
SDL_WM_SetCaption( SCREEN_CAPTION, NULL );
background = loadImage( "images/background.png" );
sprite = loadImage( "images/player.png" );
SDL_FreeSurface( sprite );
SDL_FreeSurface( background );
while( running )
{
//Main game loop
if( SDL_PollEvent( &event ) )
{
switch( event.type )
{
case SDL_QUIT:
running = false;
break;
case SDL_KEYDOWN:
switch( event.key.keysym.sym )
{
case SDLK_q:
running = false;
break;
}
break;
}
}
keystate = SDL_GetKeyState(NULL);
if( keystate[SDLK_q] ) player.evolved = !player.evolved;
if( keystate[SDLK_UP] )
{
if(isJumping != true)
{
isJumping = true;
}
}
if( keystate[SDLK_LEFT] ) player.hitbox.x -= 1;
if( keystate[SDLK_RIGHT] ) player.hitbox.y += 1;
//Window collision
if( player.hitbox.x < 0 ) {player.hitbox.x = 0;}
else if( player.hitbox.x > SCREEN_WIDTH - player.hitbox.w ) {player.hitbox.x = SCREEN_WIDTH - player.hitbox.w;}
if( player.hitbox.y < 0 ) {player.hitbox.y = 0;}
else if( player.hitbox.y > SCREEN_HEIGHT - player.hitbox.h ) {player.hitbox.y = SCREEN_HEIGHT - player.hitbox.h;}
//Jumping
if( isJumping == true )
{
if(jump >= jumpHeight)
{
jump--;
player.hitbox.y++;
}else {
jump++;
player.hitbox.y--;
}
}
//Updating the screen
applySurface( 0, 0, background, screen );
applySurface( player.hitbox.x, player.hitbox.y, sprite, screen );
if( SDL_Flip( screen ) == -1 )
{
return 1;
}
}
SDL_Quit();
return 0;
}
^ That is the exact code I have. When I run the file it immediately closes. It is compiled with: g++ -o myprogram.exe mysource.cpp -lmingw32 -lSDLmain -lSDL -lSDL_image -static-libgcc -static-libstdc++.
The files I have linked to do exist; they are currently placeholders (background is some random png image I found, and the player is an image of 8-bit mario).
How do I stop my program from closing immediately?
SDL_FreeSurface( sprite );
SDL_FreeSurface( background );
This is where your problem lies.
These lines should appear at the end of the program right before you call SDL_Quit().
Currently, you're blitting freed surfaces onto the window.