Sign in to follow this  
HJSimpson

Problem with class using SDL

Recommended Posts

HJSimpson    122
I have some classes that I am trying to test. They use SDL and draw images or text to the screen. Sprite inherits from Drawable which contains functions for Drawing and resizing the images, Sprite conatins a few functions for moving the sprite around the screen and choosing a frame. I'll post all the code that the test program uses. The problem is that it only draws one sprite, when it should draw two. testSprite won't draw unless backGround is created. backGround doesn't even have to have the image loaded, or anything but a declaration. But backGround won't draw. However, declaring and even attempting to draw a third sprite doesn't remedy the situation with backGround not Drawing. It seems that testSprite is the only one that will draw. Drawable.h and Drawable.cpp
#ifndef DRAWABLE_H
#define DRAWABLE_H
#include "SDL\SDL.h"
#include "SDL\SDL_image.h"
#include <string>

class Drawable
{
private:

protected:
	SDL_Rect destRect, srcRect;
	SDL_Surface *image;
public:
	Drawable(int, int, int, int);
	Drawable(){}
	virtual ~Drawable();
	bool Load(std::string);
	bool Draw(SDL_Surface *);
	void Resize(int, int);
	void Free();
};

#endif

///////////////////////////////////////////////////////////////////

#include "Drawable.h"

Drawable::Drawable(int x=0, int y=0, int h=0, int w=0)
{
	destRect.x=x;
	destRect.y=y;
	destRect.h=h;
	destRect.w=w;
	srcRect.x=x;
	srcRect.y=y;
	srcRect.h=h;
	srcRect.w=w;
}

Drawable::~Drawable()
{
}

bool Drawable::Load(std::string filePath)
{
	image=IMG_Load(filePath.c_str());
	if(image==NULL)
	{
		return false;
	}
	return true;
}

bool Drawable::Draw(SDL_Surface *dest)
{
	if(SDL_BlitSurface(image, &srcRect, dest, &destRect)<0)
	{
		return false;
	}
	return true;
}

void Drawable::Free()
{
	SDL_FreeSurface(image);
}

void Drawable::Resize(int h, int w)
{
	destRect.h=h;
	destRect.w=w;
	srcRect.h=h;
	srcRect.w=w;
}


Sprite.h and Sprite.cpp
#ifndef SPRITE_H
#define SPRITE_H
#include "drawable.h"

class Sprite : public Drawable
{
private:

public:
	Sprite();
	~Sprite();
	void MoveTo(int, int);
	void MoveBy(int, int);
	void GotoFrame(int);
};

#endif

///////////////////////////////////////////////////////

#include "Sprite.h"

Sprite::Sprite()
{
}

Sprite::~Sprite()
{
}

void Sprite::MoveTo(int x, int y)
{
	destRect.x=x;
	destRect.y=y;
}

void Sprite::MoveBy(int x, int y)
{
	destRect.x+=x;
	destRect.y+=y;
}

void Sprite::GotoFrame(int frame)//not used
{
	srcRect.y=srcRect.h*frame;
}


main
#include "SDL\SDL.h"
#include "SDL\SDL_ttf.h"
#include "Sprite.h"

int main(int argc, char* args[])
{
	SDL_Surface *screen;
	bool game;
	SDL_Event e;
	Sprite testSprite, backGround;
	
	/*********************************
	SDL Initialization****************
	*********************************/
	if(SDL_Init(SDL_INIT_VIDEO)<0)
	{
		return 1;//exit if SDL fails to init
	}

	if(TTF_Init()<0)
	{
		return 1;
	}

	screen=SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);

	if(screen==NULL)
	{
		return 1;//exit if screen doen't init
	}

	SDL_WM_SetCaption("Test", NULL);

	/*******************************
	Game Object initialization******
	*******************************/

	if(!testSprite.Load(".\\test.png"))
		return 1;
	if(!backGround.Load(".\\bg.png"))
		return 1;

	testSprite.Resize(40, 40);
	testSprite.MoveTo(30, 30);
	backGround.Resize(480, 640);
	backGround.MoveTo(0, 0);

	/*******************************
	Game Loop***********************
	*******************************/

	game=true;
	while(game)//game loop
	{
		/***********************
		Drawing*****************
		***********************/
		backGround.Draw(screen);
		testSprite.Draw(screen);

		SDL_Flip(screen);	

		/*********************
		Event handling********
		*********************/
		
		SDL_PollEvent(&e);
		switch(e.type)
		{
		case SDL_KEYUP:			
			switch(e.key.keysym.sym)
			{
			case SDLK_ESCAPE:
				game=false;
				break;
			}//end e.key.keysym.sym

			break;//end SDLK_KEYUP
		case SDL_QUIT:
			game=false;
			break;//end SDL_QUIT
		}//end e.type
	}//end game loop
	
	/*************************
	Clean up******************
	*************************/
	
	testSprite.Free();
        backGround.Free();
	SDL_FreeSurface(screen);
	TTF_Quit();
	SDL_Quit();
	return 0;
}


BTW: All of the images do load properly.

Share this post


Link to post
Share on other sites
DeadXorAlive    535
The SDL api unfortunatly doesn't support resizing by itself, so perhaps the problem is connected to that. Have the source rect be only initialized by the Load function (image->w and image->h) and touched nowhere else. Otherwise I couldn't see what was going on exactly.

And since you have in C++ automatic destruction of objects, put SDL_FreeImage(image) in the destructor, you can get rid of the free function and all is fine. (this is called raii)
Also change to Sprite constructor to:

Sprite::Sprite()
: image(0) // initialize image to NULL, 0 can be used for that and is recommended.
{
}

Share this post


Link to post
Share on other sites
HJSimpson    122
By resizing I didn't mean making the actual image smaller, moving and resizing the rectangle inside that it clips from the sprite. Sorry about not being clear.

So, I added the initialization of image to Drawable's constructor. Changed the SDL_FreeSurface to be part of the destructor for Drawable, but this still happens.

If it helps I am using MS VC++ 2005 Express.

Share this post


Link to post
Share on other sites
DeadXorAlive    535
So testSprite will be drawn as expected if and only if a backGround is created, while backGround isn't drawn at all? I can't see what could be the problem myself, so I'll leave you with this:
What you can do is to find the bug is:
- use assertions, if you don't know about them: include <cassert>, then assert(image != 0); for example will generate a runtime error pointing out the source of evil if image == 0. Sprinkle your code with them where you expect conditions to be true. Defining NDEBUG will get rid of them when you compile for a release version.
- simplify the test cases down to a version that works, somewhere in between this and your original code lies the bug.
- use a debugger, it can be a help and your IDE is supposed to have quite a good one.

Sorry I couldn't be of more help and good luck.

Share this post


Link to post
Share on other sites

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