Jump to content
  • Advertisement
Sign in to follow this  
GenuineXP

SDL Sprite Class Problem

This topic is 4814 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 just keep running into problems... Anyway, the class I created to load and draw sprites in my program (using SDL) isn't working! I create a sprite object and I can display it just fine. I can set a transparent color, and animate images using a strip. Here's the problem: if I ever create more than one sprite object, the program crashes! Actually, if I create another empty sprite object (default constructor with no arguments), then the program runs, but it doesn't exit properly; it crashes! Another thing I realized is that, for some reason, if my destructor isn't declared virtual, then I can't create any sprite objects without the program immediately crashing! Please help! Here's the code for the class. (I hope I post the code correctly. :-P ) SPRITE.H
#ifndef SPRITE_H
#define SPRITE_H

#include<SDL/SDL.h>

#define UINT unsigned short int

class sprite
{
    protected:
        SDL_Surface*  m_psfImage;    //image surface
        SDL_Color     m_cColorKey;   //transparent color key
        Uint8         m_cAlpha;      //alpha channel
        SDL_Rect      m_rBndBox;     //sprite bounding box
        UINT          m_iNumFrms;    //number of frames in the image
        UINT          m_iFrmWidth;   //width of each frame
        UINT          m_iCurrentFrm; //the current frame to display
        
        void LoadFile( char* szFName );
        void ApplyColorKey( SDL_Color cCol );
        void ApplyAlpha( Uint8 iA );
    public:
                 sprite();
                 sprite( char* szFName );
                 sprite( char* szFName, UINT iNFrms, UINT iFrmW);
                 //sprite( const sprite& rhs );
        virtual ~sprite();
        
        void NextFrame( UINT iRate = 1 );
        void Draw( SDL_Surface* sfDest, int iLocX, int iLocY );
        void Reload( char* szFName );
        void Reload( char* szFName, UINT iNFrms, UINT iFrmW );

        void SetColorKey( SDL_Color cCol );
        void SetColorKey( UINT iR, UINT iG, UINT iB );
        void SetAlpha( UINT iA );
        void SetCurrentFrame( UINT iCFrm )  { m_iCurrentFrm = iCFrm; }
        void SetNumFrames( UINT iNFrms )    { m_iNumFrms = iNFrms;   }
        //void SetFrameWidth( UINT iFrmW )    { m_iFrmWidth = iFrmW;   }
        
        SDL_Rect      GetBoundBox()      const { return m_rBndBox;     }
        SDL_Surface*  GetSurface()       const { return m_psfImage;    }
        SDL_Color     GetColorKey()      const { return m_cColorKey;   }
        UINT          GetCurrentFrame()  const { return m_iCurrentFrm; }
        UINT          GetNumFrames()     const { return m_iNumFrms;    }
        UINT          GetFrameWidth()    const { return m_iFrmWidth;   }
        
        //static void NextFrame( UINT iRate = 1 );
};

#endif
SPRITE.CPP
#include <SDL/SDL.h>
#include <SDL/SDL_Image.h>

#include "sprite.h"

