Sign in to follow this  

SDL problem with passing pointers

This topic is 1082 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm totally stuck with trying to implement a texture wrapper class, when I'm passing a pointer to a method through a pointer it dies and I have no idea why. can anyone help.

 

I'm following lazy foo's tutorials (http://lazyfoo.net/tutorials/SDL/10_color_keying/index.php) and they load properly when i'm using his tutorial format, but when trying to take the texture wrapper into a class structure it loads but dies when it displays a screen.

 

my code is as follows

 

CTexture.h

#ifndef CTEXTURE_H_
#define CTEXTURE_H_

#include "capp.h"

using namespace std;

class CTexture
{
    SDL_Texture *_Texture;
    int _Width;
    int _Height;

public:
    CTexture();
    ~CTexture();

    bool fLoadFromFile( SDL_Renderer *pRenderer, string path );
    void fRender( SDL_Renderer *pRenderer, int x, int y);

    int fGetHeight() { return _Width; }
    int fGetWidth() { return _Height; }

    void fFreeResources();
};

#endif // CTEXTURE_H

CTexture.cpp


#include "CTexture.h"

CTexture::CTexture()
    :
    _Texture(NULL),
    _Width(0),
	_Height(0)
{
    //auto initialize
}

CTexture::~CTexture()
{
    fFreeResources();
}

bool CTexture::fLoadFromFile( SDL_Renderer *pRenderer, string path )
{
    fFreeResources(); //delete pre-existing texture

    SDL_Texture* newTexture = NULL;
    SDL_Surface* loadedSurface = IMG_Load( path.c_str() );

    if(loadedSurface == NULL)
    {
        printf("unable to load image", path.c_str(), IMG_GetError() );
    } else {
        SDL_SetColorKey( loadedSurface, SDL_TRUE, SDL_MapRGB( loadedSurface->format, 0, 0xFF, 0xFF ) );
        newTexture = SDL_CreateTextureFromSurface( pRenderer, loadedSurface );
        if(newTexture == NULL)
        {
            printf("unable to create new texture ", path.c_str(), SDL_GetError() );
        } else {
            _Width = loadedSurface->w;
            _Height = loadedSurface->h;
        }
        SDL_FreeSurface(loadedSurface);
    }
    _Texture = newTexture;
    return _Texture != NULL;
}

void CTexture::fFreeResources()
{
    if(_Texture != NULL)
    {
        _Texture = NULL;
        _Width = 0;
        _Height = 0;
    }
}

void CTexture::fRender( SDL_Renderer *pRenderer, int x, int y)
{
    SDL_Rect renderQuad = { x, y, _Width, _Height };
    SDL_RenderCopy( pRenderer, _Texture, NULL, &renderQuad );
}

The variables are initialized in main:

 

CTexture *charTexture;
CTexture *bgTexture;

And then loaded at the right time through a loadMedia function call:

    if(!charTexture->fLoadFromFile( Renderer, "images/foo.png"))
    {
        printf( "Failed to load 'images/foo.png' texture image!\n" );
        return false;
    } else {
        printf("Success: 'images/foo.png' loaded" );
    }

    if(!bgTexture->fLoadFromFile( Renderer, "images/background.png"))
    {
        printf( "Failed to load 'images/background.png' texture image!\n" );
        return false;
    } else {
        printf("Success: 'images/background.png' loaded" );
    }

    charTexture->fRender( Renderer, 0, 0 );
    bgTexture->fRender( Renderer, 240, 190 );

But It will not compile properly, any ideas what the hell I am doing wrong?

 

Share this post


Link to post
Share on other sites


But It will not compile properly

If it won't compile, then it will tell error message and you should post it.

 


any ideas what the hell I am doing wrong?

 

You didn't show if you create texture objects or not. Right now it looks like you're calling texture methods via uninitialized pointer.

Share this post


Link to post
Share on other sites

The variables are initialized in main:

CTexture *charTexture;
CTexture *bgTexture;
And then loaded at the right time through a loadMedia function call:

That's not an initialization, that's a declaration.

 

And then loaded at the right time through a loadMedia function call:
    if(!charTexture->fLoadFromFile( Renderer, "images/foo.png"))
    {
        printf( "Failed to load 'images/foo.png' texture image!\n" );
        return false;
    } else {
        printf("Success: 'images/foo.png' loaded" );
    }

    if(!bgTexture->fLoadFromFile( Renderer, "images/background.png"))
    {
        printf( "Failed to load 'images/background.png' texture image!\n" );
        return false;
    } else {
        printf("Success: 'images/background.png' loaded" );
    }

    charTexture->fRender( Renderer, 0, 0 );
    bgTexture->fRender( Renderer, 240, 190 );
But It will not compile properly, any ideas what the hell I am doing wrong?

I'm guessing Renderer is a SDL_Renderer*, right? Or something else? You should follow some convention on the naming of variables, charTexture and Renderer look like different things (a variable and a class name respectively).

 

Also:

void CTexture::fFreeResources()
{
    if(_Texture != NULL)
    {
        _Texture = NULL;
        _Width = 0;
        _Height = 0;
    }
}

That's not freeing the resources for the _Texture, your just setting the pointer to null, you need to use SDL_DestroyTexture with _Texture.

Edited by DiegoSLTS

Share this post


Link to post
Share on other sites

I managed to fix this in the end after learning more on pointers, turns out I didn't initialize the pointer therefore it folded in on itself!

 

I have managed to make a texture wrapper class and I'm trying to implement a linked list for the generation of the textures/objects for when they are needed.

 

Do I 'Have' to initialize the textures at the point of initialization or can I call them when they are needed from the folders, is this way around a redundant way of thinking?

 

Any feed back would be greatly appreciated.

Share this post


Link to post
Share on other sites

I have managed to make a texture wrapper class and I'm trying to implement a linked list for the generation of the textures/objects for when they are needed.

std::list is a standard library available to you (#include <list>) that is a linked list.
However, std::vector (or, depending on what you are doing, std::unordered_map) is a superior choice here.
 

Do I 'Have' to initialize the textures at the point of initialization or can I call them when they are needed from the folders

No, you don't need to point your pointers at dynamic memory the moment you create them, but you should at least initialize your pointers to null. You should never leave variables uninitialized.
 

Blah *myPointer; //Bad. Points to a random gibberish location in memory. 'Bad Things Happen' if you accidentally try to use it.
Blah *myPointer = nullptr; //Better. If you try to read or write to a null pointer, your program crashes. And that's a *good* thing.

However, in general, it's preferred not to use raw pointers to micro-manage memory lifetimes.

Even though SDL does this, that's because SDL is designed for the 'C' language.

In C++, it's better if your variables manage their own allocations and deallocations, to prevent human error mistakes when writing code.

 

Wrapping the texture in a class is one possible correct thing to do, but you might want to post your implementation (inbeween [ code ] and [ /code ] tags) so we can make sure it is written properly. Dynamic memory can be difficult to get right if you are just starting to learn the language.

Share this post


Link to post
Share on other sites
#ifndef __TEXTURE_H__
#define __TEXTURE_H__

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

#include <iostream>
#include <string>

class Texture
{
private:
    int _X = 0;
    int _Y = 0;
    int _Width = 0;
    int _Height = 0;

    SDL_Texture* _Texture = NULL;

public:
    Texture()
    {
        std::cout << "Texture constructor called" << std::endl;
    };
    ~Texture()
    {
        std::cout << "Texture destructor called" << std::endl;
        if(_Texture)
        {
            SDL_DestroyTexture(_Texture);
            _Texture = NULL;
        }
    }

    bool Load(std::string, SDL_Renderer*);

    void Render(SDL_Renderer*);
    void Render(int X, int Y, int Width, int Height, SDL_Renderer*);

    int GetWidth();
    int GetHeight();
};

#endif

And

 
 


#include "Texture.h"

bool Texture::Load(std::string Filename, SDL_Renderer* pRenderer) {
	if(pRenderer == NULL)
    {
		std::cout << "Bad SDL renderer passed" << std::endl;
		return false;
	}

	SDL_Surface* pTempSurface = IMG_Load(Filename.c_str());
	if(pTempSurface == NULL)
    {
        std::cout << "pTempSurface IMG_Load failed" << std::endl;
		return false;
	}

    // Convert SDL surface to a texture
	if((_Texture = SDL_CreateTextureFromSurface(pRenderer, pTempSurface)) == NULL)
    {
        std::cout << "pTempSurface SDL_CreateTextureFromSurface failed" << std::endl;
		return false;
	}

    // Grab dimensions
	SDL_QueryTexture(_Texture, NULL, NULL, &_Width, &_Height);

	SDL_FreeSurface(pTempSurface);

	return true;
}

void Texture::Render(SDL_Renderer* pRenderer)
{
	SDL_Rect Destination = {_X, _Y, _Width, _Height};
	SDL_RenderCopy(pRenderer, _Texture, NULL, &Destination);
}


//------------------------------------------------------------------------------
void Texture::Render(int x, int y, int Width, int Height, SDL_Renderer* pRenderer)
{
    _X=x;
    _Y=y;
    _Width=Width;
    _Height=Height;
	SDL_Rect Destination = {x, y, Width, Height};
	SDL_RenderCopy(pRenderer, _Texture, NULL, &Destination);
}


Edited by Ubermeowmix

Share this post


Link to post
Share on other sites

Thanks Servant, that has to be the best reply I've ever had to any post ever, you've really helped me in a lot of areas as I definitely picked up bad habits from stumbling across Hungarian notation, and I didn't realize that the underscore would cause so much trouble.

 

A hell of a lot of this is me learning as I'm going so some of the changes I am making are just due to inexperience and lack of understanding so you've really helped me fill a lot of the gaps in. I'm off to tweak a lot of my code now and start aiming toward making an actual game that I can be proud of.

 

Thanks again, I am going to print this and keep referencing it to remind me what not to do.

Share this post


Link to post
Share on other sites

This topic is 1082 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this