2010-02-22 67 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