Console Project/2. 출력 버퍼

C++|2019. 12. 9. 19:22

 문자 출력이 가능한 콘솔 창에서 2D 이미지를 출력하기 위해서는 이미지를 ASCII Art로 변환하여 출력해야 한다. 하지만 이미지의 픽셀 개수 만큼의 길이를 가진 문자열을 printf 혹은 std::cout 등으로 출력하는 방식은 대체로 느리다. 여러 이미지를 하나하나 화면에 그리다 보면 그려지는 순서가 보일 지경이 될 것이다.

 이를 개선하기 위해 출력 버퍼에 여러장의 이미지를 그린 후, 버퍼에 바뀜이 있을 때 화면을 갱신(출력)하면 보다 깔끔하게 출력이 가능할 것이다.

출력 버퍼

 ASCII Art는 텍스트로 이루어져 있으므로 char 배열로 buffer를 만든다.

int width = 200;
int height = 200;
char *buffer = new char[width * height];

// clear
for (int i = 0; i < width * height; i++) {
    buffer[i] = ' ';
}

// output to console
gotoXY(0, 0);
for (int i = 0; i < height; i++) {
    char line[width + 1];
    for (int j = 0; j < width; j++) {
        line[j] = buffer[i * width + j];
    }
    line[width] = '/0'; // end of string
    std::cout << line << std::endl;
}

이제 원하는 위치에 이미지를 버퍼에 그려 화면에 출력 할 수 있다. 아래는 이미지를 버퍼에 쓰는 작업을 하는 코드이다.

int posX = 10;
int posY = 25;

int imageWidth = image.width;
int imageHeight = image.height;
char* asciiArt = imageToAscii(image);

// draw image to buffer
for (int y = 0; y < iamgeHeight; y++) {
    for (int x = 0; x < imageWidth; x++) {
    
        // 이미지 픽셀에 대한 버퍼의 위치를 구한다.
        int bufferX = x + posX;
        int bufferY = y + posY;
        
        // 버퍼 밖으로 그리게 될 경우는 무시한다.
        if (bufferX < 0 || bufferX >= bufferWidth || bufferY < 0 || bufferY >= bufferHeight) {
            continue;
        }
        
        // 이미지의 픽셀 위치와 버퍼의 픽셀 위치를 구한다.
        int imageIndex = y * imageWidth + x;
        int bufferIndex = bufferY * bufferWidth + bufferX;
        
        // 이미지의 픽셀을 버퍼의 픽셀에 대입한다.
        buffer[bufferIndex] = asciiArt[imageIndex];
    }
}

// Output to Console
...

WriteConsoleOutput

 위의 코드로 이미지를 그릴 경우 초당 몇 ~ 십몇 프레임이상 그리지 못할 것이다. 이때 빠르게 콘솔에 출력하는 함수가 WriteConsoleOutput이다. 자세한 내용은 링크 참조.

2019/12/09 - [C++] - WriteConsoleOutput - Console 화면에 빠르게 출력하는 함수.

 

WriteConsoleOutput를 사용하려면 CHAR_INFO 배열이 필요한데 버퍼를 아예 CHAR_INFO 배열로 사용할 수 있다.

...

CHAR_INFO* buffer = new CHAR_INFO[width * height];

// clear
for (int i = 0; i < width * height; i++) {
    buffer[i].Char.AsciiChar = ' ';
    buffer[i].Attribute = 7; // white
}

// output to console
COORD pos = { 0, 0 }, size = { width, height };
SMALL_RECT rect = { 0, 0, width, height };
WriteConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE), buffer, size, pos, &rect);

클래스

기능을 클래스화하여 사용한다. 자세한 내용은 링크.

https://github.com/wakeup5/Console-Project/blob/master/Project/RenderBuffer.h

https://github.com/wakeup5/Console-Project/blob/master/Project/RenderBuffer.cpp

'C++' 카테고리의 다른 글

Console Project/4. GameLoop  (0) 2019.12.10
Console Project/3. 이미지  (0) 2019.12.10
Console Project/1. 화면  (0) 2019.12.09
Console Project  (0) 2019.12.09
WriteConsoleOutput - Console 화면에 빠르게 출력하는 함수.  (0) 2019.12.09

댓글()

Console Project/1. 화면

C++|2019. 12. 9. 18:37

 콘솔창에 ASCII Art를 출력하기 위해서는 적절한 글자 크기와 창 크기가 필요하다. 보다 높은 해상도의 이미지를 그리기 원한다면 가능한 작은 글자 크기로 셋팅해야 할 것이다.

글자 크기 조절

