Jump to content

  • Log In with Google      Sign In   
  • Create Account


Another SDL Error


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 Dante12129   Members   -  Reputation: 968

Like
0Likes
Like

Posted 21 March 2013 - 05:12 PM

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


#include <iostream>
#include "Screen.hpp"
#include "Image.hpp"
 
int main ( int argc, char* argv[] )
{
    if(SDL_Init(SDL_INIT_EVERYTHING) != 0)
    {
        std::cerr << "Failed to inialize SDL. Error:  " << SDL_GetError() << "\n";
        return 1;
    }
 
    myeng::Screen main_screen(600, 600, "Test");
    myeng::Image background(200, 200, "Background.png");
 
    main_screen.Screen_RepBack(200, 200, background.getImg_Surface());
    if(main_screen.Screen_Flip() != 0)
    {
        std::cerr << "Error flipping screen at line " << __LINE__ << "\n";
    }
 
    std::cout << main_screen.getScreen_Width() << "\n";
    std::cout << main_screen.getScreen_Height() << "\n";
    std::cout << main_screen.getScreen_Depth() << "\n";
 
    SDL_Delay(1000);
    SDL_Quit();
    return 0;
}
 

 

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.


Edited by Dante12129, 21 March 2013 - 06:14 PM.


Sponsor:

#2 EWClay   Members   -  Reputation: 655

Like
0Likes
Like

Posted 21 March 2013 - 06:22 PM

When you free optimizedImage, you free the surface that img_surface points to, because they are the same at that point. After that, you are using an surface that has been freed, which is an error.

#3 Dante12129   Members   -  Reputation: 968

Like
0Likes
Like

Posted 21 March 2013 - 07:13 PM

That was my problem, I just set it to nullptr between assigning it to img_surface and freeing it.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS