2010-02-22 68 views
0

我正在學習一個教程。我正在嘗試在屏幕上繪製一個.bmp文件。它建立沒有錯誤,但沒有圖像出現。根據這本書,我應該看到隨機出現的圖像。以下是我的代碼。作者不推薦這種繪製對象的技巧,他只是爲了演示而做的。如果你想知道。圖像不會畫到屏幕C++

圖像是一個25x25的方形紅色正方形。

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

using namespace std; 

const string APPTITLE = "Game Loop"; 
HWND window; 
HDC device; 
bool gameover = false; 


void DrawBitmap(char *filename, int x, int y) 
{ 
//load the bitmap image 
HBITMAP image = (HBITMAP)LoadImage(0,"c.bmp", IMAGE_BITMAP,0,0, LR_LOADFROMFILE); 

BITMAP bm; 
GetObject(image, sizeof(BITMAP), &bm); 

HDC hdcImage = CreateCompatibleDC(device); 
SelectObject(hdcImage,image); 

BitBlt(
    device, 
    x,y, 
    bm.bmWidth, bm.bmHeight, 
    hdcImage, 
    0,0, 
    SRCCOPY); 

//deletec the device context and bitmap 
DeleteDC(hdcImage); 
DeleteObject((HBITMAP)image); 
} 

bool Game_Init() 
{ 
srand(time(NULL)); 
return 1; 
} 

void Game_Run() 
{ 
if(gameover == true) return; 

RECT rect; 
GetClientRect(window, &rect); 

//draw bitmap at random location 
int x = rand() % (rect.right - rect.left); 
int y = rand() % (rect.bottom - rect.top); 

DrawBitmap("c.bmp",x,y); 
} 

void Game_End() 
{ 
//free the device 
ReleaseDC(window,device); 
} 

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); 
} 

ATOM MyRegisterClass(HINSTANCE hInstance) 
{ 
//set the new windows properties 

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(BLACK_BRUSH); 
wc.lpszMenuName = NULL; 
wc.lpszClassName= APPTITLE.c_str(); 
wc.hIconSm = NULL; 

return RegisterClassEx(&wc); 
} 

bool InitInstance(HINSTANCE hInstance, int nCmdShow) 
{ 
//create a new window 
window = CreateWindow(
    APPTITLE.c_str(), 
    APPTITLE.c_str(), 
    WS_OVERLAPPEDWINDOW, 
    CW_USEDEFAULT, CW_USEDEFAULT, 
    640,480, 
    NULL, 
    NULL, 
    hInstance, 
    NULL); 

//was there an error creating the window ? 
if(window == 0) return 0; 

//display the window 
ShowWindow(window, nCmdShow); 
UpdateWindow(window); 
device = GetDC(window); 

return 1; 
} 

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

//register the class 
MyRegisterClass(hInstance); 

//initialize application 
if(!InitInstance(hInstance, nCmdShow)) return 0; 

//initilize the game 
if(!Game_Init()) return 0; 

//main message loop 
while(!gameover) 
{ 
    if(PeekMessage(&msg,NULL, 0, 0,PM_REMOVE)) 
    { 
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
    } 
    Game_Run(); 
} 

Game_End(); 

return msg.wParam; 
} 

我不確定是否因爲我在錯誤的位置有圖像。但如果是這樣的話。我想它會拋出一個錯誤。我將圖像放置在源文件夾的根目錄下。

[編輯]

此外,當我重建,我得到這可能是原因的警告,但這裏是警告

1>------ Rebuild All started: Project: Begin, Configuration: Debug Win32 ------ 
1>Deleting intermediate and output files for project 'Begin', configuration 'Debug|Win32' 
1>Compiling... 
1>main.cpp 
1>c:\users\numerical25\documents\visual studio 2008\projects\begin\begin\main.cpp(39) : warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data 
1>Compiling manifest to resources... 
1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1 
1>Copyright (C) Microsoft Corporation. All rights reserved. 
1>Linking... 
1>LINK : C:\Users\numerical25\Documents\Visual Studio 2008\Projects\Begin\Debug\Begin.exe not found or not built by the last incremental link; performing full link 
1>Embedding manifest... 
1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1 
1>Copyright (C) Microsoft Corporation. All rights reserved. 
1>Build log was saved at "file://c:\Users\numerical25\Documents\Visual Studio 2008\Projects\Begin\Begin\Debug\BuildLog.htm" 
1>Begin - 0 error(s), 1 warning(s) 
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ========== 