콘솔의 글자 크기는 SetCurrentConsoleFontEx함수를 통해 임의의 크기로 설정할 수 있다. cfi.dwFontSize에 원하는 크기의 값을 입력하면 된다. 체크하면서 폭과 높이가 일치하는 사이즈를 찾으면 된다.

CONSOLE_FONT_INFOEX cfi;
cfi.cbSize = sizeof(cfi);
cfi.nFont = 0;
cfi.dwFontSize.X = 2;
cfi.dwFontSize.Y = 2;
cfi.FontFamily = FF_DONTCARE;
cfi.FontWeight = FW_NORMAL;
wcscpy_s(cfi.FaceName, TEXT("Raster Fonts"));

SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &cfi);

화면 크기 조절

 게임의 해상도를 미리 정해 놓고 그에 맞는 화면 크기를 설정한다. 이 프로젝트에서는 200x200으로 한다.

SMALL_RECT windowSize = { 10, 10, 210, 210 };
SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &windowSize)

타이틀

 게임 타이틀 설정은 다음과 같다.

SetConsoleTitle(TEXT("Console Project"));

'C++' 카테고리의 다른 글

Console Project/3. 이미지  (0) 2019.12.10
Console Project/2. 출력 버퍼  (0) 2019.12.09
Console Project  (0) 2019.12.09
WriteConsoleOutput - Console 화면에 빠르게 출력하는 함수.  (0) 2019.12.09
C++ Image Library - CImg  (0) 2019.12.08

댓글()

Console Project

C++|2019. 12. 9. 17:03

 요즘 유니티로만 개발을 하다보니 C#을 너무 사랑했던 나머지 배웠던 C++을 다 잊어버릴 지경에 다다랐다. 오랜만에 C++도 다뤄보고 학원에 다닐 때 Console용 포트폴리오 게임을 만들었던 기억이 나 Console용으로 가벼운 게임을 하나 만들기로 결심했다.

 다만 텍스트로 표현했던 기존의 콘솔 프로그램 게임 대신 텍스트로 이미지를 표현하여 2D게임을 만들어 보고자 한다.

링크

모든 코드는 https://github.com/wakeup5/Console-Project에서 볼 수 있다.

목차

2019/12/09 - [C++] - Console Project/1. 화면

2019/12/09 - [C++] - Console Project/2. 출력 버퍼

2019/12/10 - [C++] - Console Project/3. 이미지

2019/12/10 - [C++] - Console Project/4. GameLoop

2019/12/10 - [C++] - Console Project/4.5 중간보고

2019/12/10 - [C++] - Console Project/5. 문자 출력

2019/12/12 - [C++] - Console Project/6. 키 입력

2019/12/14 - [C++] - Console Project/7. TileMap

 

개발 하면서 얻은 팁

2019/12/08 - [C++] - C++ Image Library - CImg

2019/12/09 - [C++] - WriteConsoleOutput - Console 화면에 빠르게 출력하는 함수.

'C++' 카테고리의 다른 글

Console Project/3. 이미지  (0) 2019.12.10
Console Project/2. 출력 버퍼  (0) 2019.12.09
Console Project/1. 화면  (0) 2019.12.09
WriteConsoleOutput - Console 화면에 빠르게 출력하는 함수.  (0) 2019.12.09
C++ Image Library - CImg  (0) 2019.12.08

댓글()

WriteConsoleOutput - Console 화면에 빠르게 출력하는 함수.

C++|2019. 12. 9. 15:39

 일반적으로 Console에 출력할 때에 printf 혹은 std::cout을 사용하게 된다. 하지만 Console 프로그램 게임에서 전체 이미지 등을 표시하기에는 느리다는 단점이 있다.

 이를 해결하기 위한 방법으로는 WriteConsoleOutput 함수가 있다. CHAR_INFO array로 이루어진 buffer에 먼저 쓴 후, 해당 함수에 전달하면 빠르게 콘솔에 출력할 수 있다.

int width = 10;
int height = 10;

CHAR_INFO buffer[width * height];

for (int i = 0; i < width * height; i++) {
    buffer[i].Char.UnicodeChar = 'a';
    buffer[i].Attributes = 7; 
    // 7을 입력할 경우 흰색으로 출력.
    // 자세한 내용은 
    // https://docs.microsoft.com/en-us/windows/console/char-info-str
    // 참조.
}

COORD pos = { 0, 0 }, size = { width, height };
SMALL_RECT rect = { 0, 0, width, height };
WriteConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE), buffer, size, pos, &rect);

 

'C++' 카테고리의 다른 글

Console Project/3. 이미지  (0) 2019.12.10
Console Project/2. 출력 버퍼  (0) 2019.12.09
Console Project/1. 화면  (0) 2019.12.09
Console Project  (0) 2019.12.09
C++ Image Library - CImg  (0) 2019.12.08

댓글()