cannot display texture in SDL 2 - c++

I'm trying to display a texture onto the screen but all I'm getting is a black window.
No SDL Errors are being reported. There's a good chance that I'm missing something stupid, but I can't see it. Hopefully another set of eyes will help. Feel free to ask for more code/info.
main.cpp
SDL_Window * window;
SDL_Renderer * renderer;
SDL_Texture * grass;
SDL_Rect g_dst;
SDL_Event event;
Game app;
SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("tmp", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
g_dst.x = g_dst.y = 0;
g_dst.w = 640;
g_dst.h = 480;
grass = IMG_LoadTexture(renderer, "grass.bmp");
while (app.isRunning()) {
app.pollEvents(&event);
app.render_init();
app.render(grass, NULL, &g_dst);
app.render_end();
}
//SDL_Quit() is handled by the Game class' destructor
Game.cpp
//Only functions used for rendering are shown
void render_init(Uint8 red=0, Uint8 green=0, Uint8 blue=0, Uint8 alpha=255)
{
SDL_SetRenderDrawColor(renderer, red, green, blue, alpha);
SDL_RenderClear(renderer);
}
void render(SDL_Texture * texture, SDL_Rect * src, SDL_Rect * dest) {
SDL_RenderCopy(renderer, texture, src, dest);
}
void render_end() { SDL_RenderPresent(renderer); }

First of all, you're initializing everything? please don't do that frequently, mind you that you're also initializing MANY unnecessary stuffs like for game controllers, etc. if the app gets bigger then the efficiency and the possibility of this app running at a smoot speed is at stake.
I also noticed that you are declaring variables in the .cpp file, do that in the header file and just recall the header to the cpp file that will be using it.
You want to render the grass right? and render it as much as the screens size.
(I'll just assume that you used this in the game.cpp part, which is the very first file, thus, not regarding any classes made)
int winWidth = 680; //The reason for this is just in case you make the window resizable
int winHeight = 480; //then the texture would also resize along with the window
SDL_Window *window = window = SDL_CreateWindow("The Space Project", 100, 100, winWidth, winHeight, SDL_WINDOW_SHOWN);
SDL_Renderer *renderer = NULL; //I've set this to NULL so that we can know if
the reason as to why your image is not rendering is because the renderer is not properly working.
renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED);
if(renderer == NULL)
{
cout >> "Renderer is not working" >> endl;
//This shows a line at the command prompt that your renderer doesn't have any output, thus, only having a NULL as an equivalent
}
SDL_Texture* grass= NULL;
grass= IMG_LoadTexture(renderer, "grass.bmp"); //As you can see, I've set the grass to Null again
if(grass == NULL)
{
cout >> "Grass have failed to initialize" >> endl;
/*I don't normally do this but it's very important if you really need trouble shooting guides
but this time, were here to check IF the grass.bmp entered the SDL_Texture grass, so if the system can't find the .bmp file then it would show this error
since the grass (SDL_Texture) still doesn't have anything inside it (NULL)*/
}
SDL_Rect grass_rect;
grass_rect.x = 0;
grass_rect.y = 0;
grass_rect.w = winWidth;
grass_rect.h = winHeight;
//Loop part, I'll skip some of it
while (!quit && mainEvent->type != SDL_QUIT) //!quit is just an imaginary Boolean I've typed)
{
SDL_PollEvent(mainEvent); //Let's say you created the event already
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, grass, NULL, &grass_rect);
//The NULL part is also similar to a rect but it's a limiting type, we didn't assign anything to it
since I assumed that you wanted the whole image to be rendered
SDL_RenderPresent(renderer);
}
I revised the code and made it more efficient since your code called for useless extras which might result in lower performance.
I also notice that you tried calling for color changes?
use this
SDL_SetTextureColorMod(texture, red-value, green-value, blue-value);
and put it in the loops part under the render present of the same texture.
SDL_SetTextureColorMod(grass, 250, 250, 250);
Doing this would set all color values to 250, thus, having a white color, this change your texture color to white.
You're also wasting space on making the app.is running(), you could easily replace it with a boolean, which consumes much less space or you could omit it if you don't have an exit button inside the application and just make your loop read the SDL_QUIT, this saves space for the file, mind the efficiency.
If this still doesn't work then try replacing the image your using, make a simple one on paint name it something like "grass.png" or anything then try it again.
Don't forget to put the file in the proper folder, in the DEBUG folder if you haven't specified a folder, and also put it in the app folder so it would also read it when it executes as an .exe file and not as part of the debug command.

