17

In C++ using Code::Blocks v10.05, how do I draw a single pixel on the console screen? Is this easy at all, or would it be easier to just draw a rectangle? How do I color it?

I'm sorry, but I just can't get any code from SOF, HF, or even cplusplus.com to work. This is for a Super Mario World figure on the screen. The game I think is 16-bit, and is for the SNES system. C::B says I need SDK for C::B. It says "afxwin.h" doesn't exist. Download maybe?

This is what I'm trying to make:

Image I'm trying to create

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
hCon
  • 207
  • 1
  • 7
  • 19
  • Can you link to the code that you couldn't get to work? – Borgleader Sep 11 '12 at 22:11
  • Wow this takes me back... People used to do this in DOS. You had to jump into memory where the character set was stored and alter it (common practice for just about everything in DOS, including writing bytes to the video card in other graphics modes), then draw your sprites using the modified characters. Obviously you were constrained to 256 possible subimages. I don't know if this is still what happens in Windows. Can't give an answer, sorry, except to say that the console window is just another window. I wonder if you can hook its WM_PAINT message. – paddy Sep 11 '12 at 22:12
  • http://stackoverflow.com/questions/4576019/c-drawing-pixels-question – hCon Sep 11 '12 at 22:13
  • 1
    or better show the code here not in a link (which will disappear) – mmmmmm Sep 11 '12 at 22:19
  • 13
    The whole point of a console is to not do graphics... – user541686 Sep 11 '12 at 22:20
  • 1
    FYI the console window is partially managed by CSRSS so it might not allow you to do it even if you try to hack around it by GetDC and the like. – user541686 Sep 11 '12 at 22:23

6 Answers6

26

It depends on your OS. I suppose you are programming in a Windows platform, therefore you can use SetPixel but you have to use "windows.h" to get a console handle, so here an example for drawing the cos() function:

#include<windows.h>
#include<iostream>
#include <cmath>

using namespace std;

#define PI 3.14

int main() 
{
    //Get a console handle
    HWND myconsole = GetConsoleWindow();
    //Get a handle to device context
    HDC mydc = GetDC(myconsole);

    int pixel =0;

    //Choose any color
    COLORREF COLOR= RGB(255,255,255); 

    //Draw pixels
    for(double i = 0; i < PI * 4; i += 0.05)
    {
        SetPixel(mydc,pixel,(int)(50+25*cos(i)),COLOR);
        pixel+=1;
    }

    ReleaseDC(myconsole, mydc);
    cin.ignore();
    return 0;
}

You can also use some others libraries like: conio.h allegro.h sdl, etc.

FacundoGFlores
  • 7,858
  • 12
  • 64
  • 94
  • 1
    Gross :D But +1 for a "solution". Note that you will not be handling `WM_PAINT` so if the region becomes invalid, it will be erased. Normal windows strongly favored over this. – tenfour Sep 11 '12 at 22:44
  • Code::Blocks Error: 'GetConsoleWindow' was not declared in this solution. – hCon Sep 12 '12 at 00:23
  • 1
    @Mike have you included "windows.h" header? Remember you have to get it from microsoft. You must download microsoft sdk: http://www.microsoft.com/en-us/download/details.aspx?id=3138 – FacundoGFlores Sep 12 '12 at 01:43
  • So I have to use the one from microsoft, or can I use the one that came with code::blocks? – hCon Sep 12 '12 at 11:42
  • 2
    Sorry? If you refer to the SDK, yes you have to use microsoft. And the other hand, I said you can use anothers libraries like: conio.h allegro.h sdl, etc. In linux, you can use ncurses or http://www.svgalib.org/... – FacundoGFlores Sep 12 '12 at 12:41
20

If you're willing to have the image look blocky, you could take advantage of the block characters from the console code page.

  • = '\xDB' = U+2588 FULL BLOCK
  • = '\xDC' = U+2584 LOWER HALF BLOCK
  • = '\xDF' = U+2580 UPPER HALF BLOCK
  • and space

By using the half-blocks in combination with colored text, you can turn an 80×25 console window into an 80×50 16-color display. (This was the approach used by the QBasic version of Nibbles.)

Then, you just need to convert your image to the 16-color palette and a reasonably small size.

Mario in 8 lines and 10 columns of "text"

Community
  • 1
  • 1
dan04
  • 87,747
  • 23
  • 163
  • 198
  • 3
    I used this technique to make an 80x50 16 colour display on the Commodore 64 as a science fair project when I was in high school. I added new commands to BASIC for plotting pixels and lines. Good times. :-) – yoyo Apr 17 '20 at 21:01
2

windows.h provides a function SetPixel() to print a pixel at specified location of a window. The general form of the function is

SetPixel(HDC hdc, int x, int y, COLORREF& color);

where, x and y are coordinates of pixel to be display and color is the color of pixel.

Important: to print the pixel in your machine with Code::blocks IDE, add a link library libgdi32.a (it is usually inside MinGW\lib ) in linker setting.

1

Console is a text device, so in general you don't write to individual pixels. You can create a special font and select it as a font for console, but it will be monochromatic. There are libraries which simplify writing console UI (e.g. Curses), but I believe that you also have more gamelike functionality in mind besides just showing a sprite.

if you want to write a game, I suggest taking a look at some of the graphics/game frameworks/libs, e.g. SDL

