Allegro 5 Screenshot

From Allegro Wiki
Jump to: navigation, search

About

If you want to add Screenshot functionality to your Allegro 5 project, simply copy and paste this code.

Code

///////////////////////////////////////////////////////////////////////////////
//
// Allegro 5 Screenshot Functions
//
// Usage:
//
// To save a screenshot Call:
// ale_screenshot(const char *destination_path, const char *gamename)
// 
// 
// If you simply want a screenshot to be saved when F12 is pressed, call:
//
// ale_screenshot_process_event(ALLEGRO_EVENT ev, const char *destination_path, const char *gamename)
//
// after receiving an Event, and the function will automatically check for the
// key press.
//
///////////////////////////////////////////////////////////////////////////////




// Save a copy of the current target_bitmap (usually what's on the screen).
// The screenshot is placed in `destination_path`.
// The filename will follow the format "`gamename`-YYYYMMDD[a-z].png"
// Where [a-z] starts at 'a' and increases (towards 'z') to prevent duplicates
// on the same day.
// This filename format allows for easy time-based sorting in a file manager,
// even if the "Modified Date" or other file information is lost.
//
// Arguments:
// `destination_path` - Where to put the screenshot. If NULL, uses
//      ALLEGRO_USER_DOCUMENTS_PATH.
//
// `gamename` - The name of your game (only use path-valid characters).
//      If NULL, uses al_get_app_name().
//
//
// Returns:
// 0 on success, anything else on failure.
inline int ale_screenshot(const char *destination_path, const char *gamename)
{
	ALLEGRO_PATH *path;
	char *filename, *filename_wp;
	struct tm *tmp;
	time_t t;
	unsigned int i;
	const char *path_cstr;

	if(!destination_path)
		path = al_get_standard_path(ALLEGRO_USER_DOCUMENTS_PATH);
	else
		path = al_create_path_for_directory(destination_path);

	if(!path)
		return -1;

	if(!gamename) {
		if( !(gamename = al_get_app_name()) ) {
			al_destroy_path(path);
			return -2;
		}
	}

	t = time(0);
	tmp = localtime(&t);
	if(!tmp) {
		al_destroy_path(path);
		return -3;
	}

	// Length of gamename + length of "-YYYYMMDD" + length of maximum [a-z] + NULL terminator
	if ( !(filename_wp = filename = (char *)malloc(strlen(gamename) + 9 + 2 + 1)) ) {
		al_destroy_path(path);
		return -4;
	}

	strcpy(filename, gamename);
	// Skip to the '.' in the filename, or the end.
	for(; *filename_wp != '.' && *filename_wp != 0; ++filename_wp);

	*filename_wp++ = '-';
	if(strftime(filename_wp, 9, "%Y%m%d", tmp) != 8) {
		free(filename);
		al_destroy_path(path);
		return -5;
	}
	filename_wp += 8;

	for(i = 0; i < 26*26; ++i) {
		if(i > 25) {
			filename_wp[0] = (i / 26) + 'a';
			filename_wp[1] = (i % 26) + 'a';
			filename_wp[2] = 0;
		}
		else {
			filename_wp[0] = (i % 26) + 'a';
			filename_wp[1] = 0;
		}

		al_set_path_filename(path, filename);
		al_set_path_extension(path, ".png");
		path_cstr = al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP);

		if (al_filename_exists(path_cstr))
			continue;

		al_save_bitmap(path_cstr, al_get_target_bitmap());
		free(filename);
		al_destroy_path(path);
		return 0;
	}

	free(filename);
	al_destroy_path(path);

	return -6;
}


// Automatically calls ale_screenshot when F12 is pressed.
// Returns 0 if a screenshot is saved, 1 if not, and anything else if an error occurs.
inline int ale_screenshot_process_event(ALLEGRO_EVENT ev, const char *destination_path, const char *gamename)
{
	if(ev.type != ALLEGRO_EVENT_KEY_DOWN)
		return 1;

	if(ev.keyboard.keycode != ALLEGRO_KEY_F12)
		return 1;

	return ale_screenshot(destination_path, gamename);
}

Usage

For Any Project

This will save a screenshot to the "screenshots/" directory.

if(User Clicks Screenshot Button || User does a funny dance)
	ale_screenshot("screenshots/", "YourProjectsName");

Convenience Function

If you have an Allegro 5 event loop, and just want a screenshot to be taken when F12 is pressed, you can use this code.

al_wait_for_event(event_queue, &ev);

ale_screenshot_process_event(ev, "screenshots/", "YourProjectsName");

... the rest of your game logic ...

You should already have a call to al_wait_for_event so just put the call to ale_screenshot_process_event after it, or elsewhere in your event processing.