///////////////////2016-5-4/////////////////////////
一.游戏名称:打砖块
二.游戏内容描述:任意数量砖块放置在画面顶部,画面底部为一定长度和厚度的条状物,条状物可玩家控制,玩家需要用条状物作为屏幕中一随机小球的降落反弹媒介,确保能使小球再次反弹,并能击中顶部砖块,小球击中砖块,玩家分数对应增加,当玩家击中最后一个砖块后(或小球掉落),视为游戏结束
三.功能与设计:
1.双缓冲页面切换
2.接受键盘输入
3.位图加载(随机位置)与碰撞点设计
4.定时器控制小球运动(?)
今日待解决:{位图加载}:载入原图片,生成随机数组,规定范围随机显示
//////////////////2016-5-8//////////////////////////
[这几天全去玩守望先锋了,根本停不下来,废话少说,我今天终于正常了]
ps:我一直在学习的教程是《win32游戏编程大师 第二版》这是一本比较老的书,但是入门不错,2013年的第二版。算是比较新,主要是代码详解非常好,但是错误不少,其实也蛮好可,可以认真的研究哪里出错,理解程序的逻辑
一.已解决的问题
1.学完加载位图后,我自己画了砖块的位图(毕竟这是一个打砖块游戏。。。),24位的位图加载,然后就出错了,我直接用的书里的源码(作者自己写的位图加载函数,我感觉比loadimage清晰,而且自己写的阅读器容易修改);然后就是各种调bug,各种百度,然后发现有人说书里作者的这段代码只能加载640*480的位图,然后我就把自己画的位图改成了640*480,再一调试,奇迹发生了!!位图被加载了出来!然后本菜鸟就开始解决这个问题,这是为什么咧?然后我再一次仔细的看了代码,特别是有640和480字样的部分(忘记说了,在头文件里define了SCREEN_HEIGHT 480 ;SCREEN_WEIGHT 640),然后我看到了下面这段代码的注释,很明显,这里的缓冲大小是和SCREEN_WEIGHT&SCREEN_HEIGHT有关的,所以就出错在这里,这里的缓冲大小应该是位图的大小才对
// process each line and copy it into the primary buffer
for (int index_y = 0; index_y < SCREEN_HEIGHT; index_y++)
{
for (int index_x = 0; index_x <SCREEN_WIDTH; index_x++)
{
// get BGR values
UCHAR blue = (bitmap.buffer[index_y*SCREEN_WIDTH * 3 + index_x * 3 + 0]),
green = (bitmap.buffer[index_y*SCREEN_WIDTH * 3 + index_x * 3 + 1]),
red = (bitmap.buffer[index_y*SCREEN_WIDTH * 3 + index_x * 3 + 2]);
// this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode)
DWORD pixel = _RGB32BIT(0, red, green, blue);
// write the pixel
primary_buffer[index_x + (index_y*ddsd.lPitch >> 2)] = pixel;
} // end for index_x
【闲话】:为什么作者的图片是640*480呢?首先作者用的是640*480的模式,然后作者做了一个小人走路的实例,这涉及到动画帧,然而作者用了单元模板,就是说一张位图上有动画的每一帧(下图),然后生成裁剪序列,blt到每个离屏表面,很明显,打砖块这个游戏没有形态的事物(砖块只需要显示和消失,挡板需要左右移动,小球是物理碰撞运动),所以并不需要那么大的缓冲,个人觉得缓冲大小和位图图片一样就行
待解决:{位图加载}:砖块位图的放置和消失&挡板位图的叠加和移动
//////////////////2016-5-10//////////////////////////
还说每日更......结果是,只要关掉vs就再也不想打开了(所以换个名字:勤快就更!!!机智如我!!)
今日总结:今天主要看了loadimage()和bitblt(),就开发效率来说,确实使用API快一点,找个实例,然后看懂每个参数就ok了,话说今天用某度的时候,还看到loadbitmap(),然而这个函数基本被loadimage取代了,而且个人觉得loadbirmap的资源不容易识别,我就不明白了,明明是.bmp,为什么就加不进.rc里,所以我的loadbitmap尝试失败,但是我感觉如果用MFC应该能成功(大家可以试试)。下面介绍一下loadimage()和bitblt()的用法,我就直接贴代码了,说起来忏愧,代码还是我在网上扒的......(不完整代码,vs2013标准win32框架,只是添了几行代码)【顺便吐槽一下,vc++和vs的win32框架,差别还是有点大啊,vc++都集合在一起了,容易改一点,vs分得比较细,虽然方便,看似更容易改,但是大部分教材的IDE都用的是vc啊!!所以说,其实能把vc++的案例弄到vs上跑通还是可以得,不要打我!我毕竟是个软绵绵的菜鸟=_=】【好烦,这个代码插件不好用】
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HBITMAP hBitmap;
BITMAP bitmap;
static int cxClient, cyClient, cxSource, cySource;
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc,hdcMem;
HINSTANCE hInstance;//很明显,要拿到位图实例句柄
switch (message)
{
case WM_CREATE:
hInstance = ((LPCREATESTRUCT)lParam)->hInstance;//WM_CREATE消息的lParam参数是一个CREATESTRUCT结构的指针,包含hInstance.(重载)【这段话是我百度的。。。】
hBitmap = (HBITMAP)LoadImage(NULL, "brick.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);//重头戏LoadImage();参数的意思自己某度
GetObject(hBitmap, sizeof(BITMAP), &bitmap);//这时候要拿到图像的信息,要不然怎么bitblt
cxSource = bitmap.bmWidth;//图片的尺寸
cySource = bitmap.bmHeight;
return 0;
case WM_SIZE:
cxClient = LOWORD(lParam); cyClient = HIWORD(lParam);//窗口的尺寸(这段代码中我没有用,感觉可以用作自适应
return 0;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
hdcMem = CreateCompatibleDC(hdc);//先来个环境
SelectObject(hdcMem, hBitmap);//把hbitmap弄到环境里
BitBlt(hdc,0, 0, cxSource, cySource, hdcMem, 0, 0, SRCCOPY);//bitblt时间到
DeleteDC(hdcMem);//这个不能忘
EndPaint(hWnd, &ps);
return 0;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}