• (2 Pages)
  • +
  • 1
  • 2

Beginning SDL - Part 3 - A Sprite/Drawing Class

#1 stayscrisp  Icon User is offline

  • フカユ
  • member icon

Reputation: 1009
  • View blog
  • Posts: 4,197
  • Joined: 14-February 08

Posted 28 June 2009 - 07:44 AM

*
POPULAR

Beginning SDL - Part 3 - Sprite Drawing Class

Ok in this tutorial we will write a class that will draw objects to the screen, this will be useful when we want to start creating entities or GUI objects.

So lets get started...

First create 2 new files, Sprite.h and Sprite.cpp

Open up Sprite.h and lets get coding

#ifndef  _SPRITE_H_
#define _SPRITE_H_

#include <SDL.h>

class Sprite
{
	public:
		   
			 Sprite();
			 
			 static SDL_Surface* Load(char* pFile);
			  
			 static   bool   Draw(SDL_Surface* dest, SDL_Surface* src, int x, int y);
			  
			  static bool   Draw(SDL_Surface* dest, SDL_Surface* src, int x, int y, int x2,  
			  int y2, int width, int height);
};


#endif



So thats the Sprite.h file, its quite basic for the moment but we will extend it and improve upon it over time, but for now this will do nicely. Lets write the functions themselves now, open up the Sprite.cpp

#include "Sprite.h"

// constructor 
Sprite::Sprite()
{
}




here we will load the file needed to draw the surface, this will be the filename of a compatible BMP, we create 2 pointers to SDL surfaces and set them to NULL. These surfaces are used to store the data of the created surface, one is used to load the file onto, and the other is used to optimize the surface, we then return the optimized surface and free the unused temp surface


SDL_Surface* Sprite::Load(char* File)
{
	SDL_Surface* temp = NULL;
	SDL_Surface* optimized = NULL;

	if((temp = SDL_LoadBMP(File)) == NULL)
	{
		  return NULL;
	}
	
	optimized = SDL_DisplayFormatAlpha(temp);
	SDL_FreeSurface(temp);

	return optimized;
}




now we need to have a function that blits the BMP to an SDL surface, we pass in the screen and the name of the surface we loaded our BMP onto, we also pass in where we want to draw it. We use the x and y values to create an SDL_Rect, we then blit to this using SDL_Blitsurface();


bool Sprite::Draw(SDL_Surface* dest, SDL_Surface* src, int x, int y)
{
	  if(dest == NULL || src == NULL)
	   {
				  return false;
	   }

	   SDL_Rect  destR;

	   destR.x = x;
	   destR.y = y;

	   SDL_BlitSurface(src, NULL, dest, &destR);
	   
		return true;
}




this next function only draws part of the bitmap, this is especially useful when using sprite sheets as you will find out in later tutorials, we pass in the values for an SDL_Rect again like last time, but we now will create another rectangle this one will be used to tell which part of the image to draw, so if we where to pass in x2 = 0, y2 = 0, w = 50, h = 50 , it would draw the top corner of the image, a 50 x 50 square.


bool Sprite::Draw(SDL_Surface* dest, SDL_Surface* src, int x, int y, int x2, int y2, int width, int height) {
	if(dest == NULL || src == NULL) {
		return false;
	}
	
	SDL_Rect destR;
	
	destR.x = x;
	destR.y = x;
	
	SDL_Rect srcR;
	
	srcR.x = x2;
	srcR.y = y2;
	srcR.w = width;
	srcR.h = height;
	
	SDL_BlitSurface(src, &srcR, dest, &destR);
	
	return true;
}



Ok so thats our sprite class, we can use this to draw any image to the screen and also draw only the parts of the image that we want. lets test these functions out inside our game loop.

Open up the Game.h file and add this code

// we need to include the "Sprite.h" file that we just created
#include "Sprite.h"

private:
	 
	  // add a surface to test our functions.
	  SDL_Surface* testSprite;



now open up the Game.cpp file and add some more code

// inside the Init function add this code
testSprite = NULL;

testSprite = Sprite::Load("test.bmp");


// now inside the Draw function add this code
Sprite::Draw(m_pScreen, testSprite, 0, 0);



Ok now build and run, you should see the image in the top left corner of the window, pretty easy huh :)

ok now we need to test our other function, we can use the same image we loaded last time so in Game.cpp file
// inside our Draw function
Sprite::Draw(m_pScreen, testSprite, 300, 300, 0, 0, 50, 50);



Now build and run, you should see a small 50x50 square of our original image.

So to recap we created a sprite class, I call it a sprite class but if it makes more sense you could call it a drawing class or whatever your prefer. This class blits images to the screen, we also created a function to only draw specific parts of an image.

One thing we need to do after all that is to free our test sprite surface so as to avoid memory leaks, we can use our Clean function in Game.cpp to add this code

SDL_FreeSurface(testSprite);



Ok now we are done, next time we will incorporate some transparency and also an external library to use images other than BMP's.

Heres the image I used
Attached File  test.bmp (144.05K)
Number of downloads: 1249

Happy Coding.

Is This A Good Question/Topic? 9
  • +

Replies To: Beginning SDL - Part 3 - A Sprite/Drawing Class

#2 Guest_J3d1*


Reputation:

Posted 03 August 2009 - 04:50 AM

Thanks you! Recently has started to study C++, gcc, make, SDL for creation of simple games. Your articles very much help me. Waiting for continuation...:)
Was This Post Helpful? 0

#3 Shikoro  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 08-August 09

Posted 11 August 2009 - 05:25 AM

