SDL Sprite SheetOpinions on my sprite sheet function
22 Replies - 7546 Views - Last Post: 08 July 2010 - 05:51 AM
#1
SDL Sprite Sheet
Posted 28 June 2010 - 06:02 PM
Here is the function:
http://pastebin.com/AubnfLTJ
I think I am going to pair this with a texturing function like lazyfoo did. But I wanna make sure It looks good before I go any further.
Thanks in advance,
ZOMBIE!!!
Replies To: SDL Sprite Sheet
#2
Re: SDL Sprite Sheet
Posted 28 June 2010 - 06:05 PM
// Wraps a rectangle around every sprite in a sprite sheet and stores it in an array of rectangles(Clip[])
void spriteSheet(string FileName, int SpriteWidth = 64,int SpriteHeight= 64, int SheetDimension = 4){
int Sprites = SheetDimension * SheetDimension;// Number of Sprites on sheet
SDL_Rect Clip[Sprites]; // Rectangles that will wrap around each sprite
int SpriteXNum = 0;// The number sprite going from left to right
int SpriteYNum = 0;// The number sprite going from top to bottom
int YIncrement = 0;// Increment for each row.
for(int i = 0; i< Sprites; i++){// While i is less than number of sprites
if(i = 0){// First sprite starts at 0,0
Clip[i].x = 0;
Clip[i].y = 0;
Clip[i].w = SpriteWidth;
Clip[i].h = SpriteHeight;
}
else{
if(SpriteXNum < SheetDimension - 1 ){// If we have reached the end of the row, go back to the front of the next row
SpriteXNum = 0;
}
if(YIncrement < SheetDimension - 1){
SpriteYNum += 1; // Example of 4X4 Sheet
} // ________________
Clip[i].x = SpriteWidth * SpriteXNum; // | 0 | 1 | 2 | 3 |
Clip[i].y = SpriteHeight * SpriteYNum; // |===============|
// | 0 | 1 | 2 | 3 |
// |===============|
Clip[i].w = SpriteWidth; // | 0 | 1 | 2 | 3 |
Clip[i].h = SpriteHeight; // |===============|
// | 0 | 1 | 2 | 3 |
} // |---------------|
SpriteXNum++;
YIncrement++;
}
}
#4
Re: SDL Sprite Sheet
Posted 29 June 2010 - 03:44 PM
#5
Re: SDL Sprite Sheet
Posted 29 June 2010 - 03:58 PM
#6
Re: SDL Sprite Sheet
Posted 01 July 2010 - 01:55 AM
#include <string>
#include <iostream>
#include <vector>
#include <SDL/SDL.h>
#include <iostream>
using namespace std;
// Wraps a rectangle around every sprite in a sprite sheet and stores it in an array of rectangles(Clip[])
void loadSpriteSheet(string FileName, vector<SDL_Surface*> Frames, int SpriteWidth = 64,int SpriteHeight= 64, int SheetDimension = 4){
int Sprites = SheetDimension * SheetDimension;// Number of Sprites on sheet
SDL_Rect Clip[Sprites]; // Rectangles that will wrap around each sprite
SDL_Surface* SpriteSheet = SDL_LoadBMP(FileName.c_str());
int SpriteXNum = 0;// The number sprite going from left to right
int SpriteYNum = 0;// The number sprite going from top to bottom
int YIncrement = 0;// Increment for each row.
for(int i = 0; i< Sprites; i++){// While i is less than number of sprites
if(i = 0){// First sprite starts at 0,0
Clip[i].x = 0;
Clip[i].y = 0;
Clip[i].w = SpriteWidth;
Clip[i].h = SpriteHeight;
}
else{
if(SpriteXNum < SheetDimension - 1 ){// If we have reached the end of the row, go back to the front of the next row
SpriteXNum = 0;
}
if(YIncrement < SheetDimension - 1){
SpriteYNum += 1; // Example of 4X4 Sheet
} // ________________
Clip[i].x = SpriteWidth * SpriteXNum; // | 0 | 1 | 2 | 3 |
Clip[i].y = SpriteHeight * SpriteYNum; // |===============|
// | 0 | 1 | 2 | 3 |
// |===============|
Clip[i].w = SpriteWidth; // | 0 | 1 | 2 | 3 |
Clip[i].h = SpriteHeight; // |===============|
// | 0 | 1 | 2 | 3 |
} // |---------------|
SpriteXNum++;
YIncrement++;
cout<<"IN LOOP"<<endl;
}
SDL_Rect Offset;
Offset.x = 0;
Offset.y = 0;
for(int i = 0; i < Sprites; i++){
SDL_BlitSurface(SpriteSheet,&Clip[i],Frames[i],&Offset);
}
cout<<"BLITTING IN FUNC"<<endl;
}
int main(int args, char* argv[])
{
if(SDL_Init(SDL_INIT_EVERYTHING) == -1){
cout<<"Error in initializing"<<endl;
}
cout<<"SDL INITIALIZED"<<endl;
vector<SDL_Surface*> Frames;
loadSpriteSheet("SpriteSheet.bmp", Frames,32,32,2);
SDL_Surface* Screen = NULL;
Screen = SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
SDL_BlitSurface(Frames[1],NULL,Screen,NULL);
if(Screen == NULL){
cout<<"Error in blitting to screen";
}
SDL_Delay(2000);
for(int i = 0;i<Frames.size();i++){
SDL_FreeSurface(Frames[i]);
}
SDL_FreeSurface(Screen);
SDL_Quit;
return 0;
}
I'm not getting any errors, but when I run it, nothing happens. I placed a lot of cout<<"in loop" in for loops to make sure I am not in an infinite loop, but nothing shows up. Not even when it should go into the loop.
Thanks for playing the game in advance,
ZOMBIE!!!
#7
Re: SDL Sprite Sheet
Posted 01 July 2010 - 06:23 AM
Alternatively, you can include <windows.h> and use the MessageBox() function to help you debug.
MessageBox(NULL, "IN LOOP", "Debugging", MB_OK);
I always use the latter because the pop up message box is a very easy and obvious method.
Also, a few things that i noticed in your code:
1) You included iostream twice
2) You don't need to free your screen surface because SDL_Quit() will do that for you.
3) You should check to see if the screen is NULL after you set the video mode, and before you try to blit to it.
4) Inside of your loadSpriteSheet function at the bottom, you don't need the Offset variable because if you pass NULL as the fourth parameter of SDL_BlitSurface then it will use (0, 0) for the destination position.
5) You don't free your SpriteSheet surface. You should free it at the end of your loadSpriteSheet function.
Now for why it's not working... I would check to see what your SDL_BlitSurface functions return because they may be failing. If SDL_BlitSurface fails it will return -1. Check it in your loadSpriteSheet function and in your main.
I hope that helps you.
This post has been edited by Fib: 01 July 2010 - 07:03 AM
#8
Re: SDL Sprite Sheet
Posted 01 July 2010 - 08:17 AM
This kind of thing is much easier to achieve by simply creating a function that only draws a specific part of an image, then you can pass in the needed values. A sprite sheet is just one large image split into smaller images, you can loop through it by knowing the height and width of the images and then drawing only that part, incrementing the height or width each time.
The method you seem to be trying would only really work if you used lots of individual images and then pushed them onto a vector, not very efficient.
Here is an example of a function that draws only part of an image.
bool DrawPartOfImage(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;
}
#9
Re: SDL Sprite Sheet
Posted 01 July 2010 - 02:58 PM
#10
Re: SDL Sprite Sheet
Posted 01 July 2010 - 06:28 PM
#include <string>
#include <iostream>
#include <vector>
#include <SDL/SDL.h>
#include <iostream>
using namespace std;
// Takes one frame of a sprite sheet (Sheet) and applies it to
// a frame (Frame)
void loadFrame(SDL_Surface* Sheet, SDL_Surface* Frame, int SpriteWidth, int SpriteHeight, int SheetDimensionX, int SheetDimensionY, int FrameNum){
SDL_Rect Clip;
Clip.w = SpriteWidth;
Clip.h = SpriteHeight;
int Row = 1;
int Column = 1;
for(int i = 1; i <= FrameNum; i++){
if(Column > SheetDimensionX){
Column = 1;
}
if(i > SheetDimensionX){
Row++;
SheetDimensionX *= 2;
}
if(i == FrameNum){
break;
}
Column++;
cout<<"Column: "<<Column<<"/t"<<"Row: "<<Row<<endl;
}
Clip.x = (Column - 1) * SpriteWidth;
Clip.y = (Row - 1) * SpriteHeight;
SDL_Rect Offset;
Offset.x = 0;
Offset.y = 0;
SDL_BlitSurface(Sheet, &Clip, Frame, &Offset);
}
int main(int args, char* argv[])
{
SDL_Init(SDL_Init(SDL_INIT_EVERYTHING));
SDL_Surface* Screen = NULL;
Screen = SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
SDL_Surface* SpriteSheet = SDL_LoadBMP("SpriteSheet.bmp");
SDL_Surface* Frame = NULL;
loadFrame(SpriteSheet, Frame, 32, 32, 2, 2, 2);
SDL_BlitSurface(Frame,NULL,Screen,NULL);
SDL_Delay(2000);
SDL_Quit();
return 0;
}
I don't know if it works because code::blocks is have issues with plugins. But if you can offer a more efficient way of finding the x and y coordinate of the frame please let me know. Also, one other quick question: Would it be better to run "Frame" as a parameter, or return an SDL_Surface* like Frame = loadFrame(SpriteSheet,32,32,2,2)?
Thanks again,
ZOMBIE!!!
#11
Re: SDL Sprite Sheet
Posted 01 July 2010 - 11:54 PM
#include "SDL/SDL.h"
#include <string>
#include <vector>
#include <iostream>
using namespace std;
// Takes one frame of a sprite sheet (Sheet) and applies it to
// a frame (Frame)
int loadFrame(SDL_Surface* Sheet, SDL_Surface* Frame, int SpriteWidth, int SpriteHeight, int SheetDimensionX, int SheetDimensionY, int FrameNum){
if(Sheet == NULL){
cerr<<"SPRITESHEET WAS NULL"<<endl;
return -1;
}
SDL_Rect Clip;
Clip.w = SpriteWidth;
Clip.h = SpriteHeight;
int Row = 1;
int Column = 1;
for(int i = 1; i <= FrameNum; i++){
if(Column > SheetDimensionX){
Column = 1;
}
if(i > SheetDimensionX){
Row++;
SheetDimensionX *= 2;
}
if(i == FrameNum){
break;
}
Column++;
}
cout<<"Column "<<Column<<endl<<"Row "<<Row<<endl;
Clip.x = (Column - 1) * SpriteWidth;
Clip.y = (Row - 1) * SpriteHeight;
cout<<"X "<<Clip.x<<endl<<"Y "<<Clip.y<<endl;
cout<<"Width "<<Clip.w<<endl<<"Height "<<Clip.h<<endl;
SDL_BlitSurface(Sheet, &Clip, Frame, NULL);
if(Frame == NULL){
cerr<<"FRAME IS NULL AFTER BLITTING"<<endl;
return -1;
}
return 0;
}
int main(int args, char* argv[])
{
SDL_Init(SDL_Init(SDL_INIT_EVERYTHING));
SDL_Surface* Screen = NULL;
Screen = SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
SDL_Surface* SpriteSheet = SDL_LoadBMP("SpriteSheet.bmp");
if(SpriteSheet == NULL){
return 2;
}
SDL_Surface* Frame = NULL;
if(loadFrame(SpriteSheet, Frame, 32, 32, 2, 2, 3) == -1){
return -1;
}
SDL_BlitSurface(Frame,NULL,Screen,NULL);
SDL_Delay(2000);
SDL_Quit();
return 0;
}
Thanks for any help,
ZOMBIE!!!
#12
Re: SDL Sprite Sheet
Posted 02 July 2010 - 06:16 AM
SDL_Init(SDL_Init(SDL_INIT_EVERYTHING));
This line is at the top of your main.
It should be:
SDL_Init(SDL_INIT_EVERYTHING);
Also, don't forget to free all of your surfaces. Your not freeing spriteSheet, or Frame. The only surface that you don't have to free is screen because SDL_Quit() does that for you.
I hope that helps.
This post has been edited by Fib: 02 July 2010 - 06:18 AM
#13
Re: SDL Sprite Sheet
Posted 03 July 2010 - 06:46 PM
Can anyone find a problem:
#include "SDL/SDL.h"
#include <string>
#include <vector>
#include <iostream>
using namespace std;
// Takes one frame of a sprite sheet (Sheet) and applies it to
// a frame (Frame)
int loadFrame(SDL_Surface* Sheet, SDL_Surface* Frame, int SpriteWidth, int SpriteHeight, int SheetDimensionX, int SheetDimensionY, int FrameNum){
cout<<endl<<endl<<"In loadFrame():"<<endl;
if(Sheet == NULL){
cerr<<"Sprite Sheet was NULL"<<endl;
return -1;
}
SDL_Rect Clip;
Clip.w = SpriteWidth;
Clip.h = SpriteHeight;
int Row = 1;
int Column = 1;
for(int i = 1; i <= FrameNum; i++){
if(Column > SheetDimensionX){
Column = 1;
}
if(i > SheetDimensionX){
Row++;
SheetDimensionX *= 2;
}
if(i == FrameNum){
break;
}
Column++;
}
Clip.x = (Column - 1) * SpriteWidth;
Clip.y = (Row - 1) * SpriteHeight;
cout<<"Blitting Sheet to Frame"<<endl;
SDL_BlitSurface(Sheet, &Clip, Frame, NULL);
if(Frame == NULL){
cerr<<"Error in Blitting"<<endl;
SDL_FreeSurface(Sheet);
return -1;
}
SDL_FreeSurface(Sheet);
cout<<"End of loadSheet()"<<endl;
return 0;
}
int main(int args, char* argv[])
{
cout<<"Initializing SDL..."<<endl;
if(SDL_Init(SDL_INIT_EVERYTHING)== -1){
cerr<<"ERROR IN INITIALIZING SDL"<<endl;
return -1;
}
SDL_Surface* Screen = NULL;
Screen = SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
SDL_Surface* SpriteSheet = NULL;
cout<<"Loading SpriteSheet.bmp..."<<endl;
SpriteSheet = SDL_LoadBMP("SpriteSheet.bmp");
if( SpriteSheet == NULL){
cerr<<"ERROR IN LOADING SPRITESHEET.BMP"<<endl;
return -1;
}
SDL_Surface* Frame = NULL;
cout<<"Using loadFrame function..."<<endl;
if(loadFrame(SpriteSheet, Frame, 32, 32, 6, 4, 3) == -1){
cerr<<"loadFrame RETURNED -1"<<endl;
return -1;
}
cout<<"Blitting Frame to Screen..."<<endl;
SDL_BlitSurface(Frame,NULL,Screen,NULL);
SDL_Delay(2000);
cout<<endl<<endl<<"Quitting SDL..."<<endl;
SDL_Quit();
return 0;
}
#14
Re: SDL Sprite Sheet
Posted 06 July 2010 - 06:22 AM
For example:
SpriteSheet = SDL_LoadBMP("c:\\game\\graphics\\SpriteSheet.bmp");
Just replace the string with the path to your SpriteSheet.bmp. Don't forget to use the double slashes (\\) in your path.
If that doesn't work... well then I don't know.
This post has been edited by Fib: 06 July 2010 - 06:22 AM
#15
Re: SDL Sprite Sheet
Posted 06 July 2010 - 07:29 AM
The way I described would not need to know the x and y coordinates of the sprite sheet frame, it only needs to know the height and width of each part of the sprite sheet. You could then pass the maximum number of frames and the row or column you want to loop through.
pseudo code
Walk Button Pressed ()
{
Player->Animate(8,1); // the walk loop has 8 frames and is in the first column of the sprite sheet
}
Attack Button Pressed ()
{
Player->Animate(3,2); // the attack loop has 3 frames and is in the second column of the sprite sheet
}
This is what you might want to achieve. I can give you a few more pointers if you need them but I would have a good rethink about your load frame function and try to logically step through it, as it seems to be messing with your code.
This post has been edited by stayscrisp: 06 July 2010 - 07:29 AM
|
|

New Topic/Question
Reply




MultiQuote





|