alt text

+1

您需要檢查Win32函數調用的結果。其中任何一個都可能失敗,沒有人會知道。 – GManNickG 2010-02-22 21:24:52

+0

只是好奇,你如何跟蹤C++?也許這可能幫助我弄清楚這些功能是否失敗。原因會不會停止,如果它? – numerical25 2010-02-22 21:29:51

+0

不,函數如果失敗就不會停止,它只是返回一個錯誤指示,並且您可以獲取錯誤代碼。有關詳細信息,請查看每個Windows呼叫的文檔。 Visual Studio將逐步執行一個程序,或者如果您想檢查一個點,則停止在一行中。 – 2010-02-22 21:36:40

回答

5

的代碼不工作,你只是忘記把你的c.bmp放在正確的位置。如果你正在從資源管理器啓動程序,或者如果你正在從Visual Studio中啓動程序,則將它放到項目輸出文件夾(即bin/Debug)中。

+0

k,我會試試看。謝謝 – numerical25 2010-02-22 21:31:55

+0

它工作。我不確定圖像相對於應用程序運行的位置。但它是有意義的,將運行相對於.exe文件。謝謝 – numerical25 2010-02-22 21:34:35

+0

我無法計算出當天我寫了幾個小時的遊戲,直到我意識到這一點......每一次,我都會撓撓頭腦。 – rmeador 2010-02-22 22:06:01

0

對於「工作」的充分寬鬆的定義,您的代碼似乎工作。除非你試圖修改代碼(相當多),否則我的建議是找到一個不同的教程來遵循 - 至少對我來說,現在大部分的東西都是不起眼的。

剛例如,Game_Run()通過位圖文件作爲參數傳遞給Draw_Bitmap()的名字,但參數被忽略,Draw_Bitmap()使用硬編碼的文件名來代替。

PeekMessage()循環使程序看起來像它是在25年前,在16位Windows的時代(並且可以說是不那麼偉大)。在新代碼中很少(如果有的話)有充分的理由使用PeekMessage(),並且使用它的代碼很可能會因爲大修而逾期。主循環通常使用GetMessage(),您可以(例如)使用SetTimer(持續時間爲0)來計算繪製位圖的新座標,然後調用InvalidateRect()來繪製它。有一段時間,有一個公平的觀點認爲,額外的消息會導致額外的開銷,但在現代化的機器上,它會跟上顯示器刷新率,而使用CPU的10%或更少。然而,爲了保持CPU使用率降低,你需要重新構造一些代碼 - 現在,每次繪製圖形時,都會獲得窗口矩形,從磁盤重新加載BMP,將BMP選擇爲兼容DC,最後用BitBlt將圖像顯示到屏幕上。這是代碼的一部分,優化將有所作爲 - 強烈的偏好,你想它只需致電BitBlt並做好。剩下的代碼應該移到其他地方,所以只有在需要時纔會發生。例如,您可以檢索窗口矩形以響應WM_SIZE,並將其保存在中間。由於您在此期間使用的是相同的位圖,因此只需加載一次,然後從中顯示出來。

+0

是的,我注意到Draw_Bitmap()中的ignore參數。以及。我糾正了它。我正在爲這本書尋找勘誤。這本書是「開始遊戲編程」第三版。亞瑟也表示,這種格式將是他將在書中使用的最後一種格式,並且他承認這不是繪製對象的正確方法。他展示瞭如果你不使用直接的x sdk,你將不得不渲染對象。這本書剛剛開始就是爲了讓事情順利進行。我會再給它一個機會一段時間。 – numerical25 2010-02-23 00:13:19

+0

@numer25:即使沒有使用DirectX,這也不是真正(至少是IMO)的「正確」方式來繪製任何東西。 – 2010-02-23 02:24:43