[A5] Just Sharing a simple screen shot function
Neil Roy

I just whipped up this screenshot function for my Allegro 5 project I thought I would share if anyone wants it. It doesn't have all the bells and whistles, it basically saves a screenshot in the same folder as your executable. It can be easily modified to save elsewhere, just provide the path as part of the gamename you send to it I suppose.

It saves with the date + the time, so if you supply a game name like my "DeluxePacman" it would save it as "DeluxePacman_20130905_144600.png" for example. It uses 24hour time and the full year. The order is "YYYYMMDD_HHMMSS" so it will be listed in the folder in order that it was taken. This also easily allows you to take multiple screenshots with no limits, one per second.

If you prefer another format, just change PNG to JPG or BMP or whatever Allegro supports. I tested it and it works for me just fine.

I don't know if there is a way to automatically detect physfs and perhaps have the function automatically call `al_set_standard_file_interface()` and `al_set_physfs_file_interface()` or not, I just whipped this up quickly, but it would be nice if that functionality could be added. I suppose it should probably be left up to the person though.

Edit: I just updated this code and used Elias' suggestion to store the current file interface state, then switch to standard file interface, save the bitmap and restore the old state to what it was. Great solution. Works perfectly. :)

a5_screenshot.c

#SelectExpand
1#include "a5_screenshot.h" 2 3bool a5_screenshot(const char *gamename) 4{ 5 time_t rawtime; 6 struct tm *timeinfo; 7 char filename[80], timestr[80]; 8 bool saved; 9 ALLEGRO_STATE state; 10 11 al_store_state(&state, ALLEGRO_STATE_NEW_FILE_INTERFACE); 12 13 al_set_standard_file_interface(); 14 15 time(&rawtime); 16 timeinfo = localtime(&rawtime); 17 18 strftime(timestr, 80, "%Y%m%d_%H%M%S", timeinfo); 19 snprintf(filename, 80, "%s_%s.png", gamename, timestr); 20 21 saved = al_save_bitmap(filename, al_get_target_bitmap()); 22 23 al_restore_state(&state); 24 25 if(!saved) return false; 26 27 return true; 28}

a5_screenshot.h

#ifndef _a5_screenshot_h_
#define _a5_screenshot_h_

#include "allegro5/allegro.h"
#include <stdio.h>

bool a5_screenshot(const char *gamename);

#endif //_a5_screenshot_h_

Elias

You can use al_get_new_file_interface to get the current file interface (and reset back to that if it's not the standard one). Or you can use al_store_state and al_restore_state with ALLEGRO_STATE_NEW_FILE_INTERFACE to store/restore the current file interface.

Neil Roy

Great idea Elias, thanks. I updated my original posts code to reflect your suggestion. Works great.

Edit: I tried this out with a5_screenshot("Screenshots/DeluxePacman2"); and it saved it into the "Screenshots" folder as expected. Of course, the folder has to already exist, but it does work which is nice.

Evert

How reliable is it that al_get_target_bitmap() gives you the front buffer (ie, what's currently on the screen) rather than the back buffer (ie, where stuff that is drawn actually goes)?

I assumed (based on manual) that there was no reliable cross-platform way to do that...

J-Gamer
Evert said:

I assumed (based on manual) that there was no reliable cross-platform way to do that...

Even if there isn't, couldn't you bypass this by calling the screenshot function after drawing your current frame(and before flipping the screen)? At 60fps, there normally isn't too much difference between two frames, and the user won't notice the screenshot is one frame off.

EDIT: this might be relevant: http://stackoverflow.com/questions/2661936/asynchronous-readback-from-opengl-front-buffer-using-multiple-pbos

Thomas Fjellstrom
J-Gamer said:

Even if there isn't, couldn't you bypass this by calling the screenshot function after drawing your current frame(and before flipping the screen)? At 60fps, there normally isn't too much difference between two frames, and the user won't notice the screenshot is one frame off.

One problem is that there's no guarantee that the backbuffer even contains what you drew, or that theres only two pages, there could be many more.

J-Gamer

One problem is that there's no guarantee that the backbuffer even contains what you drew, or that theres only two pages, there could be many more.

I meant taking a screenshot of the next frame instead of trying to get the current front buffer.

Thomas Fjellstrom

Ah, I missed that part. Sorry. Yeah, I expect that would work.

Or you could draw to a screen sized bitmap, and save that off.

It seems like some games do that, as it takes them some time to actually create and save a screenshot.

J-Gamer

Or you could draw to a screen sized bitmap, and save that off.It seems like some games do that, as it takes them some time to actually create and save a screenshot.

You could easily redraw the current frame to that bitmap, instead of using the next frame as a screenshot. That's a less hackish way of doing it, I suppose.

Thread #613224. Printed from Allegro.cc