Concepts
Each frame of a GIF can have a different duration, measured in 1/100s of second.
GameMaker does not currently support per-frame timings in dynamically loaded sprites,
so instead you can provide an array to be populated with per-frame delays
and then use that for accurate playback (see the demo project).
Turns out that the more sub-images your sprite has,
the longer it takes to add new ones to it!
(likely because GameMaker tries to fit them on a texture page).
As this can become a source of problems for long GIFs,
you can provide an array to be populated with single-frame sprites
for individual frames.
When doing so, you will still get a sprite back from the calls,
but it will be the last frame of the GIF.
If you don't want the game to freeze while adding a GIF,
you can opt for the _start
versions of the functions
Functions
path
Wherever to take your GIF from (should be accessible by the game).
xorig, yorig
Origin of the sprite, just like in the regular sprite_add
.
frame_delays (optional)
If provided, per-frame timings will be added to this array
(see frame delays).
frame_sprites (optional)
If provided, each frame will be added to this array as a separate sprite
(see frame delays).
Returns a gif_reader to work with.
For example,
sprite = sprite_add_gif("cool.gif", 16, 16);
Like sprite_add_gif,
but uses gradual loading,
loads the GIF from a buffer,
and returns a gif_reader.
Attention: The buffer will-be used as-is and should not be touched/deleted
while the GIF is loading. You can destroy it after you call finish().
Reader API
sprite_add_gif_start and sprite_add_gif_buffer_start functions return you a
gif_reader
struct (or array-thing in old GameMaker versions)
for gradual loading.
These have the following methods:
GM:S name: gif_reader_next
Does one step of the loading process
(that's reading a GIF section or adding a frame to the sprite).
Returns whether there's still more work left to do.
For example, what sprite_add_gif_buffer
does is just about:
var reader = sprite_add_gif_buffer_start(buffer, 0, 0);
while (reader.next()) {}
var sprite = reader.finish();
Or, for old GameMaker versions:
var reader = sprite_add_gif_buffer_start(buffer, 0, 0);
while (gif_reader_next(reader)) {}
var sprite = gif_reader_finish(reader);
GM:S name: gif_reader_next_few
Like next, but does one or more steps
until a timeout (in milliseconds) is reached or there's nothing left to do.
The function aborts after a step so it may take longer than the requested interval.
Returns whether there's still more work left to do.
For example, if you wanted to freeze the game for roughly 100ms at the time,
you could do:
// Create
reader = sprite_add_gif_buffer("cool.gif", 0, 0);
sprite = -1;
// Step
if (reader != undefined) {
if (reader.next_few(100)) {
// not done yet!
} else {
sprite = reader.finish();
reader = undefined;
}
}
Or, for old GameMaker versions:
// Create
reader = sprite_add_gif_buffer("cool.gif", 0, 0);
sprite = -1;
// Step
if (reader != undefined) {
if (gif_reader_next_few(reader, 100)) {
// not done yet!
} else {
sprite = gif_reader_finish(reader);
reader = undefined;
}
}
GM:S name: gif_reader_finish
This function frees up any intermediate structures used by the reader
and returns the final sprite.
It can also be called amid loading to abort the process.
Info:
get_last_action_name()
GM:S name: gif_reader_get_last_action_name
Returns the name of the action that was done during the last
next() call.
This is mostly useful if you're trying to figure out what takes the longest.
GM:S name: gif_reader_get_last_action
Like above, but returns the index of the action.
For possible values, see gif_reader_action
enum.
GM:S name: gif_reader_get_frame_count
Returns the number of frames that are "complete" and ready to use.
GM:S name: gif_reader_get_sprite
Returns the reader's sprite, which might not have all the frames yet,
but can still be drawn if you need to show something as soon as possible.
If frame sprites are enabled, this is the latest frame.
May return -1
if the GIF is invalid or we haven't completed a single frame yet.