C++ Pixels In Console Window
Asked Answered
S

6

18

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

Selfreliance answered 11/9, 2012 at 22:7 Comment(6)
Can you link to the code that you couldn't get to work?Upi
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.Shuler
https://mcmap.net/q/669086/-c-drawing-pixels-questionSelfreliance
or better show the code here not in a link (which will disappear)Flub
The whole point of a console is to not do graphics...Propagable
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.Propagable
V
27

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.

Vigorous answered 11/9, 2012 at 22:40 Comment(5)
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.Dilution
Code::Blocks Error: 'GetConsoleWindow' was not declared in this solution.Selfreliance
@Mike have you included "windows.h" header? Remember you have to get it from microsoft. You must download microsoft sdk: microsoft.com/en-us/download/details.aspx?id=3138Vigorous
So I have to use the one from microsoft, or can I use the one that came with code::blocks?Selfreliance
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 svgalib.org...Vigorous
G
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"

Garin answered 12/9, 2012 at 3:14 Comment(1)
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. :-)Batty
S
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.

Sigvard answered 21/9, 2012 at 1:9 Comment(0)
M
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

Monopode answered 11/9, 2012 at 22:28 Comment(2)
So should I display a sprite/image in the window? If so, how do I do it?Selfreliance
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: libsdl.org/intro.en/usingvideo.htmlMonopode
C
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

Cyzicus answered 12/9, 2012 at 15:9 Comment(0)
L
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;
}
Leshia answered 9/12, 2016 at 11:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.