Related

SDL Window causes mouse to freeze every few seconds

Every time I attempt to run my application it creates a window perfectly fine but when moving the mouse about it becomes obvious that it freezes briefly for a few seconds. I also had this issue in a previous SDL project but didn't fix it as it wasn't very vital but I could never find a solution for it.
I tried looking up my issue but couldn't find anything that matches the issue I'm facing, despite this I attempted a few things that I felt could work like slightly different implementations of an event loop.
I'm not 100% sure on what EVERY line of SDL related code does but I took it from a previous project so I knew what it did at one point but it's not too hard to work out.
int width = 160;
int height = 144;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Window Title", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width * 4, height * 4, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
bool quit = false;
while (!quit)
{
SDL_Event E;
while (SDL_PollEvent(&E))
{
if (E.type == SDL_QUIT)
quit = true;
}
}
I expect the window to display smoothly and not have this freezing occur every few seconds. I'm not sure if it only occurs when the mouse is moving or if it happens to freeze every few seconds despite this as the cursor is the only way I have to test it. I saw one post that talked about flooding the event queue but that solution didn't seem to work for me.
Any help is appreciated.

How to display a image on a user defined rectangle with SDL_surface?

Im working on a project with my friend and we have run into an issue with surfaces and windows in SDL.
Currently we are able to create a window and display a rectangle on that window and move it around. The next thing we want to do is take a image and display it on a rectangle and then move it around the screen.
We started with taking the SDL_window* and turning it into SDL_surface* though this would take the image and display it on the background of the window.
Is there a way to turn a rectangle we create into a surface and display the image on that rectangle?
I have also tried using textures and it distorts the image when I tried to move it and the whole image doesn’t move with the rectangle.
// this happens in the constructor
temp_image_sur = IMG_Load( image_location.c_str() );
if( temp_image_sur == NULL )
{
std::cout << "Image could not be loaded" <<std::endl;
exit(1);
}
// This is in the actual draw function.
display_surface = SDL_GetWindowSurface( display_window );
if(display_surface == NULL )
{
printf(" null im exiting here %s\n", SDL_GetError());
exit(1);
}
image_surface = SDL_ConvertSurface( temp_image_sur, display_surface->format, 0 );
image_size = { this->location.x, this->location.y, this->size.width, this->size.height };
SDL_BlitSurface( image_surface, &image_size, display_surface, &image_size );
This is what we did for our first attempt, and the image was displaying on the base window. I believe I understand why it is displaying on the base window, it is because we are using that window as the surface, though I'm confused how do I make a user defined rectangle the surface?
We did try using SDL_CreateRGBSurface, though nothing is being displayed on the screen when we do this either.
display_surface = SDL_CreateRGBSurface(0, this->size.width, this->size.height, 1, this->color.red, this->color.green, this->color.blue, this->color.alpha);
Thanks guys!
Please let me know if there is anymore information you need, this is my first time posting and I tried to put all the info that I could think of.
Create a texture from your image surface by using SDL_CreateTextureFromSurface:
SDL_Texture* image_surface = SDL_CreateTextureFromSurface(renderer, temp_image_sur);
(remember to free it with SDL_DestroyTexture)
then use SDL_RenderCopy to draw it:
SDL_RenderCopy(renderer, image_texture, nullptr, &image_rect);
where image_rect is a SDL_Rect and the destination rectangle you want to draw your image to, for example:
SDL_rect image_rect = {10, 10, 200, 200};
To move your image simply change image_rect.x and/or image_rect.y

SDL will only draw a black screen when trying to print a picture C++

