2016-06-13 5 views
0

그래서 저는 C + +로 여러 책 및 웹 자습서를 사용하여 얼마 동안 놀았습니다.SetPixel 및 다중 픽셀 C++ winapi

이제 그래픽을 보았습니다. 현재 WinApi에 있습니다.

텍스트, 이미지 또는 픽셀을 칠하는 창이 있습니다.

그러나 SetPixels를 사용하여 많은 픽셀을 페인팅하는 것은 단순히 느려지는 것입니다. 내 코드에서

발췌문 :

void DrawBitmap(RECT rect, string text) { 


    HDC buffer = CreateCompatibleDC(device); 
    HBITMAP BGimage = CreateCompatibleBitmap(device, rect.right - rect.left, rect.bottom - rect.top); 
    SelectObject(buffer, BGimage); 

    //Clearing the screen with a full rect 
    Rectangle(buffer, rect.left, rect.top, rect.right, rect.bottom); 


    //Sample on making a single pixel at mouseclik, with color 250 on screen. 

    SetPixelV(buffer, x, y, 250); 


    int PixelSize = 4; 



    //SOME HEAVY PIXELS to slow the FPS 
    /* 
    for (int i = 0; i < 255; i++) { 
     for (int k = 0; k < 255; k++) { 
      SetPixelV(buffer, x + i, y + k, COLORREF RGB(150, i, k)); 
     } 
    } 
    */ 



    //Sample on making some text. 
    RECT drawRect; 
    drawRect = { rect.left + 5, rect.top + 5, rect.left + 105, rect.top + 25 }; 
    DrawText(buffer, text.c_str(), text.length(), &drawRect, DT_LEFT); 


    // counter number to be converted to a string 
    int timeint = GetTickCount(); 
    ostringstream convert; // stream used for the conversion 
    convert << "TIME: " << timeint;  // insert the textual representation of 'Number' in the characters in the stream 
    text = convert.str(); 
    drawRect = { rect.left + 5, rect.top + 25, rect.left + 680, rect.top + 45 }; 
    DrawText(buffer, text.c_str(), text.length(), &drawRect, DT_LEFT); 

    ostringstream convert2; // stream used for the conversion 
    convert2 << "FPS: " << FPS_calc;  // insert the textual representation of 'Number' in the characters in the stream 
    text = convert2.str(); 
    drawRect = { rect.left + 5, rect.top + 45, rect.left + 680, rect.top + 65 }; 
    DrawText(buffer, text.c_str(), text.length(), &drawRect, DT_LEFT); 


    //do the dubble buffering 
    BitBlt(device, 0, 0, rect.right - rect.left, rect.bottom - rect.top, buffer, 0, 0, SRCCOPY); 

    DeleteDC(buffer); 
    DeleteObject((HBITMAP)BGimage); 
} 

지금,이 잘 작동하지만 (현재 오프 주석)을 // 일부 HEAVY 픽셀 이 속도를 많이 차지합니다. 그때 나는 당신이 이미지를 잠그고 물기를 조작 할 수 있다고 들었다.

나는 그저 내 머리를 감당할 수 없습니까? 모든 고비용의 전화 기능을 피하면서 개별 픽셀로 x, y에서 100x100 필드를 채우고 싶습니다 (표본의 경우).

나는 [동일의 https://msdn.microsoft.com/en-us/library/5ey6h79d(v=vs.110).aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-2]

그리고 많은 다른 버전을 시도했습니다. 하지만 난 일할 수없는 것 같아요.

아무도 아이디어가 있습니까?

내 전체 작업 코드는 여기에 있습니다 :

#include<Windows.h> 
#include<iostream> 
#include<time.h> 
#include<string> 


#include <sstream> 

using namespace std; 

const string APPTITLE = "GAME LOOP"; 
const string APPNAME = "GAME LOOP"; 
HWND window; 
HDC device; 

bool gameover = false; 
POINT p; 
int x = 200; 
int y = 200; 
int startTime; 
int currentTime; 
int lastTime; 
int FPS_calc = 0; 


// FORWARD DECLARATIONS 
void DrawBitmap(RECT rect, string text); 
bool Game_Init(); 
void Game_Run(); 
void Game_End(); 
ATOM MyRegisterClass(HINSTANCE hInstance); 
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow); 
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); 
string ArrowKey(); 
void MouseDet(POINT &mp); 



int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { 
    MSG msg; 
    MyRegisterClass(hInstance); 

    if (InitInstance(hInstance, nCmdShow) != 1) return GetLastError(); 

    if (!Game_Init()) return 0; 
    while (!gameover) { 
     if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 
     Game_Run(); 
    } 
    Game_End(); 

    return msg.wParam; 
} 

//////////Functions////////////// 


// Main game function 
void Game_Run() { 
    if (gameover == true) return; 

    RECT rect; 
    GetClientRect(window, &rect); 


    //ARROW KEY DETECTOR 
    string text = ArrowKey(); 
    //MouseDetector sets point if Left mouse key is pressed/held 
    MouseDet(p); 
    currentTime = GetTickCount(); 
    FPS_calc = int(1000/(currentTime-lastTime)); 
    if (lastTime != currentTime) lastTime = currentTime-1; 
    else lastTime = currentTime-30; 
    DrawBitmap(rect, text); 

} 


