1

Ive been designing a roguelike video game in the console.

My problem is i initially draw the entire map with writeconsoleoutput at once then use writeconsoleoutputcharacter to redraw whats neccessary. But i have found that it draws an extra pixel thick on the right side. This essentially erases one pixel off the tile on the right side.

Does anyone know a way to make it stop drawing a character and adding a 1 pixel blank space on the right side of the character.

EDIT: ONE WORKAROUND I HAVE FOUND IS TO REDRAW THE LINES THE PLAYER STEPS ON BUT IT ISNT PERFECT ONCE IN A WHILE I CAN NOTICE A FLICKER. Would be preferable to just redraw characters on an individual basis without any pixels attached on the end. or anywhere else. The Code used to print the character

void printchar(char character, COORD location,short color)
{
    const char *pointer = &character;
    //short LENGTH = 1;
    DWORD dwWritten = 0;
    std::vector<WORD> attributes;attributes.clear();;
    setAttributesChar(color,attributes);//Pushes back the color
    if(attributes.size() == 1)
    {    WriteConsoleOutputAttribute(GetStdHandle(STD_OUTPUT_HANDLE),&attributes[0], attributes.size(), location, &dwWritten);
        WriteConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), pointer, attributes.size(), location, &dwWritten); 
    }
}

void setAttributesChar(short color,std::vector<WORD> &attributes)
{
    switch(color)
    {
    case DEFAULTCOLOR:
        attributes.push_back(FOREGROUND_INTENSE_WHITE);return;
    case HOVEREDCOLOR:
        attributes.push_back(FOREGROUND_GREEN);return;
    case RED:
        attributes.push_back(FOREGROUND_RED);return;
    case GOLD:
        attributes.push_back(FOREGROUND_INTENSE_YELLOW);return;
    case REDWHITE:
        attributes.push_back(COMBINED_REDWHITE);return;
    case YELLOWPURPLE:
        attributes.push_back(COMBINED_YELLOWPURPLE);return;
    case NPCCOLOR:
        attributes.push_back(FOREGROUND_INTENSE_CYAN);return;
    case PURPLE:
        attributes.push_back(FOREGROUND_MAGENTA);return;
    case REDPURPLE:
        attributes.push_back(COMBINED_REDPURPLE);return;
    case BLUE:
        attributes.push_back(FOREGROUND_BLUE);return;
    case BLUEPURPLE:
        attributes.push_back(COMBINED_BLUEPURPLE);return;
    case INTENSEGREEN:
        attributes.push_back(FOREGROUND_INTENSE_GREEN);return;
    case REDGREEN:
        attributes.push_back(COMBINED_REDGREEN);return;
    case BWHITE:
        attributes.push_back(BACKGROUND_WHITE);return;
    }
}

EXAMPLE:

BEFORE CHARACTER WALKS OVER ROAD: BEFORE IMAGE

AFTER CHARACTER WALKS OVER ROAD: AFTER IMAGE

EXECUTABLE LINK: EXECUTABLE

I have created a working example that you guys can compile(Assuming u use windows) to see what is occuring. In it i create a console set the size fill the screen with the asci symbol 223. then i use Writeconsoleoutchar to print a green 223 symbol. You can see the extra drawn black pixel line.

#include <windows.h>
#include <cwchar>
#include <vector>
enum COLORS{HOVEREDCOLOR};
void setAttributesChar(short color,std::vector<WORD> &attributes)
{
    switch(color)
    {
    case HOVEREDCOLOR:
        attributes.push_back(FOREGROUND_GREEN);return;
    }
}
void printchar(char character, COORD location,short color)
{
    const char *pointer = &character;
    //short LENGTH = 1;
    DWORD dwWritten = 0;
    std::vector<WORD> attributes;attributes.clear();;
    setAttributesChar(color,attributes);//Pushes back the color
    if(attributes.size() ==1)
    {      WriteConsoleOutputAttribute(GetStdHandle(STD_OUTPUT_HANDLE),&attributes[0], attributes.size(), location, &dwWritten);
        WriteConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), pointer, attributes.size(), location, &dwWritten); 
    }
}
#define SCREENWIDTH 1550
#define SCREENHEIGHT 850
void SETWINDOWUP(DWORD &SIZE)
{
    CONSOLE_SCREEN_BUFFER_INFO info;
    MoveWindow(GetConsoleWindow(),0,0,SCREENWIDTH,SCREENHEIGHT,true);         //MOVE WINDOW TO 0,0 AND MAKE 1600 BY 880
   ::SetWindowPos(GetConsoleWindow(), HWND_TOPMOST, 0, 0, 0,0,     SWP_DRAWFRAME | SWP_NOREPOSITION | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); //SET WNDOWS POSITION COMPARED TO OTHER WINDOWS IN DRAW ORDER
::SetWindowPos(GetConsoleWindow(),HWND_NOTOPMOST, 0, 0, 0, 0, SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hout,&info);
COORD newBuffersize =
{
    info.srWindow.Right - info.srWindow.Left + 1,
    info.srWindow.Bottom - info.srWindow.Top + 1
};
SetConsoleScreenBufferSize(hout,newBuffersize);
SIZE = info.dwSize.X * info.dwSize.Y;
//EDIT REGULATED FONT SIZE
CONSOLE_FONT_INFOEX cfi;
std::wcscpy(cfi.FaceName, L"Lucida Console"); // Choose your font
cfi.FontFamily = FF_DONTCARE;
cfi.nFont = 0;
cfi.dwFontSize.X = 0;
cfi.dwFontSize.Y = 25;                  // Height
cfi.FontWeight = FW_BOLD;
cfi.cbSize = sizeof(cfi);
SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), false, &cfi);
}
int main()
{
Sleep(500);DWORD SIZE = 0;SETWINDOWUP(SIZE);
DWORD charswritten;COORD start = {0,0};TCHAR CHARACTER = 223;
    FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE),CHARACTER,SIZE,start,&charswritten);
