An approach that can work is to place the sprite frames anywhere in the bitmap (so you can make them more compact) and accompany each bitmap file (n xml) that describes the location, size and origin of each frame AND has a list of all animations. Something like that:
<SpriteSheet> <Frames> <Frame id="0" location="20,40" size="64,64" origin="32,32" /> <Frame id="1" location="100,40" size="64,64" origin="32,32" /> <Frame id="2" location="164,40" size="64,64" origin="0,0" /> <Frame id="3" location="20,120" size="64,64" origin="32,32" /> </Frames> <Animations> <Animation name="walk left" > <Keyframes> <Keyframe frameId="0" duration="0:0:0.5" offset="-5,0" /> <Keyframe frameId="1" duration="0:0:0.5" offset="-5,0" /> <Keyframe frameId="2" duration="0:0:0.4" offset="-2,0" /> <Keyframe frameId="1" duration="0:0:0.5" offset="-5,0" /> </Keyframes> </Animation> <Animation name="walk right" > <Keyframes> <Keyframe frameId="5" duration="0:0:0.5" offset="5,0" /> <Keyframe frameId="6" duration="0:0:0.5" offset="5,0" /> <Keyframe frameId="2" duration="0:0:0.4" offset="2,0" /> <Keyframe frameId="6" duration="0:0:0.5" offset="5,0" /> </Keyframes> </Animation> </Animations> </SpriteSheet>
Thus, you can reuse frames in the animation (and thereby optimize the size of the bitmap images even more) and adjust the animation by simply editing the xml file.
All you have to do is read the XML file, read the bitmap, and when starting the animation: start the timer, which ticks at regular intervals. When it is ticking, you calculate the correct keyframe in the animation, adding the duration of the keyframes one by one and stopping when the sum is greater than the tick time; You must use the current keyframe.
In the xml file above, I added things like an offset, which allows you to change the position of the sprite during the animation (you can even interpolate it so that it moves smoothly)
All that remains is to capture the correct frame from the bitmap. As an optimization, you can pre-process the bitmap when loading the xml file by capturing frames, saving them as tiny bitmaps and discarding a large bitmap. This can optimize memory when the bitmap is large and not fully covered by frames.
In other cases, you do not pre-process and just blit the frame.
For large applications (more raster images / animations / frames), I recommend creating an application for creating and editing an XML file. Another option would be to create a plugin for your favorite painting program (if possible)