SDL Load image using multiple classes and files - c++

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.

Related

"Class" type redefinition error C2011 in C++

Here's my header file:
#ifndef SOMETHING_H
#define SOMETHING_H
#include <SDL.h>
#include <stdio.h>
#include <string>
#pragma once
class Something {
public:
//Screen dimension constants
int SCREEN_WIDTHS;
int SCREEN_HEIGHTS;
//Starts up SDL and creates window
bool inits();
//Loads media
bool loadMediases();
//Frees media and shuts down SDL
void closes();
Something(int height);
int mains();
//Loads individual image
SDL_Surface* loadSurfaces(std::string path);
//The window we'll be rendering to
SDL_Window* gWindows;
//The surface contained by the window
SDL_Surface* gScreenSurfaces;
//The images that correspond to a keypress
SDL_Surface* gKeyPressSurfaceses[5];
//Current displayed image
SDL_Surface* gCurrentSurfaces;
};
#endif
Here's my cpp file:
//Using SDL, standard IO, and strings
#include <SDL.h>
#include <stdio.h>
#include <string>
#include "Something.h"
class Something {
public:
//Screen dimension constants
int SCREEN_WIDTHS = 640;
int SCREEN_HEIGHTS = 480;
//Key press surfaces constants
enum KeyPressSurfaceses
{
KEY_PRESS_SURFACE_DEFAULT,
KEY_PRESS_SURFACE_UP,
KEY_PRESS_SURFACE_DOWN,
KEY_PRESS_SURFACE_LEFT,
KEY_PRESS_SURFACE_RIGHT,
KEY_PRESS_SURFACE_TOTAL
};
//The window we'll be rendering to
SDL_Window* gWindows = NULL;
//The surface contained by the window
SDL_Surface* gScreenSurfaces = NULL;
//The images that correspond to a keypress
SDL_Surface* gKeyPressSurfaceses[KEY_PRESS_SURFACE_TOTAL];
//Current displayed image
SDL_Surface* gCurrentSurfaces = NULL;
Something(int height) {
SCREEN_HEIGHTS = height;
}
bool inits()
{
//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
gWindows = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTHS, SCREEN_HEIGHTS, SDL_WINDOW_SHOWN);
if (gWindows == NULL)
{
printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Get window surface
gScreenSurfaces = SDL_GetWindowSurface(gWindows);
}
}
return success;
}
bool loadMedias()
{
//Loading success flag
bool success = true;
//Load default surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_DEFAULT] = loadSurfaces("resources/images/press.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_DEFAULT] == NULL)
{
printf("Failed to load default image!\n");
success = false;
}
//Load up surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_UP] = loadSurfaces("resources/images/up.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_UP] == NULL)
{
printf("Failed to load up image!\n");
success = false;
}
//Load down surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_DOWN] = loadSurfaces("resources/images/down.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_DOWN] == NULL)
{
printf("Failed to load down image!\n");
success = false;
}
//Load left surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_LEFT] = loadSurfaces("resources/images/left.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_LEFT] == NULL)
{
printf("Failed to load left image!\n");
success = false;
}
//Load right surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_RIGHT] = loadSurfaces("resources/images/right.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_RIGHT] == NULL)
{
printf("Failed to load right image!\n");
success = false;
}
return success;
}
void closes()
{
//Deallocate surfaces
for (int i = 0; i < KEY_PRESS_SURFACE_TOTAL; ++i)
{
SDL_FreeSurface(gKeyPressSurfaceses[i]);
gKeyPressSurfaceses[i] = NULL;
}
//Destroy window
SDL_DestroyWindow(gWindows);
gWindows = NULL;
//Quit SDL subsystems
SDL_Quit();
}
SDL_Surface* loadSurfaces(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 mains(int argc, char* args[])
{
//Start up SDL and create window
if (!inits())
{
printf("Failed to initialize!\n");
}
else
{
//Load media
if (!loadMedias())
{
printf("Failed to load media!\n");
}
else
{
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//Set default current surface
gCurrentSurfaces = gKeyPressSurfaceses[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:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_UP];
break;
case SDLK_DOWN:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_DOWN];
break;
case SDLK_LEFT:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_LEFT];
break;
case SDLK_RIGHT:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_RIGHT];
break;
default:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_DEFAULT];
break;
}
}
}
//Apply the current image
SDL_BlitSurface(gCurrentSurfaces, NULL, gScreenSurfaces, NULL);
//Update the surface
SDL_UpdateWindowSurface(gWindows);
}
}
}
//Free resources and close SDL
closes();
return 0;
}
};
Why does it keep throwing a "Class" type redefinition error? How can I fix this? I've tried everything but I just run into more problems. I saw some posts relating the issue to defining the class twice, but getting rid of the class definition in the cpp and using classname::functionname just causes more errors.
I know this is a stupid problem to have, I'm a beginning C++ programmer using tutorials and Visual Studio.
In your .cpp file you have completely redeclared class Something. That's not how you do it if you want to just put the implementations of functions in the .cpp file.
The syntax in there should be like:
bool Something::inits()
{
// implementation ...
}
bool Something::loadMedias()
{
// implementation ...
}
And so on

"Invalid texture" error from SDL_CreateTextureFromSurface()?

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.

SDL/C++ (Accelerated) Black Screen

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

Unable to open Image in C++ SDL

