放一个菜鸟级的程序出来:

做一个简单的弹球窗口,碰到窗口边缘就会弹回。

该程序的球不会粘边缘,可以任意改变窗口,可以最小化都不会出问题。

效果图如下:

算法:

1 取得窗口大小,以作为判断是否到边缘了

2 判断球的位置是否到了边缘,如果到了边缘,速度方向就为反方向

1 先初始化窗口之后就进入下面的主循环。

下面是它的主循环代码,游戏就是在这样的循环中不断更新,直到退出的时候,销毁windows。

while(!gameEnd){while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {if( msg.message == WM_QUIT ) {// Stop loop if it's a quit messagegameEnd = true;} else {TranslateMessage( &msg );DispatchMessage( &msg );}}timer.approxiStableFPS();InvalidateRect(hWnd, NULL, TRUE);UpdateWindow(hWnd);}

2 首先定义一个球的数据结构

struct Ball
{int x; int y;int xVelocity;    int yVelocity;Ball(){}
};

3 在callback 函数中初始化参数,这里包括画笔,球和创建back buffer的初始化变量

LRESULT CALLBACK WindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{static HPEN MagentaPen  = CreatePen(PS_SOLID, 2, RGB(255, 0, 255));static HPEN OldPen   = NULL;static HBRUSH YellowBrush = CreateSolidBrush(RGB(255, 255, 0));static HBRUSH OldBrush = NULL;static int cxWidth, cyHeight; static Ball* balls = new Ball[NUM_BALLS];static HDC hdcBackBuffer;static HBITMAP    hBitmap;static HBITMAP  hOldBitmap;

初始化之后就是判断windows消息msg,

4 在首次创建Windows的时候,产生一个WM_CREATE消息,开始画图:

switch (msg){case WM_CREATE:{RECT rect;GetClientRect(hwnd, &rect);cxWidth = rect.right;cyHeight = rect.bottom;srand((unsigned) time(NULL));for (int i=0; i<NUM_BALLS; ++i){balls[i].x = uti::intRangeRand(0, cxWidth);balls[i].y = uti::intRangeRand(0, cyHeight);balls[i].xVelocity = uti::intRangeRand(1, MAX_VELOCITY);balls[i].yVelocity = uti::intRangeRand(1, MAX_VELOCITY);}hdcBackBuffer = CreateCompatibleDC(NULL);HDC hdc = GetDC(hwnd);hBitmap = CreateCompatibleBitmap(hdc,cxWidth,cyHeight);hOldBitmap = (HBITMAP)SelectObject(hdcBackBuffer, hBitmap);ReleaseDC(hwnd, hdc);}break;

5 在消息WM_PAINT中更新:

系统有需要重新画窗口或窗口的一部分的时候,就会产生一个WM_PAINT消息。比如最大化,最小化,改变窗口大小,窗口被遮挡的时候。
主循环中不断地调用:
        InvalidateRect(hWnd, NULL, TRUE);UpdateWindow(hWnd);
这两个函数,InvalidateRect确定要更新的区域,NULL代表默认整个窗口, UpdateWindow产生WM_PAINT消息,使得下面的代码不断更新:
case WM_PAINT:{PAINTSTRUCT ps;BeginPaint (hwnd, &ps);BitBlt(hdcBackBuffer, 0,    0, cxWidth, cyHeight, NULL, NULL, NULL,WHITENESS);OldPen = (HPEN)SelectObject(hdcBackBuffer, MagentaPen);OldBrush = (HBRUSH)SelectObject(hdcBackBuffer, YellowBrush);for (int i=0; i<NUM_BALLS; ++i){if (balls[i].x >= cxWidth) {balls[i].x = cxWidth - 1;balls[i].xVelocity *= -1;}if (balls[i].x < 0){balls[i].x = 1;balls[i].xVelocity *= -1;}if (balls[i].y >= cyHeight){balls[i].y = cyHeight -1;balls[i].yVelocity *= -1;}if (balls[i].y < 0){balls[i].y = 1;balls[i].yVelocity *= -1;}balls[i].x += balls[i].xVelocity;balls[i].y += balls[i].yVelocity;Ellipse(hdcBackBuffer,balls[i].x - RADIUS,balls[i].y - RADIUS,balls[i].x + RADIUS,balls[i].y + RADIUS);}SelectObject(hdcBackBuffer, OldPen);SelectObject(hdcBackBuffer, OldBrush);BitBlt(ps.hdc, 0, 0, cxWidth, cyHeight, hdcBackBuffer, 0, 0, SRCCOPY); RECT rect;GetClientRect(hwnd, &rect);char ch[] = "Bill Su's Bouncing Balls Demo";int chSize = strlen(ch);TextOut(ps.hdc, rect.left, rect.top, ch, chSize); EndPaint (hwnd, &ps);}break;

这段代码有点复杂,因为我完善了一个偏移功能:

当球与窗口边缘触碰的时候,球就自动向窗口内偏移1, 这样可以防止球“粘”在窗口边缘,不断碰撞。

使用GDI就需要这样处理,使用Direct2D就不需要了,原理解析:http://blog.csdn.net/kenden23/article/details/17402485

6 当窗口大小变化的时候更新球的位置:

case WM_SIZE:{double oldcx = (double)cxWidth;double oldcy = (double)cyHeight;cxWidth = LOWORD(lParam);cyHeight = HIWORD(lParam);double rateX = double(cxWidth) / oldcx;double rateY = double(cyHeight) / oldcy;for (int i=0; i<NUM_BALLS; ++i){balls[i].x *= rateX;balls[i].y *= rateY;}           SelectObject(hdcBackBuffer, hOldBitmap);DeleteObject(hBitmap); HDC hdc = GetDC(hwnd);hBitmap = CreateCompatibleBitmap(hdc, cxWidth, cyHeight);ReleaseDC(hwnd, hdc);SelectObject(hdcBackBuffer, hBitmap);}

球的位置与窗口的大小成比例的。

不过注意一个问题,就是当窗口最小化的时候,球的位置会变为(0,0) 。

如果前面没有偏移功能,那么这个时候就会把球粘在右上角了。

最后再看看效果图:

从真正的游戏程序角度来看,本程序为简单程序,有两个缺陷:

1 球的位置更新并不是按照时间来更新的

2 帧率并不是固定的

但是简单程序嘛,先这样吧。

我写的完整代码,有兴趣的可以参考下,可以很容易修改球的数量,速度和大小。

方便菜鸟了,包含了完成的所有vs文件,可以直接打开运行了。免积分下载:

http://download.csdn.net/detail/kenden23/6712077

声明:这个是GDI写的,直接的底层语言是C++,跟c#一点边也挨不上,居然有人评论我的资源是C#写的,不知道是被气死还是笑死,O(∩_∩)O~

这个是使用GDI写的,微软要使用Direct2D代替GDI,虽然Direct2D速度和效果比起GDI+都上了一个档次,但是给我感觉是Direct2D也不好用。估计微软的Direct2D要胎死腹中了,还是直接使用Direct3D吧。

Windows游戏编程 - 简单的弹球窗口相关推荐

  1. 【逐梦旅程Windows游戏编程学习笔记 ①】基本GDI绘图

    近半年各种忙碌,一直没写博客,现在得空学习记录一下,原书为<逐梦旅程 Windows游戏编程之从零开始>毛星云编著 实现样式与功能: 实现功能: 1,显示title:"致我们.. ...

  2. Windows游戏编程快速入门方法

    Windows游戏编程快速入门方法 Easideao(简单思路) 序言: 从2001年到2005年,在不知不觉中我已经渡过了4年的职业游戏开发生涯.在这4年里经常会有些网友向我询问编程的入门有没有捷径 ...

  3. Windows游戏编程之从零开始d

    Windows游戏编程之从零开始d I'm back~~恩,几个月不见,大家还好吗? 这段时间真的好多童鞋在博客里留言说或者发邮件说浅墨你回来继续更新博客吧. woxiangnifrr童鞋说每天都在来 ...

  4. 《Windows游戏编程大师技巧》(第二版)第2章

    因此几乎是一夜间,Windows 95就改变了整个计算机行业.的确,目前还有一些公司仍然在使用Windows 3.1(你能相信吗?),但是Windows 95使得基于Intel的PC成为除游戏之外的所 ...

  5. 《Windows游戏编程大师技巧》(第二版)第1章(上)

    第1章 学海无涯 "Oh, you want some too?!?" -Hudson, Aliens Windows 编程就像是一场由来已久并还在进行着的战争.尽管游戏程序员曾经 ...

  6. Windows游戏编程大师技巧(一)

    第一章 无尽之旅 Windows编程是一场由来已久并还在进行着的战争.开始时,游戏程序拒绝Windows平 台,但正如Borg所言:"反对无效......",我也赞同这一观点.本章 ...

  7. 【浅墨著作】 逐梦旅程 Windows游戏编程之从零开始 勘误 配套源代码下载

    这段时间真的好多童鞋在博客里留言说或者发邮件说浅墨你回来继续更新博客吧. woxiangnifrr童鞋说每天都在来浅墨的博客逛一下看有没有更新,"每天都来就像看女神那般不依不舍", ...

  8. 开始利用CSDN做学习笔记,从windows 游戏编程大师技巧和3D游戏编程大师开始

    利用两个月的空余时间将windows 游戏编程大师技巧和3D游戏编程大师技巧看了一遍. 第一遍读的并不深入,代码也没有仔细研究.特别是3D下册,基本只是草草浏览了一遍而已.这一遍是为了对整体有个印象和 ...

  9. windows游戏编程_少儿编程该怎么学?看看帕拉卡3D动画编程创始人李西峙分享七个核心...

    原标题:少儿编程该怎么学?看看帕拉卡3D动画编程创始人李西峙分享七个核心 市场上,有很多教孩子们学习编程的平台.我认为,它们都太糟糕了.我宁愿让我的小孩去玩游戏,也不愿意让他们去这样的平台上学习编程. ...

  10. 《Windows游戏编程大师技巧》(第二版)第1章(下)

    实例:FreakOut 在沉溺于所讨论的有关Windows.DirectX 和3D 图形之前,应当暂停一下,先给你看一个完整的游戏--虽然简单了一点,但毫无疑问是一个完整的游戏.你会看到一个实际的游戏 ...

最新文章

  1. 教育部:不得将研究生当作廉价劳动力!也不得故意拖延毕业时间!
  2. Linux进程突然挂死,当主进程突然死亡时,我该如何杀死linux spawnProcess?
  3. 重磅推荐:保姆级Java技术图谱!够学到元宵节了,赶紧收藏!
  4. mongodb java crud_MongoDB用Java,简单的CRUD操作,两种方法,附源码下载。
  5. AttributeError: ‘float‘ object has no attribute ‘exp‘
  6. 6.29 Vue 第二天 学习笔记
  7. !JS实战之随机像素图
  8. Hyperledger Fabric 1.0发布:基于区块链的开源分布式账本
  9. 实现 VUE 中 MVVM - step10 - Computed
  10. 图论--树的直径--DFS+树形DP模板
  11. VerifyRenderingInServerForm 和EnableEventValidation引发的两个问题
  12. c语言两个线程交替打印奇数和偶数,经典面试题——两个线程交替打印奇数和偶数...
  13. 资源打包Assetbundle .
  14. [转载] python打包程序在win10不能运行、点击无反应_Windows10平台用PyInstaller打成exe程序后不能运行请高手指点...
  15. 开两个服务内存溢出_详解JVM内存区域
  16. jq监听子元素被点击_jQuery怎么实现当前被点击元素的父级下的某个元素显示出来了?...
  17. Android反编译APK
  18. OSX 安装配置Maven
  19. Linux下禁用笔记本触摸板
  20. PyMOL | Pymol绘图教程(一)

热门文章

  1. 遥感影像数据下载网站整理
  2. IE浏览器版本 - 升级与降级( IE8、 IE9 、IE10)
  3. vue项目实战-尚品汇
  4. 新书上市|这套北大数学系青睐的数学科普书,又添新成员
  5. 二维码----百度百科
  6. Tomcat的下载及安装
  7. 16进制编辑器 linux,Tweak - Linux下的16进制编辑器
  8. html自动计时器,html计时器
  9. 打标工具labelme或者labelimg遇到图片闪退的完美解决方案
  10. 面试 之 git工作流