I am having an error putting a background onto a screen with SDL. I have a screen class and an image class, and the screen class has a function that repeats a background across the screen. Since this function takes a pointer, I have a function in the image class that gets the pointer to the stored SDL_Surface for the image. This function always fails and returns three. Here's my code:
Screen.hpp
#ifndef SCREEN_HPP_INCLUDED
#define SCREEN_HPP_INCLUDED
#include <string>
#include "SDL.h"
namespace myeng
{
class Screen final //This class doesn't need to be derived from
{
public:
//Constructor and destructor
Screen(int height, int width, std::string caption);
~Screen();
//Functions to get the width, height, and depth of the screen
int getScreen_Width();
int getScreen_Height();
int getScreen_Depth();
//Function to get screen_ptr
SDL_Surface* getScreen_Ptr();
//Function to flip the screen
int Screen_Flip();
//Function to put something on the screen
int Screen_Put(int x, int y, SDL_Surface* source);
//Functions for backgrounds
int Screen_RepBack(int height, int width, SDL_Surface* source);
private:
//Constants
int SCREEN_WIDTH;
int SCREEN_HEIGHT;
int SCREEN_DEPTH;
//Other variables
std::string screen_name;
//Surfaces
SDL_Surface* screen_ptr = nullptr; //Creates the main surface for the screen
};
}
#endif // SCREEN_HPP_INCLUDED
Screen.cpp
#include <iostream>
#include "Screen.hpp"
//Cosntructor and destructor
myeng::Screen::Screen(int height, int width, std::string caption)
{
SCREEN_WIDTH = width;
SCREEN_HEIGHT = height;
SCREEN_DEPTH = 32;
screen_ptr = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_DEPTH, SDL_SWSURFACE);
SDL_WM_SetCaption(caption.c_str(), caption.c_str());
}
myeng::Screen::~Screen()
{
}
//Functions to get width, height, and depth of the screen
int myeng::Screen::getScreen_Width()
{
return SCREEN_WIDTH;
}
int myeng::Screen::getScreen_Height()
{
return SCREEN_HEIGHT;
}
int myeng::Screen::getScreen_Depth()
{
return SCREEN_DEPTH;
}
//Function to get screen_ptr
SDL_Surface* myeng::Screen::getScreen_Ptr()
{
return screen_ptr;
}
//Function to flip the screen
int myeng::Screen::Screen_Flip()
{
if(SDL_Flip(screen_ptr) != 0)
{
std::cerr << "Failed to flip screen. Error" << SDL_GetError() << "\n";
return 1;
}
else
{
return 0;
}
}
//Function to put something on the Screen
int myeng::Screen::Screen_Put(int x, int y, SDL_Surface* source)
{
//Create a rectangle to store the offsets of the source
SDL_Rect offset;
//Set the offsets
offset.x = x;
offset.y = y;
//Apply the source to the screen
if(SDL_BlitSurface(source, nullptr, screen_ptr, &offset) != 0)
{
std::cerr << "Failed to blit the surface. Error " << SDL_GetError();
return 1;
}
else
{
return 0;
}
}
//Functions for backgrounds
int myeng::Screen::Screen_RepBack(int height, int width, SDL_Surface* source)
{
int columns = SCREEN_HEIGHT / height;
int rows = SCREEN_WIDTH / width;
if((SCREEN_HEIGHT % height != 0) || (SCREEN_WIDTH % width != 0))
{
std::cerr << "Background cannot be repeated over the screen \n";
return 1;
}
else
{
for(int i = 0; i < columns; i++)
{
for(int j = 0; j < rows; j++)
{
Screen_Put(j*width, i*height, source);
}
}
}
return 0;
}
Image.hpp
#ifndef IMAGE_HPP_INCLUDED
#define IMAGE_HPP_INCLUDED
#include <string>
#include "SDL.h"
#include "SDL_Image.h"
namespace myeng
{
class Image
{
public:
//Constructor and destructor
Image(int height, int width, std::string filename);
~Image();
//Functions to get member variables
SDL_Surface* getImg_Surface();
int getImage_Width();
int getImage_Height();
bool getTransparency();
bool getOptimized();
//Functions for loading images
int Image_Load(int height, int width, std::string filename);
//Functions to change images
int Image_MakeTransparent();
private:
//Constants
int IMAGE_WIDTH;
int IMAGE_HEIGHT;
//Image Info
bool is_transparent;
bool is_optimized;
//Surfaces
SDL_Surface* img_surface = nullptr;
};
}
#endif // IMAGE_HPP_INCLUDED
Image.cpp
#include <iostream>
#include "Image.hpp"
//Constructor and destructor
myeng::Image::Image(int height, int width, std::string filename)
{
is_transparent = false;
is_optimized = false;
Image_Load(height, width, filename);
IMAGE_HEIGHT = height;
IMAGE_WIDTH = width;
}
myeng::Image::~Image()
{
SDL_FreeSurface(img_surface);
}
//Functions to get member variables
SDL_Surface* myeng::Image::getImg_Surface()
{
return img_surface;
}
int myeng::Image::getImage_Width()
{
return IMAGE_WIDTH;
}
int myeng::Image::getImage_Height()
{
return IMAGE_HEIGHT;
}
bool myeng::Image::getTransparency()
{
return is_transparent;
}
bool myeng::Image::getOptimized()
{
return is_optimized;
}
//Functions for loading images
int myeng::Image::Image_Load(int height, int width, std::string filename)
{
//The image that's loaded
SDL_Surface* loadedImage = nullptr;
//The optimized image that will be used
SDL_Surface* optimizedImage = nullptr;
//Load the image
loadedImage = IMG_Load(filename.c_str());
//If the image loaded
if(loadedImage != nullptr)
{
//Log the image loading
std::cout << "Successfully loaded: " << filename << "\n";
//Create an optimized image
optimizedImage = SDL_DisplayFormat(loadedImage);
//Free the old image
SDL_FreeSurface(loadedImage);
//Specify the image as optimized
is_optimized = true;
}
else
{
//Log the failure and make sure the image is specified as not optimized
std::cerr << "Failed to load: " << filename;
is_optimized = false;
return 1;
}
//Return the optimized image
img_surface = optimizedImage;
SDL_FreeSurface(optimizedImage);
return 0;
}
//Functions to change images
int myeng::Image::Image_MakeTransparent()
{
//Check to see if the image is already transparent
if(is_transparent == false)
{
//Creates the color that will be transparent
Uint32 colorkey = SDL_MapRGB(img_surface->format, 0xED, 0x0B, 0xB5);
//Set the transparency
if(SDL_SetColorKey(img_surface, SDL_SRCCOLORKEY, colorkey) != 0)
{
std::cerr << "Error making image transparent. Error: " << SDL_GetError() << "\n";
return 1;
}
else
{
//Set the transparency flag to true
is_transparent = true;
return 0;
}
}
else
{
//Report that the image is already transparent
std::cout << "Image is already transparent. \n";
return 2;
}
}
main.cpp
I am compiling the Screen and Image stuff into a .dll and linking my test program to it. When I use a normal SDL_Surface* and load an image for that, it works fine. But if I try to use the Image and getImg_Surface, even making a new surface inbetween, it doesn't work and will just flash the screen before crashing and saying it returns three.
The debugger (gdb through C::B) says that the surfaces in the main_screen and background objects' internal surfaces aren't null and all the flags show that they loaded properly. It also says I'm getting a segmentation fault from SDL_GetRGB when it tries to apply the background.