图像不会画到屏幕C++
我正在学习一个教程。我正在尝试在屏幕上绘制一个.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 ==========
的代码不工作,你只是忘记把你的c.bmp
放在正确的位置。如果你正在从资源管理器启动程序,或者如果你正在从Visual Studio中启动程序,则将它放到项目输出文件夹(即bin/Debug)中。
k,我会试试看。谢谢 – numerical25 2010-02-22 21:31:55
它工作。我不确定图像相对于应用程序运行的位置。但它是有意义的,将运行相对于.exe文件。谢谢 – numerical25 2010-02-22 21:34:35
我无法计算出当天我写了几个小时的游戏,直到我意识到这一点......每一次,我都会挠挠头脑。 – rmeador 2010-02-22 22:06:01
对于“工作”的充分宽松的定义,您的代码似乎工作。除非你试图修改代码(相当多),否则我的建议是找到一个不同的教程来遵循 - 至少对我来说,现在大部分的东西都是不起眼的。
刚例如,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
,并将其保存在中间。由于您在此期间使用的是相同的位图,因此只需加载一次,然后从中显示出来。
是的,我注意到Draw_Bitmap()中的ignore参数。以及。我纠正了它。我正在为这本书寻找勘误。这本书是“开始游戏编程”第三版。亚瑟也表示,这种格式将是他将在书中使用的最后一种格式,并且他承认这不是绘制对象的正确方法。他展示了如果你不使用直接的x sdk,你将不得不渲染对象。这本书刚刚开始就是为了让事情顺利进行。我会再给它一个机会一段时间。 – numerical25 2010-02-23 00:13:19
@numer25:即使没有使用DirectX,这也不是真正(至少是IMO)的“正确”方式来绘制任何东西。 – 2010-02-23 02:24:43
您需要检查Win32函数调用的结果。其中任何一个都可能失败,没有人会知道。 – GManNickG 2010-02-22 21:24:52
只是好奇,你如何跟踪C++?也许这可能帮助我弄清楚这些功能是否失败。原因会不会停止,如果它? – numerical25 2010-02-22 21:29:51
不,函数如果失败就不会停止,它只是返回一个错误指示,并且您可以获取错误代码。有关详细信息,请查看每个Windows呼叫的文档。 Visual Studio将逐步执行一个程序,或者如果您想检查一个点,则停止在一行中。 – 2010-02-22 21:36:40