//Draw function with dubble buffering 
void DrawBitmap(RECT rect, string text) { 


    HDC buffer = CreateCompatibleDC(device); 
    HBITMAP BGimage = CreateCompatibleBitmap(device, rect.right - rect.left, rect.bottom - rect.top); 
    SelectObject(buffer, BGimage); 

    //Clearing the screen with a full rect 
    Rectangle(buffer, rect.left, rect.top, rect.right, rect.bottom); 


    //Sample on making a single pixel at mouseclik, with color 250 on screen. 

    SetPixelV(buffer, x, y, 250); 


    int PixelSize = 4; 



    //SOME HEAVY PIXELS to slow the FPS 
    /* 
    for (int i = 0; i < 255; i++) { 
     for (int k = 0; k < 255; k++) { 
      SetPixelV(buffer, x + i, y + k, COLORREF RGB(150, i, k)); 
     } 
    } 
    */ 



    //Sample on making some text. 
    RECT drawRect; 
    drawRect = { rect.left + 5, rect.top + 5, rect.left + 105, rect.top + 25 }; 
    DrawText(buffer, text.c_str(), text.length(), &drawRect, DT_LEFT); 


    // counter number to be converted to a string 
    int timeint = GetTickCount(); 
    ostringstream convert; // stream used for the conversion 
    convert << "TIME: " << timeint;  // insert the textual representation of 'Number' in the characters in the stream 
    text = convert.str(); 
    drawRect = { rect.left + 5, rect.top + 25, rect.left + 680, rect.top + 45 }; 
    DrawText(buffer, text.c_str(), text.length(), &drawRect, DT_LEFT); 

    ostringstream convert2; // stream used for the conversion 
    convert2 << "FPS: " << FPS_calc;  // insert the textual representation of 'Number' in the characters in the stream 
    text = convert2.str(); 
    drawRect = { rect.left + 5, rect.top + 45, rect.left + 680, rect.top + 65 }; 
    DrawText(buffer, text.c_str(), text.length(), &drawRect, DT_LEFT); 


    //do the dubble buffering 
    BitBlt(device, 0, 0, rect.right - rect.left, rect.bottom - rect.top, buffer, 0, 0, SRCCOPY); 

    DeleteDC(buffer); 
    DeleteObject((HBITMAP)BGimage); 
} 



//initialize value 
bool Game_Init() { 
    //get a random engine 
    srand(time(NULL)); 
    //getStartTime 
    startTime = GetTickCount(); 
    currentTime = startTime; 
    lastTime = currentTime - 1; 
    FPS_calc = int(1000/(lastTime - currentTime)); 
    return 1; 
} 


//End the game, release the window 
void Game_End() { 
    ReleaseDC(window, device); 
} 

//A window "setup" 
ATOM MyRegisterClass(HINSTANCE hInstance) { 
    WNDCLASSEX wc; 
    wc.cbSize = sizeof(WNDCLASSEX); 
    wc.style = CS_HREDRAW | CS_VREDRAW; 
    wc.lpfnWndProc = (WNDPROC)WinProc; 
    wc.cbClsExtra = 0; 
    wc.cbWndExtra = 0; 
    wc.hInstance = hInstance; 
    wc.hIcon = NULL; 
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 
    wc.lpszMenuName = NULL; 
    wc.lpszClassName = APPTITLE.c_str(); 
    wc.hIconSm = NULL; 
    return RegisterClassEx(&wc); 
} 



//Creates our visible window 
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { 
    window = CreateWindow(APPTITLE.c_str(), APPTITLE.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL); 

    if (window == 0) return 0; 

    ShowWindow(window, nCmdShow); 
    UpdateWindow(window); 

    device = GetDC(window); 
    return 1; 
} 


LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { 
    switch (message) { 
    case WM_DESTROY: 
     gameover = true; 
     PostQuitMessage(0); 
     break; 
    } 
    return DefWindowProc(hWnd, message, wParam, lParam); 
} 


//Test if arrow keys have been typed, return text wit hwich one 
string ArrowKey() { 
    string text = "NONE"; 
    if ((1 << 16) & GetAsyncKeyState(VK_UP)) 
    { 
     text = "UP"; 
     y--; 
    } 
    if ((1 << 16) & GetAsyncKeyState(VK_DOWN)) 
    { 
     text = "DOWN"; 
     y++; 
    } 
    if ((1 << 16) & GetAsyncKeyState(VK_RIGHT)) 
    { 
     text = "RIGTH"; 
     x++; 
    } 
    if ((1 << 16) & GetAsyncKeyState(VK_LEFT)) 
    { 
     text = "LEFT"; 
     x--; 
    } 
    return text; 
} 


void MouseDet(POINT &mp) { 
    if ((1 << 16) & GetAsyncKeyState(VK_LBUTTON)) { 

     GetCursorPos(&mp); 
     if (ScreenToClient(window, &mp)) {} 
     x = p.x; 
     y = p.y; 
    } 
} 
+0

'SetDIBits'와'GetDIBits'는 픽셀 단위로 여러 API를 호출하는 대신 Bitmap에서 픽셀 데이터를 수정하여 메모리 덩어리로 읽을 수있게합니다. 이것은 아마도 당신이 찾고있는 것입니다 (GDI를 넘어서서 기꺼이 움직이게하지 않는 한). https://msdn.microsoft.com/en-us/library/windows/desktop/dd162973(v=vs.85).aspx –

+0

고마워, 그것을 시도했지만 도움이되지 않는 것 같습니다. – JavaApprentis

답변

0

그냥 사각형을 그릴을 찾고 있다면이/평방 다음이 작업을 수행 할 FillRect를 사용할 수 있습니다.

+0

알아,하지만 안돼. 많은 픽셀을 개별적으로 조작하고 싶습니다 (SetPixels()) 이 예제에서는 100 x 100 상자를 사용하여 10.000 픽셀의 위치를 ​​쉽게 프로그래밍 할 수 있습니다. 나중에 사용하면 독립형 셀이됩니다. 이동할 수있는 픽셀 하지만 먼저 setPixel보다 빠르게 그래픽을 조작해야한다는 것을 알아야합니다. – JavaApprentis

+0

@JavaApprentis - 정교하게 다루십시오 ..? – Sean