class Game {
public:
Game(int width, int height) {
gwidth = width;
gheight = height;
}
~Game() {
}
bool initGame() {
bool sucsess = true;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
sucsess = false;
}
//gTetrisSurface = SDL_LoadBMP("TetrisBg.bmp");
gWindow = SDL_CreateWindow("Petris V1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, gwidth, gheight, SDL_WINDOW_SHOWN);
gScreenSurface = SDL_GetWindowSurface(gWindow);
gMainBG = SDL_LoadBMP("test.bmp");
/**if (gMainBG == NULL) {
return false;
}**/
bool running = true;
//SDL_SetWindowFullscreen(gWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
while (running == true) {
SDL_BlitSurface(gMainBG, NULL, gScreenSurface, NULL);
SDL_UpdateWindowSurface( gWindow );
}
return sucsess;
}
protected:
int gwidth, gheight;
SDL_Window* gWindow = NULL;
SDL_Surface* gScreenSurface = NULL;
SDL_Surface* gTetrisSurface = NULL;
SDL_Surface* gPongSurface = NULL;
SDL_Surface* gMainBG = NULL;
};
The thought behind this, is that this should be one huge surface, containing 2 other surfaces for 2 other games. Problem is, it wont seem to draw the BMP that i try to draw on it. Because of this my development got kinda stuck. Anyone see a possible sulotion for this problem? Thanks!
EDIT: I made it so it flushes the events, BUT, i did a bit of debugging, the problem seems to be that the img file returns NULL, why? It should be loaded with a bmp... (No error messages at all..)
From the documentation of SDL2:
https://wiki.libsdl.org/SDL_GetWindowSurface
This surface will be invalidated if the window is resized. After resizing a window this function must be called again to return a valid surface.
You may not combine this with 3D or the rendering API on this window.
My advice is to avoid using the window surface directly.
Instead, you should use a renderer and copy your own main surface to your background texture.
The SDL2 migration guide explains clearly the right way to copy surfaces and textures on the screen, especially the paragraph "If your game wants to do both".
The whole problem was that the BMP file was in the wrong folder.
If anyone have the same problem, the picture should either be in the same directory as the src (when debugging) or the solution (if building).
Hope this might help someone in the future, either way, thanks to those who tried coming up with other possibilites.
(Using visual studio)

Why am I unable to draw to a texture in SDL2?

