SDL Sprites in different sizes

Hi there, I am trying to understand how I would go about drawing sprites from an image, sprites with different sizes.

For example: When i load my image file and declare what width and height and how many frames there is per row. How would I go about getting different sizes from the same image? If i want a jump animation , or a crawl animation or whatever, they will be bigger than the walk animation.

Right now I am stuck with not being able to change the size. I have tried to change both the size of the frame and the size of the collision box, but it always fails, and even changing the collision box makes me fall through the ground :/

I don´t ask for a complete superb answer, just something to give me an idea on what would be needed.

Thanks for your time.
I don't know how your animations is working. Can't you just let each animation store width and height information. If each frame in the same animation can have different sizes you could store width and height for each frame instead.
It´s based on this tutorial:
http://www.sdltutorials.com/sdl-animation

Then in my entity class I have a instance of that animation class.

1
2
    protected:
        C_Animation     Anim_Control;


like so.

And this would be my method where i Load an image for my entity.
I also use some other params as you can see.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool C_Entity::OnLoad( std::string filename, int width, int height, int maxframes, int framerate )
{
    OnCleanup(); // Call before loading a new image

    if ((Surf_Entity = C_Surface::OnLoad( filename )) == NULL )
    {
        return false;
    }

    this->Width     = width;
    this->Height    = height;

    Anim_Control.MaxFrames = maxframes;
    Anim_Control.SetFrameRate( framerate );

    return true;

}


I just don´t know how I would go about doing what you said, some more explanation would be nice. Thanks
You want each frame of an animation to be able to have a different size? I would use an INI file for each animation. Each one would look like this:
[Animation]
File=Sprites/MySprite.png
[Frame1]
Width=64
Height=64
[Frame2]
Width=72
Height=64

You'd have to repeat the Frame sections for each frame in the sprite.

If you're not aware of the structure of INI files, it's very simple. They consist of two things: sections and properties. A section starts when some text wrapped in brackets is encountered, like [Animation] or [Frame1] in the example above. Each section can contain properties, and a property is just some text (the name) followed by an equals sign and then some more text (the value). You can also have properties outside of sections. Some INI parsers also support comments. My one only supports comments at the start of the line (whitespace notwithstanding), starting with a semi-colon (';'), which is fairly common AFAIK.

You'll need an INI parser; either find one on the Internet or write one yourself. They're not very difficult to write if you don't care about it being too robust. My one is pretty simple:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class IniParser {
private:
	std::map < std::string, std::map <std::string, std::string> > Data;
public:
	IniParser(std::ifstream& stream)
	{
		std::string line;
		std::string section;
		while (stream.good()) {
			std::getline(stream, line);
			{
				/* Strip leading whitespace.
				 */
				size_t start = line.find_first_not_of(" \t", 2);
				line.replace(0, start, "");
			}
			if ((line.size() < 1) || (line[0] == ';')) {
				/* Skip blank lines and comments. */
					continue;
			} else if (line[0] == '[') {
				/* Start of a new section. */
				size_t pos = line.find(']');
				section = line.substr(1, pos - 1);
			} else if (line.find('=') != std::string::npos) {
				size_t pos = line.find('=');
				std::string name = line.substr(0, pos);
				std::string value = line.substr(0, pos + 1);
				Data[section][name] = value;
			}
		}
		return true;
	}
};

It was originally written in C# but I just adapted it to C++. I left out any error checking and made it a bit simpler but it was basically just that.
Ye I want every frame, or row for that matter, to be able to have different sizes. Will this work with a INI file? And will it solve the problem of the character falling through or getting stuck because of the change in size?

And where would i go about updating the size? When i tried changing the size and the collision box in my C_Entity::OnAnimate I got those wierd results, so I reverted back to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
void C_Entity::OnAnimate()
{

    if ( MoveLeft == true )
    {

        Anim_Control.Oscillate = true;
        CurrentFrameRow = 2;

    }else

    if ( MoveRight == true )
    {

        Anim_Control.Oscillate = true;
        CurrentFrameRow = 2;

    }

    if ( MoveRight == false && MoveLeft == false && Jumping == false )
    {

        if ( Direction == ENTITY_DIRECTION_LEFT )
        {

            Anim_Control.Oscillate = true;
            CurrentFrameRow = 1;

        }

        if ( Direction == ENTITY_DIRECTION_RIGHT )
        {


            Anim_Control.Oscillate = true;
            CurrentFrameRow = 0;

        }

    }
    else
    {

        if ( Jumping == true )
        {
            CurrentFrameRow = 2;
        }

    }

    Anim_Control.OnAnimate();

}


Thanks.
It seems like that tutorial assumes all the animation frames will have the same size. It is probably the easiest way. You can add some extra space around the smaller frames and it will work. It will waste some memory though.

Changing the code to work with frames of different size is not straight forward. Now they can do CurrentFrameCol * Width and CurrentFrameRow * Height to get the position of the frame within the image. If the frames have different sizes you cannot do that so easily.
What would I have to do? Would i have to remake the whole process of moving the box a set amount of pixels over , to instead moving to set coordinates on the spritesheet and setting each frame with different width/height ?

Would be nice if anyone had any knowledge of how to do this that could just go a little deeper into what would be needed, since I can´t find anything on internet about this rather specific subject.
Last edited on
The easiest way to do this would be to use a GIF to store your sprites, where each frame of the GIF is a different frame of the sprite. The GIF just has to be as large as the largest frame. GIFs support transparency, so you don't have to worry about backgrounds. This way you wouldn't need the INI files either.

If you want to do it with differently sized frames anyway, then I recommend using some kind of data file (doesn't have to be INI, I just find them convenient) to store the width and height of each frame. Figuring out where to start each frame becomes as easy as summing the width (if your spritesheet grows sideways) or height (if it grows downwards) of every previous frame. Here's how I'd do it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
namespace Orientation {
        enum T {
                Horizontal, // Sprites go across
                Vertical // Sprites go downwards
        };
}

typedef Orientation::T Orientation_t;

int CalculateFrameCoords(int frame, Orientation_t orientation)
{
        std::stringstream sstream;
        std::string frameStr;
        int sum = 0;
        for (int i = 0; i < frame; ++i) {
                sstream << i;
                sstream >> frameStr;
                if (orientation == Orientation::Horizontal)
                        sum += this->Ini.GetValue("Frame" + frameStr, "Width");
                else
                        sum += this->Ini.GetValue("Frame" + frameStr, "Height");
        }
        return sum;
}

This will tell you the co-ordinates of the top-left corner of a given frame.
Last edited on
Topic archived. No new replies allowed.