So im trying to render an image. This code worked fine before I refactored into seperate classes but i cannot see the problem. The file path for the image also worked before the refactoring however i have not moved the image so it should still be in the same place.
The error i am getting is "Unable to create texture from surface. Error: Couldn't open Images/text.bmp" so im fairly certain its the line of code below that is messing up.
if (!(gTexture->LoadFromFile("Images/text.bmp")))
{
return false;
}
Here is the LoadFromFile function code
bool Texture2D::LoadFromFile(string path)
{
Free();
SDL_Texture* pTexture = NULL;
SDL_Surface* pSurface = IMG_Load(path.c_str());
if (pSurface != NULL)
{
//SDL_SetColorKey(pSurface, SDL_TRUE, SDL_MapRGB(pSurface->format, 0, 0xFF, 0xFF));
pTexture = SDL_CreateTextureFromSurface(mRenderer, pSurface);
if (pTexture == NULL)
{
cout << "Unable to create texture from surface. Error: " << SDL_GetError() << endl;
}
mWidth = pSurface->w;
mHeight = pSurface->h;
SDL_FreeSurface(pSurface);
}
else
{
cout << "Unable to create texture from surface. Error: " << IMG_GetError() << endl;
}
mTexture = pTexture;
return pTexture != NULL;
}
Below is the Source.cpp file:
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include "Constants.h"
#include "Texture2D.h"
#include "Commons.h"
#include <iostream>
#include <string>
using namespace std;
//Globals
SDL_Window* gWindow = NULL;
SDL_Renderer* gRenderer = NULL;
Texture2D* gTexture = NULL;
//prototypes
bool InitSDL();
void CloseSDL();
bool Update();
void Render();
int main(int argc, char* args[])
{
if(InitSDL())
{
bool quit = false;
while(!quit)
{
//gTexture->Render(Vector2D(), SDL_FLIP_NONE, 0);
Render();
quit = Update();
}
}
CloseSDL();
return 0;
}
bool InitSDL()
{
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
cout << "SDL did not initialise. Error: " << SDL_GetError();
return false;
}
else
{
//ITS ALL GOOD BRO
gWindow = SDL_CreateWindow("Games Engine Creation",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
//DID IT GO?
if (gWindow == NULL)
{
//NUH UH
cout << "Window was not created. Error: " << SDL_GetError();
return false;
}
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
if (gRenderer != NULL)
{
//INITIALISE THAT PNG BBY
int imageFlags = IMG_INIT_PNG;
if (!(IMG_Init(imageFlags) & imageFlags))
{
cout << "SDL_Image could not initialise. Error: " << IMG_GetError();
return false;
}
}
else
{
cout << "Renderer could not be initialised. Error: " << SDL_GetError();
return false;
}
gTexture = new Texture2D(gRenderer);
if (!(gTexture->LoadFromFile("Images/text.bmp")))
{
return false;
}
return true;
}
}
void CloseSDL()
{
SDL_DestroyWindow(gWindow);
gWindow = NULL;
delete gTexture;
gTexture = NULL;
SDL_DestroyRenderer(gRenderer);
gRenderer = NULL;
IMG_Quit();
SDL_Quit();
}
bool Update()
{
SDL_Event e;
SDL_PollEvent(&e);
switch(e.type)
{
case SDL_QUIT:
return true;
break;
case SDL_KEYUP:
switch(e.key.keysym.sym)
{
case SDLK_q:
return true;
break;
}
break;
case SDL_MOUSEBUTTONDOWN:
return true;
break;
}
return false;
}
void Render()
{
SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(gRenderer);
gTexture->Render(Vector2D(), SDL_FLIP_NONE, 0);
//SDL_Rect renderLocation = { 0, 0, mWidth, mHeight };
//SDL_RenderCopyEx(mRenderer, mTexture, NULL, &renderLocation, 0, NULL, SDL_FLIP_NONE);
SDL_RenderPresent(gRenderer);
}
A simple way to start debugging is to place the image in the same folder with the executable and show the path as ./image.bmp to see if something is wrong with the path.

Program shuts down immediately SDL

When I run this code (from the Lazy Foo SDL tutorial) the program immediately shuts down. Why is that? I'm sorry if it gets kind of messy because of the lack of comments, but I thought that it didn't really matter since there were comments on Lazy Foo's post. I get no errors when building it.
#include "SDL/SDL_image.h"
#include "SDL/SDL.h"
#include <string>
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
SDL_Surface *image = NULL;
SDL_Surface *screen = NULL;
SDL_Event event;
SDL_Surface *load_image (std::string filename)
{
SDL_Surface* loadedImage = NULL;
SDL_Surface* optimizedImage = NULL;
loadedImage = IMG_Load( filename.c_str());
if(loadedImage != NULL)
{
optimizedImage = SDL_DisplayFormat (loadedImage);
SDL_FreeSurface(loadedImage);
}
return optimizedImage;
}
void apply_surface (int x, int y, SDL_Surface* source, SDL_Surface* destination)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface (source, NULL, destination, &offset);
}
bool init()
{
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return false;
}
screen = SDL_SetVideoMode (SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);
if (screen == NULL)
{
return false;
}
SDL_WM_SetCaption("Event test", NULL);
return true;
}
bool load_files()
{
image = load_image ("background.png");
if (image == NULL)
{
return false;
}
return true;
}
void clean_up()
{
SDL_FreeSurface(image);
SDL_Quit();
}
int main(int argc, char* args[])
{
bool quit = false;
if (init() == false)
{
return 1;
}
if (load_files() == false)
{
return 1;
}
apply_surface(0,0, image, screen);
if(SDL_Flip(screen) == -1)
{
return 1;
}
while(quit == false)
{
while (SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
quit = true;
}
}
}
clean_up();
return 0;
}
If you're missing background.png, or any of the required DLL's in the executable directory, you can encounter weird crashes.
Being that this is one of the simpler programs in this series, I'd bet this is the issue. I've seen strange segfaults myself when I had a brain-fart and forgot a file, or it wasn't where the exe expected it to be.