放一个菜鸟级的程序出来:
做一个简单的弹球窗口,碰到窗口边缘就会弹回。
该程序的球不会粘边缘,可以任意改变窗口,可以最小化都不会出问题。
效果图如下:
1 取得窗口大小,以作为判断是否到边缘了
2 判断球的位置是否到了边缘,如果到了边缘,速度方向就为反方向
下面是它的主循环代码,游戏就是在这样的循环中不断更新,直到退出的时候,销毁windows。
while(!gameEnd)
{
while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if( msg.message == WM_QUIT )
{
// Stop loop if it's a quit message
gameEnd = true;
}
else
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
timer.approxiStableFPS();
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
}
struct Ball
{
int x; int y;
int xVelocity; int yVelocity;
Ball(){}
};
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;
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
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
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= 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
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
不过注意一个问题,就是当窗口最小化的时候,球的位置会变为(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吧。