Zdeslav Vojkovic
  • 14,391
  • 32
  • 45
  • So should I display a sprite/image in the window? If so, how do I do it? – hCon Sep 11 '12 at 22:31
  • Do you need to do it e.g. for school, so it is important to do all the pixel modifying code yourself, or are you more interested in the results? if former, what environment do you use (Win, Linux, etc - I guess Windows, base on afxwin.h)? if latter, here's a tutorial: http://www.libsdl.org/intro.en/usingvideo.html – Zdeslav Vojkovic Sep 11 '12 at 22:35
1

I have drawn the straight line using windows.h in code::blocks. I can't explain it in details, but I can provide you a code and procedure to compile it in code::blocks.

  1. go to setting menu and select compiler and debugger.
  2. Click on linker tab and add a link library libgdi32.a which is at C:\Program Files\CodeBlocks\MinGW\lib directory.

Now compile this program

#include <windows.h>

#include <cmath>

#define ROUND(a) ((int) (a + 0.5))

/* set window handle */

static HWND sHwnd;

static COLORREF redColor=RGB(255,0,0);

static COLORREF blueColor=RGB(0,0,255);

static COLORREF greenColor=RGB(0,255,0);


void SetWindowHandle(HWND hwnd){

sHwnd=hwnd;

}

/* SetPixel */

void setPixel(int x,int y,COLORREF& color=redColor){

if(sHwnd==NULL){

    MessageBox(NULL,"sHwnd was not initialized !","Error",MB_OK|MB_ICONERROR);

    exit(0);

}

HDC hdc=GetDC(sHwnd);

SetPixel(hdc,x,y,color);

ReleaseDC(sHwnd,hdc);

return;

// NEVERREACH //

}


void drawLineDDA(int xa, int ya, int xb, int yb){

   int dx = xb - xa, dy = yb - ya, steps, k;

   float xIncrement, yIncrement, x = xa, y = ya;

   if(abs(dx) > abs(dy)) steps = abs(dx);

   else steps = abs(dy);

   xIncrement = dx / (float) steps;

   yIncrement = dy / (float) steps;

   setPixel(ROUND(x), ROUND(y));

   for(int k = 0; k < steps; k++){

    x += xIncrement;

    y += yIncrement;

    setPixel(x, y);

 }

}

/* Window Procedure WndProc */

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){

 switch(message){

    case WM_PAINT:

        SetWindowHandle(hwnd);

        drawLineDDA(10, 20, 250, 300);

        break;

    case WM_CLOSE: // FAIL THROUGH to call DefWindowProc

        break;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    default:

    break; // FAIL to call DefWindowProc //

  }

 return DefWindowProc(hwnd,message,wParam,lParam);

}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int      iCmdShow){

static TCHAR szAppName[] = TEXT("Straight Line");

WNDCLASS wndclass;

wndclass.style         = CS_HREDRAW|CS_VREDRAW ;

wndclass.lpfnWndProc   = WndProc ;

wndclass.cbClsExtra    = 0 ;

wndclass.cbWndExtra    = 0 ;

wndclass.hInstance     = hInstance ;

wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;

wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;

wndclass.lpszMenuName  = NULL ;

wndclass.lpszClassName = szAppName ;

// Register the window //

if(!RegisterClass(&wndclass)){

    MessageBox(NULL,"Registering the class failled","Error",MB_OK|MB_ICONERROR);

    exit(0);

}

// CreateWindow //

HWND hwnd=CreateWindow(szAppName,"DDA - Programming Techniques",

            WS_OVERLAPPEDWINDOW,

             CW_USEDEFAULT,

             CW_USEDEFAULT,

             CW_USEDEFAULT,

             CW_USEDEFAULT,

             NULL,

             NULL,

             hInstance,

             NULL);

if(!hwnd){

    MessageBox(NULL,"Window Creation Failed!","Error",MB_OK);

    exit(0);

  }

  // ShowWindow and UpdateWindow //

  ShowWindow(hwnd,iCmdShow);

 UpdateWindow(hwnd);

 // Message Loop //

 MSG msg;

 while(GetMessage(&msg,NULL,0,0)){

    TranslateMessage(&msg);

    DispatchMessage(&msg);

 }

  /* return no error to the operating system */

  return 0;

}

In this program I have used DDA line drawing algorithm. Pixel drawing tasks is done by setPixel(ROUND(x), ROUND(y)) function. This is windows programing which you can learn details here

Dinesh Subedi
  • 2,603
  • 1
  • 26
  • 36
1

To use in CodeBlocks I found this (you have to add a linker option -lgdi32):

//Code Blocks: Project Build Options Linker settings Othoer linker options: add -lgdi32

I forgot: You have to put this before including windows.h:

#define _WIN32_WINNT 0x0500

The whole cosine code again. Ready to compile:

//Code Blocks: Project Build Options Linker settings Othoer linker options: add -lgdi32
#define _WIN32_WINNT 0x0500
#include "windows.h"
#include <iostream>
#include <cmath>
using namespace std;

#define PI 3.14

int main(){
    HWND myconsole = GetConsoleWindow();
    HDC mydc = GetDC(myconsole);
    int pixel =0;
    COLORREF COLOR= RGB(255,255,255);

    //Draw pixels
    for(double i = 0; i < PI * 4; i += 0.05)
    {
        SetPixel(mydc,pixel,(int)(50+25*cos(i)),COLOR);
        pixel+=1;
    }

    ReleaseDC(myconsole, mydc);
    cin.ignore();
    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770