放一个菜鸟级的程序出来:
做一个简单的弹球窗口,碰到窗口边缘就会弹回。
该程序的球不会粘边缘,可以任意改变窗口,可以最小化都不会出问题。
效果图如下:
算法:
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 message
gameEnd = 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吧。
分享到:
相关推荐
【VC++编程实例:一个小弹球游戏】 在计算机科学领域,尤其是编程,开发小型游戏是学习新语言或技术的一种有趣且实用的方式。本教程将深入探讨如何使用Microsoft的Visual C++(简称VC++)来创建一个简单的弹球游戏...
标题中的“简单Windows弹球程序”指的是一个基于Windows操作系统开发的简单游戏,它模拟了物理中的弹球运动。这类程序通常用C++或C#等编程语言编写,并使用Windows API来实现图形用户界面和游戏逻辑。 描述中提到的...
《C#实现简单弹球游戏源码解析》 在编程世界中,开发一款简单的游戏是初学者们常常选择的实践项目。本篇文章将详细解析一个使用C#语言编写的弹球游戏源码,旨在帮助读者了解游戏开发的基本原理,以及C#在图形用户...
总结,VB6编写的弹球游戏是一个集成了基础编程概念和简单物理模拟的实例,对于初学者来说,它提供了一个良好的实践平台,有助于理解和应用编程知识。通过分析和调试游戏源码,开发者可以进一步提高自己的编程技能和...
本资源提供的"弹球游戏"出自《windows游戏编程大师》,对于想要深入理解C++游戏开发的初学者来说,是一个很好的实践平台。 首先,我们从C++语言的角度来看,弹球游戏需要掌握的关键知识点包括: 1. **面向对象编程...
弹球游戏的实现基于Windows的消息机制,利用MFC(Microsoft Foundation Classes)库来处理窗口、图形绘制、事件处理等。 游戏的核心功能包括: 1. **图形界面**:游戏界面通常包含背景图像、弹球、挡板等元素,这些...
在编程世界中,"简单的弹球程序"是一个基础级别的项目,通常用于教学目的,帮助初学者理解游戏开发的基本原理和C语言的运用。这个程序可能包含了一些基本的图形用户界面(GUI)元素,如窗口、图像和动画效果,以及...
【桌面弹球小游戏简单实现】 桌面弹球游戏是一款经典的休闲娱乐软件,它的基本玩法是通过一个或多个挡板控制一个小球在屏幕上弹跳,避免小球落地。这种游戏的实现通常涉及计算机图形学、物理模拟以及事件处理等编程...
【标题】"简单的WIN32弹球游戏"是一款基于Windows操作系统平台开发的,利用GDI(Graphics Device Interface)图形设备接口技术实现的经典弹球游戏。它以简单的编程逻辑和直观的用户界面展现了游戏的基本功能,为初学...
总的来说,【VC++小游戏:弹球游戏】是一个综合性的项目,涵盖了C++编程、Windows API、图形界面设计、游戏逻辑等多个方面。开发者在实现这个游戏的过程中,既能巩固基础技能,也能学习到实际项目开发的经验。
1. **图形用户界面(GUI)设计**:游戏可能使用Windows Forms或WPF(Windows Presentation Foundation)库来创建用户界面,包括游戏窗口、控件(如弹球和挡板)以及动画效果。 2. **事件处理**:C#中的事件处理机制...
`Ball`类顾名思义,代表了游戏中的弹球,包含了弹球的位置、速度、碰撞检测等关键属性和行为。`PinBall`类可能代表了挡板,玩家可以通过它来控制弹球的方向。`AudioControl`类则负责处理游戏的声音效果,包括弹球...
这款小游戏是基于WIN32框架构建的,对于想要学习游戏编程初学者来说,这是一个很好的起点。通过这个简洁的代码实现,我们可以了解到游戏开发的一些基本原理和技巧。 首先,C语言是一种基础且强大的编程语言,它为...
Python 游戏编程是初学者进入游戏开发领域的理想起点,特别是在使用Pygame库时。Pygame是Python的一个扩展模块,专为2D游戏设计,它提供了丰富的功能,包括图形、声音、事件处理等,使得创建游戏变得相对简单。在...
【C#实现简易弹球小游戏】\n\n在编程领域,使用C#语言开发小游戏是一种常见的练习,既能提升编程技能,又能带来娱乐性。本文将详细介绍如何利用C#来创建一个简单的弹球游戏,其中涉及的主要知识点包括游戏循环、碰撞...
标题中的“经典的弹球游戏”指的是一个以弹球为主题的计算机程序,这种类型的游戏通常具有简单的物理模拟,玩家通过控制挡板来反弹小球,避免它掉落到屏幕底部。这种游戏在编程教学中常被用作实践项目,因为它涉及到...
在编程领域,游戏开发是吸引众多爱好者的一大主题,尤其是对于初学者来说,通过创建简单的游戏可以更好地理解和掌握编程语言。本文将深入探讨如何使用C#语言和.NET框架来开发一款经典的弹球游戏。这款名为"Pong Game...
【描述】"过程很简单"暗示了该程序的实现逻辑并不复杂,主要是通过C#的Windows Forms框架来创建图形用户界面(GUI),并利用事件驱动编程来处理用户的输入和游戏逻辑。开发者可能使用了基本的图形绘制功能来创建球和...
描述中提到的 "经典的一款小游戏,初步模型,没有完整,基本功能实现" 告诉我们这是一个简单的弹球游戏原型,可能包含基本的游戏逻辑但尚未完全完善。这意味着代码可能展示了如何创建游戏的基本元素,如球的移动、...
《接弹球——C#实现的小游戏解析》 ...总的来说,"接弹球"小游戏虽然简单,但它涵盖了C#编程的基础知识和游戏开发的核心概念。通过分析和重构这样的项目,开发者可以提升自己的编程技能,更好地理解和运用C#语言。