I keep getting this issue when I run my program. My images fail to load in with the error: "Invalid texture". The program used to work fine. I'm working on it in linux ubuntu with all of my drivers updated. Here is the code where the renderer is made and the images are loaded.
//init.h
//#pragma once
#ifndef INIT_H
#define INIT_H
static const int SCREEN_WIDTH = 480;
static const int SCREEN_HEIGHT = 480;
static SDL_Surface* currentSurface = NULL;
static SDL_Window* window = NULL;
static SDL_Surface* screenSurface = NULL;
static SDL_Renderer* renderer = NULL;
//static SDL_Surface *SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 0, SDL_ANYFORMAT);
bool init();
void close();
//void SetColor(int value);
#endif // INIT_H
//init.cpp
//#include "stdafx.h"
#include <stdio.h>
#include "tchar.h"
#include <SDL2/SDL.h>
#include <iostream>
#include <SDL2/SDL_image.h>
#include "main.h"
#include "init.h"
#include "load.h"
//#include <conio.h>
//#include <Windows.h>
#include <string>
#include <SDL2/SDL_ttf.h>
#include <cmath>
bool init()
{
bool boot = 1;
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
//SetColor(4);
printf("SDL failed to initialize \n");
//SetColor(7);
boot = 0;
}
else {
printf("SDL initialized!\n");
window = SDL_CreateWindow("Light Development Project", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (window == NULL)
{
//SetColor(4);
printf("SDL failed to create the window \n");
//SetColor(7);
boot = 0;
}
else {
printf("Window created!\n");
//screenSurface = SDL_GetWindowSurface(window);
printf("Screen surface created!\n");
}
printf("Initializing SDL_image...\n");
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
{
//SetColor(4);
printf("Failed to initialize SDL_image\n");
//SetColor(7);
boot = 0;
}
else {
printf("SDL_image initialized!\n");
}
printf("Initializing TTF...\n");
if (TTF_Init() == -1)
{
//SetColor(4);
printf("Failed to initialize TTF\n");
//SetColor(7);
boot = 0;
}
else {
printf("TTF initialized!\n");
}
printf("Creating renderer...\n");
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL)
{
//SetColor(4);
printf("Failed to create renderer. Error: %s\n", SDL_GetError());
//SetColor(7);
boot = 0;
} else
printf("Renderer created!\n");
printf("Setting render draw color...\n");
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
printf("Render draw color set!\n");
}
//printf("Done!\n");
return boot;
}
void close()
{
printf("\nShutting down...\nFreeing SDL surfaces...\nDetroying textures and renderers...\n");
SDL_DestroyTexture(texture);
texture = NULL;
SDL_DestroyRenderer(renderer);
renderer = NULL;
printf("SDL surfaces, textures, and renderers freed from memory!\nDestroying SDL window...\n");
SDL_DestroyWindow(window);
//TTF_CloseFont(font);
//font = NULL;
window = NULL;
printf("SDL window detroyed!\nQuitting SDL subsystems...\n");
IMG_Quit();
SDL_Quit();
//TTF_Quit();
printf("All SDL subsystems shutdown!\n");
}
/*void SetColor(int value) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), value);
/*
1: Blue
2: Green
3: Cyan
4: Red
5: Purple
6: Yellow (Dark)
7: Default white
8: Gray/Grey
9: Bright blue
10: Brigth green
11: Bright cyan
12: Bright red
13: Pink/Magenta
14: Yellow
15: Bright white
}
*/
//load.h
//#pragma once
#ifndef LOAD_H
#define LOAD_H
enum KeyPressSurfacese
{
KEY_PRESS_SURFACE_DEFUALT,
KEY_PRESS_SURFACE_UP,
KEY_PRESS_SURFACE_DOWN,
KEY_PRESS_SURFACE_LEFT,
KEY_PRESS_SURFACE_RIGHT,
KEY_PRESS_SURFACE_TOTAL
};
class cTexture {
public:
cTexture();
~cTexture();
bool loadFromFile(std::string path);
void free();
void render(int x, int y, SDL_Rect* clip = NULL, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE);
void loadFromRenderedText(std::string text, SDL_Color color);
void setColor(Uint8 red, Uint8 green, Uint8 blue);
void setBlendMode(SDL_BlendMode blending);
void setAlpha(Uint8 alpha);
int getWidth();
int getHeight();
private:
SDL_Texture * hTexture;
int hWidth;
int hHeight;
};
static cTexture keyPresses[KEY_PRESS_SURFACE_TOTAL];
static cTexture sprite;
static cTexture text;
static SDL_Texture* loadTexture(std::string path);
static SDL_Rect spriteClips[4];
//TTF_Font* font = NULL;
static SDL_Color textColor = { 0, 0, 0 };
void loadAssets();
#endif //LOAD_H
//load.cpp
//#include "stdafx.h"
#include <stdio.h>
#include "tchar.h"
#include <SDL2/SDL.h>
#include <iostream>
#include <SDL2/SDL_image.h>
#include "main.h"
#include "init.h"
#include "load.h"
//#include <conio.h>
//#include <Windows.h>
#include <string>
#include <SDL2/SDL_ttf.h>
#include <cmath>
cTexture::cTexture()
{
//printf("Constructing texture wrapper class...\n");
hTexture = NULL;
hWidth = 0;
hHeight = 0;
}
cTexture::~cTexture()
{
//printf("Destroying texture wrapper class...\n");
free();
}
void cTexture::free()
{
//if (hTexture != NULL)
SDL_DestroyTexture(hTexture);
hTexture = NULL;
hWidth = 0;
hHeight = 0;
}
bool cTexture::loadFromFile(std::string path)
{
free();
SDL_Texture* newTexture = NULL;
SDL_Surface* loadedSurface = IMG_Load(path.c_str());
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
if(newTexture == NULL)
//printf("fail. error: %s\n", SDL_GetError());
hWidth = loadedSurface->w;
hHeight = loadedSurface->h;
SDL_FreeSurface(loadedSurface);
hTexture = newTexture;
return hTexture != NULL;
}
void cTexture::render(int x, int y, SDL_Rect * clip, double angle, SDL_Point * center, SDL_RendererFlip flip)
{
//SDL_Rect renderQuad = { x, y, hWidth, hHeight };
SDL_Rect renderQuad = { x, y, 480, 480 };
if (clip != NULL)
{
renderQuad.w = clip->w;
renderQuad.h = clip->h;
}
SDL_RenderCopyEx(renderer, hTexture, clip, &renderQuad, angle, center, flip);
}
/*
void cTexture::loadFromRenderedText(std::string text, SDL_Color color)
{
free();
SDL_Surface* textSurface = TTF_RenderText_Solid(font, text.c_str(), textColor);
hTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
hWidth = textSurface->w;
hHeight = textSurface->h;
SDL_FreeSurface(textSurface);
}
*/
void cTexture::setColor(Uint8 red, Uint8 green, Uint8 blue)
{
SDL_SetTextureColorMod(hTexture, red, green, blue);
}
void cTexture::setBlendMode(SDL_BlendMode blending)
{
SDL_SetTextureBlendMode(hTexture, blending);
}
void cTexture::setAlpha(Uint8 alpha)
{
SDL_SetTextureAlphaMod(hTexture, alpha);
}
int cTexture::getWidth() { return hWidth; }
int cTexture::getHeight() { return hHeight; }
void loadAssets()
{
printf("Loading image assets in loadAssets()...\n");
if (!keyPresses[KEY_PRESS_SURFACE_DEFUALT].loadFromFile("carrot.png"))
{
//SetColor(4);
printf("Failed to load image. Error: %s\n", SDL_GetError());
//SetColor(7);
} else
printf("Image loaded\n");
if(!keyPresses[KEY_PRESS_SURFACE_UP].loadFromFile("smIamLU.jpg"))
{
//SetColor(4);
printf("Failed to load image\n");
//SetColor(7);
}
else {
//keyPresses[KEY_PRESS_SURFACE_UP].setBlendMode(SDL_BLENDMODE_BLEND);
printf("Image loaded\n");
}
if(!keyPresses[KEY_PRESS_SURFACE_DOWN].loadFromFile("down.bmp"))
{
//SetColor(4);
printf("Failed to load image\n");
//SetColor(7);
} else
printf("Image loaded\n");
if(!keyPresses[KEY_PRESS_SURFACE_LEFT].loadFromFile("left.bmp"))
{
//SetColor(4);
printf("Failed to load image\n");
//SetColor(7);
}else
printf("Image loaded\n");
if(!keyPresses[KEY_PRESS_SURFACE_RIGHT].loadFromFile("right.bmp"))
{
//SetColor(4);
printf("Failed to load image\n");
//SetColor(7);
}else
printf("Image loaded\n");
if (!sprite.loadFromFile("foo.png"))
{
//SetColor(4);
printf("Failed to load image\n");
//SetColor(7);
}else
printf("Image loaded\n");
spriteClips[0].x = 0;
spriteClips[0].y = 0;
spriteClips[0].w = 64;
spriteClips[0].h = 205;
spriteClips[1].x = 64;
spriteClips[1].y = 0;
spriteClips[1].w = 64;
spriteClips[1].h = 205;
spriteClips[2].x = 128;
spriteClips[2].y = 0;
spriteClips[2].w = 64;
spriteClips[2].h = 205;
spriteClips[3].x = 192;
spriteClips[3].y = 0;
spriteClips[3].w = 64;
spriteClips[3].h = 205;
//font = TTF_OpenFont("Ubuntu-L.ttf", 28);
//text.loadFromRenderedText("text", textColor);
printf("Done!\n");
}
With the renderer I've tried making it with differnt flags such as SDL_RENDERER_ACCELERATED or SDL_RENDERER_SOFTWARE but neither work. The error is specifically coming from the load.cpp file
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
This is the line that fails. The error generated by SDL reads "Invalid texture". The renderer is declared correctly but I can't get it to work.
I'm so confused why it isn't working because it used to work fine. I abandoned the project for a few months and it was working when I stopped, came back, and now it doesn't work. Not to mention that I had a bunch of more problems that I already worked out, but this one I can't.
I figured it out and it's the strangest fix I've ever done. I added an error check for the renderer in the load function and it started working again. If I remove the error check if statement it goes back to not working. Seems like a strange bug but I'm glad it's working again.
Related
I'm trying to make some kind of 'engine' with C++/SDL. So I followed the LazyFoo's Tutorial and searched others places/videos about it [SDL/C++].
Everything was fine, until I organized my code in 2 Classes. It was just Game.h/Game.cpp and main.cpp, but I thought that would be good to separate the part of the code that loads Images from the Game class that loads and destroys the Surfaces/Textures (Game class).
So I literally copy/pasted the code to another class. What I copy/pasted was the two boolean functions textureBMP and textureIMG everything remains the same. And before I copy/pasted the code to another class, everything was working fine, so I don't know what is making this.
Another little question, is the way I'm organizing the code the right way? I want to have good habits straight in the beginning, even with small projects, such as this little project just for learning.
Thanks in advance!
Image.h
#pragma once
#include "Game.h"
class Image
{
public:
Image();
~Image();
Game game;
SDL_Surface *gBMP = NULL;
SDL_Texture *tBMP = NULL;
SDL_Surface *gIMG = NULL;
SDL_Texture *tIMG = NULL;
bool textureBMP(char *mediaLocation, bool SetColorKey, int red, int green, int blue);
bool textureIMG(char *mediaLocation, int imgFlags);
};
Image.cpp
#include "Image.h"
Image::Image()
{
}
Image::~Image()
{
}
bool Image::textureBMP(char *mediaLocation, bool SetColorKey, int red, int green, int blue) {
gBMP = SDL_LoadBMP(mediaLocation);
if (gBMP == NULL) {
printf("Nao foi possivel carregar a imagem %s,por causa do seguinte erro: \n %s \n", mediaLocation, SDL_GetError());
return false;
}
else {
if (SetColorKey) {
SDL_SetColorKey(gBMP, 1, SDL_MapRGB(gBMP->format, red, green, blue));
}
tBMP = SDL_CreateTextureFromSurface(game.renderer, gBMP);
SDL_FreeSurface(gBMP);
}
return true;
}
bool Image::textureIMG(char *mediaLocation, int imgFlags) {
if (!(IMG_Init(imgFlags) & imgFlags)) {
printf("SDL_image não pode ser inicializada! SDL_image Error: %s\n", IMG_GetError());
return false;
}
else {
gIMG = IMG_Load(mediaLocation);
tIMG = SDL_CreateTextureFromSurface(game.renderer, gIMG);
SDL_FreeSurface(gIMG);
}
return true;
}
Game.h
#pragma once
#include <SDL.h>
#include <SDL_image.h>
#include <iostream>
#include <string>
class Game
{
public:
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;
bool running;
SDL_Event event;
SDL_Window *gWindow = NULL;
SDL_Renderer *renderer = NULL;
SDL_Surface *gScreenSurface = NULL;
Game();
~Game();
bool initEngine(char *windowName);
void freeSurface(SDL_Surface *surfaceName);
void freeTexture(SDL_Texture *textureName);
void destroyRenderer();
void destroyWindow();
};
Game.cpp
#include "Game.h"
Game::Game()
{
}
Game::~Game()
{
}
bool Game::initEngine(char *windowName) {
bool initSucess = true;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("A Engine não foi iniciada pelo seguinte erro: \n %s \n", SDL_GetError());
initSucess = false;
return initSucess;
}
else {
gWindow = SDL_CreateWindow(windowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
if (gWindow == NULL) {
printf("A janela não pode ser criada pelo seguinte erro: \n %s \n", SDL_GetError());
initSucess = false;
return initSucess;
}
else {
gScreenSurface = SDL_GetWindowSurface(gWindow);
}
}
return initSucess;
}
void Game::freeSurface(SDL_Surface *surfaceName) {
SDL_FreeSurface(surfaceName);
surfaceName = NULL;
}
void Game::freeTexture(SDL_Texture *textureName) {
SDL_DestroyTexture(textureName);
textureName = NULL;
}
void Game::destroyRenderer() {
SDL_DestroyRenderer(renderer);
renderer = NULL;
}
void Game::destroyWindow() {
SDL_DestroyWindow(gWindow);
gWindow = NULL;
}
main.cpp
#include <iostream>
#include <SDL.h>
#include "Game.h"
#include "Image.h"
int main(int argc, char* args[]) {
Game game;
Image img;
if (!game.initEngine("TESTE")) {
printf("Falha ao iniciar! \n");
return 0;
}
game.running = true;
if (!img.textureBMP("res/bouncingball.bmp", true, 255, 0, 255))
printf("Falha ao iniciar imagem!\n");
if (!img.textureIMG("res/Tulips.jpg", IMG_INIT_JPG))
printf("Falha ao iniciar imagem! \n");
SDL_Rect stretchRect{ (game.SCREEN_WIDTH / 2) - 50, (game.SCREEN_HEIGHT / 2) - 50, 100, 100 };
SDL_Rect stretchRect2{ 0, 0, game.SCREEN_WIDTH, game.SCREEN_HEIGHT };
while (game.running) {
while (SDL_PollEvent(&game.event) != 0) {
switch (game.event.type) {
case SDL_QUIT:
game.running = false;
game.freeSurface(game.gScreenSurface);
game.freeTexture(img.tBMP);
game.freeTexture(img.tIMG);
game.destroyRenderer();
game.destroyWindow();
IMG_Quit();
SDL_Quit();
break;
}//Switch Event END
} // PollEvent END
SDL_RenderCopy(game.renderer, img.tIMG, nullptr, &stretchRect2);
SDL_RenderCopy(game.renderer, img.tBMP, nullptr, &stretchRect);
SDL_RenderPresent(game.renderer);
SDL_GL_SetSwapInterval(1);
}// game.running END
return 0;
}
PrintScreen of the Output
I made some changes, and now it works properly. I changed two things, the first was the part that was giving the black screen, and now the functions look like this:
Image.h
bool textureBMP(char *mediaLocation, <...>, SDL_Renderer *render);
bool textureIMG(char *mediaLocation, <...>, SDL_Renderer *render);
main.cpp
if (!img.textureIMG("res/Tulips.jpg", IMG_INIT_JPG, game.renderer))
And, the other change was that, before Image.h was including Game.h, and, in main.cpp I was including Game.h, and Image.h and this would create an error right?
Because of this https://en.wikipedia.org/wiki/Include_guard
Obs: I created an answer because the comment doesn't allow codes
Recently I have been trying to make a button using the lazyfoo.net tutorials. The button example they code didn't fit what I needed (especially since I modified the LTexture class) so I modified it... and, of course, it didn't work.
So here is the modified LTexture class(now dubbed Texture):
#pragma once
//Using SDL, SDL_image, standard IO, and strings
#include <xstring>
#include <SDL.h> //SDL header file
#include <SDL_image.h> //SDL image file
#include <stdio.h> //standard C ouput
#include <string> //standard c++ string
#include <map>
#include <SDL_ttf.h>
using namespace std;
typedef Uint8 u8;
//Texture wrapper class (originally from lazyfoo.net)
class Texture
{
public:
//Initializes variables
Texture();
//Deallocates memory
~Texture();
//Loads image at specified path
bool loadFromFile(std::string path);
//Deallocates texture
void free();
//Renders texture at given point
void render();
//Sets the size of the image
void setSize(int width, int height);
//Adds a clip to the clips map
void addClip(string name, SDL_Rect* aclip);
//Sets the clip
void setClip(string name);
void setNullClip();
//Sets the placement of the object
void setPos(int newx, int newy);
//Moves the position of the object
void movePos(int addx, int addy);
//Gets image dimensions
int getWidth();
int getHeight();
//Sets the color
void setColor(Uint8 red, u8 green, u8 blue);
//Set blending
void setBlendMode(SDL_BlendMode blending);
//Set alpha modulation
void setAlpha(Uint8 alpha);
//Creates image from font string
bool loadFromRenderedText(std::string textureText, SDL_Color textColor);
protected:
//The actual hardware texture
SDL_Texture* mTexture;
//Image dimensions
int mWidth;
int mHeight;
//Image bottom left coordinates
int x;
int y;
//Current clip of image
SDL_Rect* clip;
//Available image clips
map<string, SDL_Rect*> clips;
};
And the function definitions:
#include "Texture.h"
#include "Univar.h"
extern SDL_Renderer* Renderer;
extern TTF_Font* Font;
Texture::Texture()
{
//Initialize
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
Texture::~Texture()
{
//Deallocate
free();
}
bool Texture::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(Renderer, 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;
}
void Texture::free()
{
//Free texture if it exists
if (mTexture != NULL)
{
SDL_DestroyTexture(mTexture);
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
}
void Texture::render()
{
//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;
}
SDL_RenderCopy(Renderer, mTexture, clip, &renderQuad);
}
void Texture::setSize(int width, int height)
{
mWidth = width;
mHeight = height;
}
void Texture::addClip(string name, SDL_Rect * aclip)
{
clips[name] = aclip;
}
void Texture::setClip(string name)
{
clip = clips[name];
}
void Texture::setNullClip()
{
clip = NULL;
}
void Texture::setPos(int newx, int newy)
{
x = newx;
y = newy;
}
void Texture::movePos(int addx, int addy)
{
x += x;
y += y;
}
int Texture::getWidth()
{
return mWidth;
}
int Texture::getHeight()
{
return mHeight;
}
void Texture::setColor(Uint8 red, u8 green, u8 blue)
{
//Modulate texture
SDL_SetTextureColorMod(mTexture, red, green, blue);
}
void Texture::setBlendMode(SDL_BlendMode blending)
{
//Set blending function
SDL_SetTextureBlendMode(mTexture, blending);
}
void Texture::setAlpha(Uint8 alpha)
{
//Modulate texture alpha
SDL_SetTextureAlphaMod(mTexture, alpha);
}
bool Texture::loadFromRenderedText(std::string textureText, SDL_Color textColor)
{
//Get rid of preexisting texture
free();
//Render text surface
SDL_Surface* textSurface = TTF_RenderText_Solid(Font, textureText.c_str(), textColor);
if (textSurface == NULL)
{
printf("Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError());
}
else
{
//Create texture from surface pixels
mTexture = SDL_CreateTextureFromSurface(Renderer, 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);
}
//Return success
return mTexture != NULL;
}
Then here is the button class:
#pragma once
#include "Texture.h"
enum MouseState {
Out,
Hover
};
enum Press {
LClick,
RClick,
None
};
class Button : public Texture{
int w;
int h;
int x;
int y;
public:
//Inits the variables
Button(int aw, int ah);
//Handles events
Press handleEvent(SDL_Event* e);
};
And the function definitions:
#include "Button.h"
Button::Button(int aw, int ah) : w(aw), h(ah)
{
setSize(aw, ah);
}
Press Button::handleEvent(SDL_Event * e)
{
//If mouse event happened
if (e->type == SDL_MOUSEMOTION || e->type == SDL_MOUSEBUTTONDOWN || e->type == SDL_MOUSEBUTTONUP)
{
//Get mouse position
int ax, ay;
SDL_GetMouseState(&ax, &ay);
//Check if mouse is in button
bool inside = true;
//Mouse is left of the button
if (ax < x)
{
inside = false;
}
//Mouse is right of the button
else if (ax > x + w)
{
inside = false;
}
//Mouse above the button
else if (ay < y)
{
inside = false;
}
//Mouse below the button
else if (ay > y + h)
{
inside = false;
}
//Mouse is outside button
if (!inside)
{
setClip("out");
return None;
}
//Mouse is inside button
else
{
setClip("Hover");
//Set mouse over sprite
switch (e->button.button)
{
case SDL_BUTTON_LEFT:
return LClick;
break;
case SDL_BUTTON_RIGHT:
return RClick;
break;
default:
return None;
break;
}
}
}
else {
return None;
}
}
And when I run this, I get nothing (well I get a window but without the button in it)! If the button class seams barebones, that's because I'm pretty sure I've narrowed down the error to handleEvent(). I looked through it and couldn't find the error.
I figured out the error. The reason is I'm not used to SDL's coordinate system.
In SDL, the top left is 0,0.
In regular coordinate grids, the bottom left is 0,0.
:(P
I've been using SDL for a little awhile and following Lazy Foo's tutorials. I have no problem loading images, animating sprites etc... but when I attempt to separate functions into different header files I'm unable to load an image.
I've looked about for on the internet for a few days now but haven't found an answer.
Sprite.cpp
#include "Sprite.h"
#include "Globals.h"
using namespace Globals;
Graphics sprite;
Sprite::Sprite(){}
bool Sprite::load()
{
bool success = true;
if(!sprite.loadImage("C:/SDL_Project/bin/Debug/PNG_transparency_demonstration_1.png"))
{
printf("Failed to load image!\n");
success = false;
}
return success;
}
void Sprite::renderSprite()
{
SDL_Rect* curSprite = &spriteClips[frames];
sprite.renderImage((SCREEN_WIDTH - curSprite->w) / 2, (SCREEN_HEIGHT - curSprite->h) / 2, curSprite);
}
Graphics.cpp
#include "Graphics.h"
#include "Globals.h"
using namespace Globals;
Graphics::Graphics()
{
hei = 0;
wid = 0;
texture = NULL;
win = SDL_CreateWindow("Foo", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(win && ren == NULL)
{
printf("Failed to create Window & Renderer!\n");
}
else
{
int imgFlags = IMG_INIT_PNG;
if( !(IMG_Init(imgFlags) &imgFlags))
{
printf("Image flags not initiated!\n");
}
}
}
Graphics::~Graphics(){}
SDL_Texture* Graphics::loadImage(std::string file)
{
SDL_Texture* newTxtr = NULL;
image = IMG_Load(file.c_str());
if(image == NULL)
{
printf("Unable to load image\n");
}
else
{
newTxtr = SDL_CreateTextureFromSurface(ren, image);
if(newTxtr == NULL)
{
printf("Unable to create texture!\n");
}
else
{
wid = image->w;
hei = image->h;
}
SDL_FreeSurface(image);
}
texture = newTxtr;
return texture;
}
void Graphics::free()
{
if(texture != NULL)
{
texture = NULL;
wid = 0;
hei = 0;
}
}
void Graphics::renderImage(int x, int y, SDL_Rect* clip)
{
SDL_Rect dstClip = {x, y, wid, hei};
if(clip != NULL)
{
dstClip.w = clip->w;
dstClip.h = clip->h;
}
SDL_RenderCopy(ren, texture, clip, &dstClip);
}
void Graphics::render()
{
SDL_RenderPresent(ren);
SDL_UpdateWindowSurface(win);
}
void Graphics::clearScreen()
{
SDL_RenderClear(ren);
}
SDL_Renderer* Graphics::getRenderer()
{
return ren;
}
void Graphics::closeGraphics()
{
IMG_Quit();
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
}
GameLoop.cpp
#include "GameLoop.h"
#include "Graphics.h"
#include "Sprite.h"
GameLoop::GameLoop()
{
if(SDL_Init(SDL_INIT_EVERYTHING)< 0)
{
printf("Failed to init\n");
}
else
{
this->loop();
}
}
GameLoop::~GameLoop(){}
void GameLoop::loop()
{
Graphics graphics;
SDL_Event e;
bool quit = false;
while(!quit)
{
while(SDL_PollEvent(&e)!= 0)
{
if(e.type == SDL_QUIT)
{
quit = true;
}
}
this->renderGraphics(graphics);
}
this->close(graphics);
}
void GameLoop::loadSprite()
{
Sprite sp;
sp.renderSprite();
}
void GameLoop::renderGraphics(Graphics& graphics)
{
SDL_SetRenderDrawColor(graphics.ren, 0x00, 0x00, 0x00, 0x00);
graphics.clearScreen();
graphics.render();
}
void GameLoop::close(Graphics& graphics)
{
SDL_Quit();
graphics.closeGraphics();
}
I've included all but one of the .cpp files.
Thanks.
I was playing around in SDL2 when I discovered something really strange. I'm trying to draw an optimized texture, but it won't work. The code which turns a surface to a texture doesn't work. According to the documentation, SDL_GetError() should give me the error, but it doesn't return anything... Any help would be appreciated! Here's the code:
Main.cpp:
#include "SDLHelper.h"
#include "Player.h"
#define WIDTH 640
#define HEIGHT 480
#define NAME "TILES BOI!"
int main(int args, char* argv[]){
SDL_Window* gWindow;
SDL_Renderer* gRenderer;
if(!init(NAME, WIDTH, HEIGHT, &gWindow, &gRenderer)){
printf("Failed to initialize!\n");
}else{
bool quit = false;
SDL_Event e;
Player* player = new Player(100, 100, 0, 0);
player->texture = loadTexture("sprites/people/male_walkcycle.png", &gRenderer);
while(!quit){
while(SDL_PollEvent(&e) != 0){
if(e.type == SDL_QUIT){
quit = true;
}
}
SDL_RenderClear(gRenderer);
SDL_RenderCopy(gRenderer, player->texture, &(player->currentTexturePos), &(player->position));
SDL_RenderPresent(gRenderer);
}
close(&gWindow, &gRenderer);
}
return 0;
}
SDLHelper.h:
#ifndef SDLHELPER_H
#define SDLHELPER_H
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
bool init(const char* name, int width, int height, SDL_Window** window, SDL_Renderer** renderer);
SDL_Texture* loadTexture(const char* path, SDL_Renderer** renderer);
void close(SDL_Window** gWindow, SDL_Renderer** gRenderer);
#endif
SDLHelper.cpp:
#include "SDLHelper.h"
bool init(const char* name, int width, int height, SDL_Window** window, SDL_Renderer** renderer){
bool success = true;
if(SDL_Init(SDL_INIT_EVERYTHING) < 0){
printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
success = false;
}else{
if(!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")){
printf("Warning: Linear texture filtering is not enabled!\n");
}
*window = SDL_CreateWindow(name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN);
if(*window == NULL){
printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}else{
*renderer = SDL_CreateRenderer(*window, -1, SDL_RENDERER_ACCELERATED);
if(*renderer == NULL){
printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}else{
SDL_SetRenderDrawColor(*renderer, 0xFF, 0xFF, 0xFF, 0xFF);
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;
}
SDL_Texture* loadTexture(const char* path, SDL_Renderer** renderer){
SDL_Texture* newTexture = NULL;
SDL_Surface* loaded = IMG_Load(path);
if(loaded == NULL){
printf("Unable to load image %s! SDL_Image Error: %s\n", path, IMG_GetError());
}else{
newTexture == SDL_CreateTextureFromSurface(*renderer, loaded);
if(newTexture == NULL){
printf("Unable to create texture from %s! SDL Error: %s\n", path, SDL_GetError());
}
SDL_FreeSurface(loaded);
}
return newTexture;
}
void close(SDL_Window** gWindow, SDL_Renderer** gRenderer){
SDL_DestroyRenderer(*gRenderer);
SDL_DestroyWindow(*gWindow);
*gWindow = NULL;
*gRenderer = NULL;
//Quit SDL subsystems
IMG_Quit();
SDL_Quit();
}
Player.h:
#ifndef PLAYER_H
#define PLAYER_H
#include <SDL2/SDL.h>
class Player
{
public:
Player(int h, int m, int x, int y);
~Player();
SDL_Texture* texture;
SDL_Rect position;
SDL_Rect currentTexturePos;
int health;
int mana;
const char* name = "Bobby";
};
#endif
Player.cpp:
#include "Player.h"
Player::Player(int h, int m, int x, int y){
health = h;
mana = m;
position.x = x;
position.y = y;
position.h = 64;
position.w = 64;
currentTexturePos.x = 64;
currentTexturePos.y = 0;
currentTexturePos.h = 64;
currentTexturePos.w = 64;
}
Player::~Player(){
SDL_DestroyTexture(texture);
texture = NULL;
}
Makefile:
CC = g++
FLAGS = -w -lSDL2 -lSDL2_image
OBJECTS = main.cpp SDLHelper.cpp Player.cpp
NAME = tileBasedRPG
all: $(OBJECTS)
$(CC) $(OBJECTS) $(FLAGS) -o $(NAME)
clean:
rm -rf *.o
You never assigned newTexture:
newTexture == SDL_CreateTextureFromSurface(*renderer, loaded);
when it meant to be
newTexture = SDL_CreateTextureFromSurface(*renderer, loaded);
I'm trying to organize my code a bit more, so I tried putting the SDL2 code used for displaying windows/images into a class. The window opens, the code runs successfully, and the image seems to be loading fine, -but the image will not appear when the code is arranged in a class like this. Why is this happening?
main.cpp:
#include <SDL.h>
#include "display.h"
SDL_Event event;
SDL_Surface* image = nullptr;
int main(int argc, char* args[])
{
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
return false;
Display display;
display.loadImage("image.bmp");
bool quit = false;
while (!quit)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
quit = true;
}
display.applySurface(0, 0, image, display.windowSurface);
display.update();
}
SDL_FreeSurface(image);
SDL_Quit();
return 0;
}
display.h:
#pragma once
#include <SDL.h>
#include <string>
#include <iostream>
class Display
{
public:
SDL_Window* window;
SDL_Surface* windowSurface;
Display();
SDL_Surface* loadImage(std::string fileName);
void applySurface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip = nullptr);
void update();
~Display();
private:
const int WINDOW_WIDTH = 612;
const int WINDOW_HEIGHT = 632;
const int SCREEN_BPP = 2;
};
display.cpp:
#pragma once
#include "display.h"
Display::Display()
{
window = SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL)
std::cout << "Error: SDL_CreateWindow failed." << std::endl;
windowSurface = SDL_GetWindowSurface(window);
if (windowSurface == NULL)
std::cout << "Error: Window surface is null." << std::endl;
}
SDL_Surface* Display::loadImage(std::string fileName)
{
SDL_Surface* loadedImage = NULL;
SDL_Surface* optimizedImage = NULL;
loadedImage = SDL_LoadBMP(fileName.c_str());
if (loadedImage == NULL)
std::cout << "Loaded image = NULL" << std::endl;
if (loadedImage != NULL)
{
optimizedImage = SDL_ConvertSurface(loadedImage, windowSurface->format, 0);
SDL_FreeSurface(loadedImage);
if (optimizedImage == NULL)
std::cout << "Optimized image = NULL" << std::endl;
if (optimizedImage != NULL)
SDL_SetColorKey(optimizedImage, SDL_TRUE, SDL_MapRGB(optimizedImage->format, 255, 255, 255));
}
return optimizedImage;
}
void Display::applySurface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface(source, clip, destination, &offset);
}
void Display::update()
{
if (SDL_UpdateWindowSurface(window) == -1)
std::cout << "Error: SDL_UpdateWindowSurface() failed." << std::endl;
}
Display::~Display()
{
SDL_FreeSurface(windowSurface);
windowSurface = NULL;
SDL_DestroyWindow(window);
window = NULL;
}
In your main.cpp your image is empty because you didn't use the return image :
image = display.loadImage("image.bmp");