sprite::sprite()
{

}
sprite::sprite( char* szFName )
{
    sprite::LoadFile( szFName );
        m_iNumFrms     = 1;
        m_iFrmWidth    = m_psfImage->w;
        m_iCurrentFrm  = 0;
    
    m_rBndBox.x = 0;
    m_rBndBox.y = 0;
    m_rBndBox.w = m_iFrmWidth;
    m_rBndBox.h = m_psfImage->h;
}
sprite::sprite( char* szFName, UINT iNFrms, UINT iFrmW )
{
    sprite::LoadFile( szFName );
        m_iNumFrms     = iNFrms;
        m_iFrmWidth    = iFrmW;
        m_iCurrentFrm  = 0;
        
    m_rBndBox.x = 0;
    m_rBndBox.y = 0;
    m_rBndBox.w = m_iFrmWidth;
    m_rBndBox.h = m_psfImage->h;
}
/*
sprite::sprite( const sprite& rhs )
{
    if ( &rhs == this )
    {
        return;
    }
    //...
}
*/
sprite::~sprite()
{
    if ( m_psfImage == NULL )
    {
        return;
    }
    SDL_SetColorKey( m_psfImage, 0, 0 );
    SDL_FreeSurface( m_psfImage );
    m_psfImage = NULL;
}
void sprite::LoadFile( char* szFName )
{
    if ( m_psfImage != NULL )
    {
        SDL_FreeSurface( m_psfImage );
    }
    SDL_Surface* psfTemp = IMG_Load( szFName );
    if ( psfTemp == NULL )
    {
        return;
    }
    m_psfImage = SDL_DisplayFormat( psfTemp );
    if ( m_psfImage == NULL )
    {
        SDL_FreeSurface( psfTemp );
        return;
    }
    SDL_FreeSurface( psfTemp );
    return;
}
void sprite::Reload( char* szFName )
{
    sprite::LoadFile( szFName );
        m_iNumFrms     = 1;
        m_iFrmWidth    = m_psfImage->w;
        m_iCurrentFrm  = 0;
        
    m_rBndBox.x = 0;
    m_rBndBox.y = 0;
    m_rBndBox.w = m_iFrmWidth;
    m_rBndBox.h = m_psfImage->h;

    return;
}
void sprite::Reload( char* szFName, UINT iNFrms, UINT iFrmW )
{
    sprite::LoadFile( szFName );
        m_iNumFrms     = iNFrms;
        m_iFrmWidth    = iFrmW;
        m_iCurrentFrm  = 0;
        
    m_rBndBox.x = 0;
    m_rBndBox.y = 0;
    m_rBndBox.w = m_iFrmWidth;
    m_rBndBox.h = m_psfImage->h;

    return;
}
void sprite::ApplyColorKey( SDL_Color cCol )
{
    if (
        SDL_SetColorKey(
            m_psfImage,
            SDL_SRCCOLORKEY,
            SDL_MapRGB( m_psfImage->format, cCol.r, cCol.g, cCol.b )
        )
    < 0 )
    {
        return;
    }
    return;
}
void sprite::ApplyAlpha( Uint8 iA )
{
    if (
        SDL_SetAlpha(
            m_psfImage,
            SDL_SRCALPHA | SDL_RLEACCEL,
            iA
        )
    < 0 )
    {
        return;
    }
    return;
}
void sprite::SetColorKey( SDL_Color cCol )
{
    m_cColorKey = cCol;
    sprite::ApplyColorKey( m_cColorKey );
}
void sprite::SetColorKey( UINT iR, UINT iG, UINT iB )
{
    if ( iR > 255 ) { iR = 255; }
    if ( iG > 255 ) { iG = 255; }
    if ( iB > 255 ) { iB = 255; }
    
    m_cColorKey.r = (Uint8)iR;
    m_cColorKey.g = (Uint8)iG;
    m_cColorKey.b = (Uint8)iB;
    sprite::ApplyColorKey( m_cColorKey );
    return;
}
void sprite::SetAlpha( UINT iA )
{
    m_cAlpha = (Uint8)iA;
    sprite::ApplyAlpha( m_cAlpha );
    return;
}
void sprite::NextFrame( UINT iRate )
{
    m_iCurrentFrm += iRate;
    if ( m_iCurrentFrm >= m_iNumFrms )
    {
        m_iCurrentFrm = 0 + ( m_iCurrentFrm - m_iNumFrms );
    }
    return;
}
void sprite::Draw( SDL_Surface* psfDest, int iLocX, int iLocY )
{
    if ( psfDest == NULL )
    {
        return;
    }

    SDL_Rect rSrcBox;
        rSrcBox.x  = (int)( m_iCurrentFrm * m_iFrmWidth );
        rSrcBox.y  = 0;
        rSrcBox.w  = (int)( m_iFrmWidth );
        rSrcBox.h  = m_psfImage->h;

    SDL_Rect rDstBox;
        rDstBox.x  = iLocX;
        rDstBox.y  = iLocY;
        rDstBox.w  = rSrcBox.w;
        rDstBox.h  = rSrcBox.h;

    SDL_BlitSurface( m_psfImage, &rSrcBox, psfDest, &rDstBox );
    
    return;
}
At the moment, this class is missing a lot of functionality that I want to add... but I can't see why it's not working. :-( Does anyone see anything here that I've done wrong?

Share this post


Link to post
Share on other sites
Advertisement
I got no compile errors. The only error message I receive says the program terminated with status 1 (when the program runs properly, it ends with status 0).

Share this post


Link to post
Share on other sites
Can I ask why you're using protected instead of private? That class isn't inherited, at least as far as your code shows me. Try using private instead.

Share this post


Link to post
Share on other sites
You have:

UINT m_iFrmWidth; //width of each frame

But in the constructor you do:

m_iFrmWidth = m_psfImage->w;


It should be the image width divided by the number of frames shouldn't it?

Share this post


Link to post
Share on other sites
I used...
m_iFrmWidth    = m_psfImage->w;
...in that constructor because it's overloaded. With that constructor, the user supplies only a filename and the class assumes that there is no animation, so the frame width is equal to the width of the image surface.

I'll try using a private declaration rather than a protected declaration. I only did it that way because I thought I might derive from this class at some point.

Share this post


Link to post
Share on other sites
The protected vs private question has nothing to do with the program crashing.

Also, it is possible that the problem is not in the class, but in the code that uses the class. Have you tried running the code through the debugger to find out exactly where it is crashing?

edit - I also noticed that your default constructor doesn't initialize any of the member variables. Thus, your SDL_surface pointer could be pointing to random memory and your other variables could have funky values.

Share this post


Link to post
Share on other sites
Yeah, changing the protected declaration to private had no effect. :-(

I'll see what I can find with the debugger... but the only code using this class is a little test program that doesn't do much more than display an image and move it via a joystick.

Share this post


Link to post
Share on other sites
An uninitialized pointer comes to mind.

In your LoadFile method, you are checking if m_psfImage is not NULL. If it's not NULL, you do a SDL_FreeSurface. However, since m_psfImage is never initialized to NULL, it could easily have a random value when LoadFile is called.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!