Sleep(500);
printchar(223,{6,5},HOVEREDCOLOR);
Sleep(500);
return 0;
};
  • `setAttributesChar(color,attributes);//Pushes back the color` -- If this function is simple, why not just call `push_back()` directly? Note that a [mcve] is one requirement when asking such questions. – PaulMcKenzie Sep 09 '18 at 00:44
  • Because i was using a variable to hold the color of the character but it was used for SetConsoleTextColor(Integer) which uses different numbers than WriteConsoleOutputAttribute(Hexidecimal) i thought it was less work to work with what i made then change it. I will edit the post with a working executable that displays the issue. – Nathan Myerscough Sep 09 '18 at 01:19
  • I have created a working example you can compile. – Nathan Myerscough Sep 09 '18 at 02:16
  • Advice -- 1) You don't check if the vector is empty before using `attributes[0]`. 2) Use `vector::size()` to determine the number of characters, and refrain from using extraneous variables like `LENGTH`. A vector knows its own size already without introducing variables that may (or may not) contain the correct information. – PaulMcKenzie Sep 09 '18 at 02:25
  • Ok i have implemented that. A security thing and i suppose i initialize one less variable. But i still wonder why it has to draw an extra pixel thickness. – Nathan Myerscough Sep 09 '18 at 02:38
  • Please post screenshots highlighting the problem for the example code's output. I tried it using both the new and legacy consoles in Windows 10, and I don't see the issue. – Eryk Sun Sep 09 '18 at 21:23
  • OK i vastly increased the text size. and if you look closely you will see a black line on the right side of the green sqaure. – Nathan Myerscough Sep 09 '18 at 22:10
  • https://imgur.com/a/9p0SLEW. Interestingly if i increase the text height to 55 i dont get a black line but i dont want size 55. lol. – Nathan Myerscough Sep 09 '18 at 22:10
  • I also edited the program so that the font was regulated. – Nathan Myerscough Sep 09 '18 at 22:15
  • The character doesn't fill the entire cell, so you're seeing the background color, which is black. If you want the whole cell to be green (actually, whatever color is assigned to index 2 in the current background-color palette), write a `L" "` (space) character and use the attribute `BACKGROUND_GREEN`, or write anything with the attribute `FOREGROUND_GREEN | BACKGROUND_GREEN`. – Eryk Sun Sep 09 '18 at 23:30
  • Also, you're building an ANSI app that depends on the current console codepage. Codes 128-255 are not ASCII. They're codepage dependent, and code 223 will only be this block character in certain codepages, such as codepage 437. You should build a Unicode application using wide characters and wide-character strings. – Eryk Sun Sep 09 '18 at 23:32
  • Is building a Unicode application as simple as changing the codepage to the UNICODE one? and LUCIDA CONSOLE font. I havent figured out how to use the unicode yet. – Nathan Myerscough Sep 10 '18 at 00:44
  • But as for the codepage thing i can do a check like if(SetConsoleOutputCP(437) == 0) logit(1,"FAILURE TO SET CODE PAGE"); – Nathan Myerscough Sep 10 '18 at 00:44
  • The black background as you say is actually casting one line onto the next tile. So the character fills the position perfectly fine but it adds on a extra column of black pixels for idk why. This is an issue because when my player moved around with printchar he clipped things on the right of him by one pixel unless he moved right then he would cover it. – Nathan Myerscough Sep 10 '18 at 00:47
  • I attempted to switch it over to wchar_t but cant use writeconsoleoutputcharacter with it. – Nathan Myerscough Sep 10 '18 at 02:14
  • Unicode is configured for VC++ by defining `_UNICODE` and for the Windows API by defining `UNICODE`. As to the line, I extended the example to repeatedly overwrite two adjacent cells, one green and one blue. I do observe the boundary line shift left and right by a pixel, which looks like a bug in the console. Other than redrawing the entire line, all I can suggest is to look for a GUI library that's intended to render text-based games instead of using the built-in console. – Eryk Sun Sep 10 '18 at 04:25

0 Answers0