Open schroederdewitt opened 6 years ago
I guess there maybe could be a way to expose the draw buffer through the C++ interface. But maybe this should exist in the BWAPI interface instead, and let OpenBW fullfill that? I can imagine people would want to do the same thing on all BW platforms?
And yes, it will most certainly run faster than pysc2 as long as the marshalling doesn't completely destroy performance. This game is from 1998 when it even ran on mediocre PCs and this is even an optimized headless version of it.
Also, out of a developers' perspective, it should never be underestimated to write ML code in C++, even if it's easier to prototype in Python, which should most definitely be available.
Thanks for your response. I have had a look at the code, it seems that the getScreenBuffer() BWAPI method is not yet implemented. However, maybe it is possible to extract the GameScreenBuffer from the Game.h?
There is actually now a std::tuple<int, int, uint32_t*> drawGameScreen(int x, int y, int width, int height)
function in Game (Broodwar->drawGameScreen). It returns a buffer (rgb data) along with the width and height of the buffer (could be slightly bigger than requested for memory alignment).
Here's some dirty example code to save a .bmp of some hardcoded position in the game:
typedef int LONG;
typedef unsigned char BYTE;
typedef unsigned int DWORD;
typedef unsigned short WORD;
typedef struct tagBITMAPFILEHEADER
{
WORD bfType; // 2 /* Magic identifier */
DWORD bfSize; // 4 /* File size in bytes */
WORD bfReserved1; // 2
WORD bfReserved2; // 2
DWORD bfOffBits; // 4 /* Offset to image data, bytes */
} __attribute__((packed)) BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize; // 4 /* Header size in bytes */
LONG biWidth; // 4 /* Width of image */
LONG biHeight; // 4 /* Height of image */
WORD biPlanes; // 2 /* Number of colour planes */
WORD biBitCount; // 2 /* Bits per pixel */
DWORD biCompress; // 4 /* Compression type */
DWORD biSizeImage; // 4 /* Image size in bytes */
LONG biXPelsPerMeter; // 4
LONG biYPelsPerMeter; // 4 /* Pixels per meter */
DWORD biClrUsed; // 4 /* Number of colours */
DWORD biClrImportant; // 4 /* Important colours */
} __attribute__((packed)) BITMAPINFOHEADER;
auto save = [&](const char *filename, int width, int height, unsigned char *data) {
BITMAPFILEHEADER bmp_head;
BITMAPINFOHEADER bmp_info;
int size = width * height * 3;
bmp_head.bfType = 0x4D42; // 'BM'
bmp_head.bfSize= size + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); // 24 + head + info no quad
bmp_head.bfReserved1 = bmp_head.bfReserved2 = 0;
bmp_head.bfOffBits = bmp_head.bfSize - size;
// finish the initial of head
bmp_info.biSize = 40;
bmp_info.biWidth = width;
bmp_info.biHeight = height;
bmp_info.biPlanes = 1;
bmp_info.biBitCount = 24;
bmp_info.biCompress = 0;
bmp_info.biSizeImage = size;
bmp_info.biXPelsPerMeter = 0;
bmp_info.biYPelsPerMeter = 0;
bmp_info.biClrUsed = 0 ;
bmp_info.biClrImportant = 0;
// finish the initial of infohead;
// copy the data
FILE *fp;
if (!(fp = fopen(filename,"wb"))) return 0;
fwrite(&bmp_head, 1, sizeof(BITMAPFILEHEADER), fp);
fwrite(&bmp_info, 1, sizeof(BITMAPINFOHEADER), fp);
fwrite(data, 1, size, fp);
fclose(fp);
};
int pitch;
int height;
uint32_t* buf;
std::tie(pitch, height, buf) = Broodwar->drawGameScreen(100, 100, 256, 256);
std::array<uint8_t, 256 * 256 * 3> bmp_buf;
for (size_t i = 0; i != height * pitch; ++i) {
uint32_t r = buf[i] & 0xff;
uint32_t g = (buf[i] >> 8) & 0xff;
uint32_t b = (buf[i] >> 16) & 0xff;
bmp_buf[i * 3] = b;
bmp_buf[i * 3 + 1] = g;
bmp_buf[i * 3 + 2] = r;
}
save("test.bmp", pitch, height, (unsigned char*)bmp_buf.data());
The screen position doesn't matter, this function only draws the requested area. No real guarantees about speed or stability (dont request areas outside of the map). But it should work.
int pitch; int height; uint32_t* buf; std::tie(pitch, height, buf) = Broodwar->drawGameScreen(100, 100, 256, 256);
or, in C++17 ;)
auto [pitch, height, buf] = Broodwar->drawGameScreen(100, 100, 256, 256);
Hi,
I would like to use OpenBW for deep reinforcement learning. For this, I need
I am happy to contribute a Boost::Python3 binding for BWAPI myself, but BWAPI does not allow to extract game screenshots. My questions are as follows:
Thanks and regards
Christian Schroeder de Witt