I've been working on a project in SDL on nights and weekends for the past few months. I'm currently trying to get a menu system working. At the moment, I'm working on drawing text using SDL_TTF. As for my question, I'm seeing some strange behavior when I try to draw some textures to another texture.
The weirdness is that when I draw it, on a destination texture created with SDL_TEXTUREACCESS_TARGET (like it says to do in the docs) draws nothing, but returns no error. However, if I use SDL_TEXTUREACCESS_STATIC or SDL_TEXTUREACCESS_STREAM, it returns an error when I set the render target because of the access attribute, but draws just fine. After doing some digging, I heard some things about a bug in the Intel drivers (I'm on a Macbook with Intel graphics), so I was wondering if this was something I messed up, and how I might fix it. Alternately, if it isn't my fault, I'd still like to know what's going on, and if it would perform differently on different platforms and how I could work around it.
Here's my code, after removing unnecessary parts and :
I create the renderer:
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
Later on, when I go to render onto a canvas:
TTF_Font *fnt = loadFont(fontName.c_str(), fontSize);
In here I parse out some attributes and set them using TTF_SetFontStyle() and the clr for text color.
SDL_Texture *canvas;
canvas = SDL_CreateTexture(rendy, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, contentRect.w, contentRect.h)
SDL_SetRenderTarget(rendy, canvas);
int pos = 0;
for (list<string>::iterator itr = lines.begin(); itr != lines.end(); itr++){
SDL_Surface *temp;
temp = TTF_RenderText_Blended(fnt, src.c_str(), clr);
SDL_Texture *line;
line = SDL_CreateTextureFromSurface(rendy, temp);
int w,h;
SDL_QueryTexture(line, NULL, NULL, &w, &h);
SDL_Rect destR;
//Assume that we're left justified
destR.x = 0;
destR.y = pos;
destR.w = w;
destR.h = h;
SDL_RenderCopy(rendy, line, NULL, &destR);
SDL_DestroyTexture(line);
SDL_FreeSurface(temp);
pos += TTF_FontLineSkip(fnt);
}
//Clean up
SDL_SetRenderTarget(rendy, NULL);
canvas gets returned to the calling function so it can be cached until this text box is modified. That function works by having a texture for the whole box, drawing a background texture onto it, and then drawing this image on top of that, and holding on to the whole thing.
That code looks like this:
(stuff to draw the background, which renders fine)
SDL_Texture *sum = SDL_CreateTexture(rendy, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, globalRect.w, globalRect.h);
SDL_SetTextureBlendMode(sum, SDL_BLENDMODE_BLEND);
SDL_SetRenderTarget(rendy, sum);
string lPad = getAttribute(EL_LEFT_PADDING);
string tPad = getAttribute(EL_TOP_PADDING);
int paddingL = strtol(lPad.c_str(), NULL, 10);
int paddingT = strtol(tPad.c_str(), NULL, 10);
SDL_Rect destR;
SDL_Rect srcR;
srcR.x = 0;
srcR.y = 0;
srcR.w = globalRect.w; //globalRect is the size size of the whole button
srcR.h = globalRect.h;
destR.x = 0;
destR.y = 0;
destR.w = globalRect.w;
destR.h = globalRect.h;
SDL_RenderCopy(rendy, bgTexture, NULL, &destR);
int maxX = contentRect.w;
fgTexture = getFGImage(rendy); //The call to the previous part
int w, h;
SDL_QueryTexture(fgTexture, NULL, NULL, &w, &h);
int width, height;
getTextSize(&width, &height, maxX);
srcR.x = 0;
srcR.y = 0;
srcR.w = width;
srcR.h = height;
destR.x = paddingL;
destR.y = paddingT;
destR.w = globalRect.w;
destR.h = globalRect.h;
SDL_RenderCopy(rendy, fgTexture, NULL, &destR);
SDL_DestroyTexture(fgTexture);
SDL_DestroyTexture(bgTexture);
return sum;
Sum is returned to another function which does the drawing.
Thanks in advance!
Update
So I've figured out that the reason it only drew when I had the incorrect access setting was that, since the function was returning an error value, the render target was never set to the texture, so it was just drawing on the screen. I've also checked all my textures by writing a function AuditTexture which checks to see that the texture format for a texture is supported by the renderer, prints a string description of the access attribute, and prints the dimensions. I now know that all of their texture formats are supported, the two lines are static, canvas and sum are render targets, and none of them have dimensions of zero.
As it turns out, I had set the render target to be the composite texture, then called my function which set the render target to the text texture before drawing text. Then when I returned from the function, the render target was still the text texture instead of the composite one, so I basically drew the text over itself instead of drawing over the background.
A word to the wise: Don't ever assume something is taken care of for you, especially in c or c++.

SDL loading my image messed up

I'm attemting to load an image that I exported from flash CS3 it's a very cute face but it loads very weird it loads on a blueish way this is the code for the two files:
//main.cpp
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "test.hpp"
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_VIDEO);
// Activamos modo de video
screen = SDL_SetVideoMode(640,480,32,SDL_SWSURFACE | SDL_DOUBLEBUF);
image = IMG_Load("face.bmp");
dest.x = 200;
dest.y = 200;
//Main Loop
while(Abierto)
{
//We Draw
Draw();
//Events
while( SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
Abierto = false;
}
}
// We free the image
SDL_FreeSurface(image);
SDL_Quit();
return 0;
}
Now the other one the;
//test.hpp
DL_Surface *image = NULL, *screen = NULL;
SDL_Rect dest;
SDL_Event event;
bool Abierto = true;
float PlaneX = 300, PlaneY = 200;
float velX = 0.1, velY = 0.1;
void Draw()
{
Uint32 color;
// Black Background is created
color = SDL_MapRGB (screen -> format, 0, 0, 0);
SDL_FillRect (screen, NULL, color);
SDL_DisplayFormatAlpha(image);
SDL_BlitSurface(image, NULL, screen, &dest);
// Flip the working image buffer with the screen buffer
SDL_Flip (screen);
}
I need help with this please Im not that experienced on SDL stuff oh and if you want to take a closer look I uplaoded the project here.
Oh my bad I must add the image is 32 pixels with alpha according to flash exporting options
According to docs, SDL_DisplayFormatAlpha returns a new image and keeps the original intact.
So, try in the first part, when you load the image:
SDL_Surface *origImage = IMG_Load("face.bmp");
image = SDL_DisplayFormatAlpha(origImage);
SDL_FreeSurface(origImage)
As there is no need to call SDL_DisplayFormatAlpha each frame.
Then in the second part, just blit image, without calling SDL_DisplayFormatAlpha.
UPDATE
I've just checked your picture, and it looks like it is a weird bmp. I've seen that before: BMP format is such a mess that if you don't keep to the basics chances are that different programs will interpret the data differently.
In your case:
display face.bmp shows correctly.
gthumb face.bmp shows nothing.
eog face.bmp says "bogus header data".
I strongly recommend using PNG files for all your game cartoon-like pictures and JPG for all the photo-like ones.
So run
$ convert face.bmp face.png
And use the PNG file. I'll will work better and you will have a file 20% the size of the original.