Good tut ;) Hope to see more parts of it :D

This post has been edited by Shikoro: 11 August 2009 - 05:29 AM

Was This Post Helpful? 0
  • +
  • -

#4 stayscrisp  Icon User is offline

  • フカユ
  • member icon

Reputation: 1009
  • View blog
  • Posts: 4,197
  • Joined: 14-February 08

Posted 17 December 2009 - 01:08 PM

Didn't realise these little things I missed in these tutorials, but heres another.

When testing the function in Game::Draw() add SDL_Flip(m_pScreen);

Thanks :)
Was This Post Helpful? 0
  • +
  • -

#5 haiyun211  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 1
  • View blog
  • Posts: 58
  • Joined: 27-July 09

Posted 02 August 2010 - 09:56 PM

View Poststayscrisp, on 17 December 2009 - 12:08 PM, said:

Didn't realise these little things I missed in these tutorials, but heres another.

When testing the function in Game::Draw() add SDL_Flip(m_pScreen);

Thanks :)


Where in the program do you Initialize m_pScreen? I don't see where it states what type of variable it is. Everything I have tried does not work because I cant figure out where it goes. Any help? Thanks in advance.
Was This Post Helpful? 0
  • +
  • -

#6 stayscrisp  Icon User is offline

  • フカユ
  • member icon

Reputation: 1009
  • View blog
  • Posts: 4,197
  • Joined: 14-February 08

Posted 03 August 2010 - 03:01 AM

Hi,

Sorry yes I just noticed the problem. In the previous tutorial I called this variable screen but during writing this tutorial I must have renamed it to m_pScreen. Check the Game.h file and there is a variable
SDL_Surface* screen
rename this to m_pScreen and then when you build all the instances will be pointed out as errors for you to change. Or you could seek them out yourself as there are not that many.

Hope that helps you and anyone else with this tutorial.
Was This Post Helpful? 0
  • +
  • -

#7 haiyun211  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 1
  • View blog
  • Posts: 58
  • Joined: 27-July 09

Posted 03 August 2010 - 05:52 PM

Thanks stayscrisp for the help that should solve the compile error.
Was This Post Helpful? 0
  • +
  • -

#8 heyoman1  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 64
  • View blog
  • Posts: 735
  • Joined: 30-November 09

Posted 14 June 2011 - 04:44 PM

I'm not sure how to solve this, but I get this error:

/usr/bin/ld: cannot find -lS
collect2: ld returned 1 exit status

EDIT:

I found out that the -lS meant that I was linking to -lSDL wrong. :P

This post has been edited by heyoman1: 14 June 2011 - 05:03 PM

Was This Post Helpful? 0
  • +
  • -

#9 JacksonD  Icon User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 215
  • Joined: 18-October 11

Posted 21 October 2011 - 07:01 PM

I am new to this language, interesting.
Was This Post Helpful? 0
  • +
  • -

#10 kiasta  Icon User is offline

  • D.I.C Regular

Reputation: 22
  • View blog
  • Posts: 260
  • Joined: 18-November 07

Posted 25 November 2011 - 09:13 PM

Is this right?

    destR.x = x;
    destR.y = x;



Or is it supposed to be:

    destR.x = x;
    destR.y = y;



Nitpicky, I know... lol.
Was This Post Helpful? 0
  • +
  • -

#11 gamer27lv  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 11-May 12

Posted 12 May 2012 - 07:41 AM

So would you add an animation class or add the animation functions to your sprite class?
Was This Post Helpful? 0
  • +
  • -

#12 ljfox4  Icon User is offline

  • D.I.C Head

Reputation: 2
  • View blog
  • Posts: 67
  • Joined: 10-February 07

Posted 18 May 2012 - 04:41 PM

Wonderful tutorial so far. Quick question, however. What is the advantage of static member functions over normal ones?

Instead of this:

 static   bool   Draw(SDL_Surface* dest, SDL_Surface* src, int x, int y);



Could you do this?

//removed src parameter
bool   Draw(SDL_Surface* dest, int x, int y);



And the object already knows that it is itself that it wants to draw. So my question I suppose is why do it static?


EDIT:
I always realize these things AFTER I post. The class doesn't actually hold the info. Just loads it. Got it. Never mind.

This post has been edited by ljfox4: 18 May 2012 - 04:44 PM

Was This Post Helpful? 0
  • +
  • -

#13 stayscrisp  Icon User is offline

  • フカユ
  • member icon

Reputation: 1009
  • View blog
  • Posts: 4,197
  • Joined: 14-February 08

Posted 21 May 2012 - 02:14 AM

Yeah, you got it. I figured I would make the sprite class as a kind of helper class that doesn't actually hold any info for a sprite it just does the loading for you and also the drawing when needed. Of course you could make a Sprite class that holds an SDL_Surface* and does the loading from within but I thought this to be a good way to start :)
Was This Post Helpful? 0
  • +
  • -

#14 gamer27lv  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 11-May 12

Posted 21 May 2012 - 02:30 AM

View Postljfox4, on 18 May 2012 - 04:41 PM, said:

EDIT:
I always realize these things AFTER I post. The class doesn't actually hold the info. Just loads it. Got it. Never mind.


"Rubber Duck Debugging" only not using a duck :-)
Was This Post Helpful? 0
  • +
  • -

#15 reversiblean  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 05-August 13

Posted 05 August 2013 - 09:29 AM

Great tutorail. BTW how did you access private memeber 'm_pScreen' from the class sprite?

And I was also wondering how could we blit something to screen from outside the Game class. : )
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2