关闭

Windows编程 GDI简单图形的绘制 简单实现锁帧效果

标签: Windows编程GDI绘图定时器锁帧
264人阅读 评论(0) 收藏 举报
分类:

版本:VS2015 语言:C++

 

快要到9月份了,天气渐渐凉了,没有空调的我终于渐渐看到了光明。

 

现在书的进度进入都最后一章的Windows编程,嘛,和作者的态度差不多,Windows编程实在是枯燥乏味,但是也是必须去了解一些基础的知识,不然看到别人的程序就懵逼了。

 

最后一章我分为两个章节来讨论,首先是GDI图形绘制(相比于使用GPU硬件加速的D3D肯定要慢)、锁帧效果,之后是作者做的游戏控制台程序,说不定我能玩出点花样来,现在还没有看。

 

好了,让我们进入正题吧。

 

点,所有图形的基础,想要绘制一个图形就得要知道怎么绘制一个点。让我们来看看代码(代码放在GameMain函数处,不清楚的请看一下我写的Windows编程第二节,即游戏循环框架的基本实现):

HDC hdc = GetDC(hwnd);	//获取图像设备表
int x = rand() % 400;	//随机x、y坐标
int y = rand() % 400;
COLORREF color = RGB(rand() % 255, rand() % 255, rand() % 255);	//随机来个颜色
SetPixel(hdc, x, y, color);	//画点!
Sleep(100);
ReleaseDC(hwnd, hdc);	//释放

画点很简单吧,但是点太小了吧,根本看不清啊,来个大点的:

HDC hdc = GetDC(hwnd);	//获取图像设备表
int x = rand() % 400;	//随机x、y坐标
int y = rand() % 400;
COLORREF color = RGB(rand() % 255, rand() % 255, rand() % 255);	//随机来个颜色
int size = 4;	//设置点的大小
for (int i = 0; i < size; ++i)
	for (int j = 0; j < size; ++j)
		SetPixel(hdc, x+i, y+j, color);	//画点!
Sleep(100);
ReleaseDC(hwnd, hdc);	//释放

效果:



嗯,很棒!有点了,然后就是要画线了,画线的话首先要学到一个画笔的系统,在画之前首先就要设置画笔,这跟画点有点不一样,画点什么都不用管,看代码:

int x = rand() % 400;	//随机x、y坐标
int y = rand() % 400;
int x2 = rand() % 400;	//随机x2、y2坐标
int y2 = rand() % 400;
COLORREF color = RGB(rand() % 255, rand() % 255, rand() % 255);	//随机来个颜色

HDC hdc = GetDC(hwnd);	//获取图像设备表
HPEN pen = CreatePen(PS_SOLID, 1, color);	//获取铅笔
SelectObject(hdc, pen);	//设置铅笔
			
MoveToEx(hdc, x, y, NULL);	//把点移动到初始点
LineTo(hdc, x2, y2);	//画线!

Sleep(100);

DeleteObject(pen);
ReleaseDC(hwnd, hdc);	//释放

效果:



以上就实现了画线的效果,需要注意的是画边框之类的线条结构,基本都是要设置HPEN铅笔的,而实心结构则需要设置画刷HBRUSH。

 

下面讲随机画矩形的示例,这边即用到了画笔画出矩形的边框,又用画刷填充矩形:

// 初始化坐标数据
int x = rand() % 400;	//随机x、y坐标
int y = rand() % 400;

// 设置绘图相关数据
HDC hdc = GetDC(hwnd);	//获取图像设备表

COLORREF color = RGB(rand() % 255, rand() % 255, rand() % 255);	//随机来个颜色
HPEN pen = CreatePen(PS_SOLID, 1, color);	//获取铅笔
SelectObject(hdc, pen);	//设置铅笔

color = RGB(rand() % 255, rand() % 255, rand() % 255);	//再来随个
HBRUSH brush = CreateSolidBrush(color);	//获取画刷
SelectObject(hdc, brush);	//设置画刷

//绘制
Rectangle(hdc, x, y, x + 10, y + 10);

Sleep(100);

//释放对象
DeleteObject(pen);
DeleteObject(brush);
ReleaseDC(hwnd, hdc);

非常好!这样我们就能随机绘制正方形了。细心的玩家可能注意到了,在设置铅笔和画刷的时候使用的函数都是一样的,都是SelectObject、DeleteObject。我想这个方法肯定不止用在这,否则也不会叫做Object了。具体我就不探究了。

 

什么,你想画圆?也很简单,之前不是学了画矩形嘛,在Windows中画圆其实就是绘制矩形的内切圆,参数是一模一样的,只需要把绘制矩形的代码写成:

Ellipse(hdc, x, y, x + 10, y + 10);

就是这种弧线锯齿很严重,非常想学抗锯齿的知识!

 

接下来是多边形,给大家一个画六边形的代码,具体更多有趣的玩法,请自己尝试尝试。

 

下面是代码:

POINT poly[6] = { {x + 10, 0 + y}, {x + 30, 0 + y}, {x + 40, 17.3 + y}, {x + 30, 34.6 + y}, {x + 10, 34.6 + y}, {x + 0, 17.3 + y} };	//六边形的坐标
Polygon(hdc, poly, 6);	//根据6个点进行绘制,注意点的顺序很有关系


把绘制矩形的代码替换成以上代码,就能获得一下效果:



其实想想看,关键绘制的代码就那么一两句,而且hdc、pen、brush之类的非常常用,所以真正编写的时候设置成全局的变量会比较舒服吧,这样实际的代码会非常的简洁,以后要改什么功能也不必关注这类初始化、销毁的细节。

 

最后作者问了一个问题,如果你绘制时点的顺序是混乱的,绘制多边形的时候很容易绘制出凹多边形,那么如何判断一个多边形是否是凸多边形呢?

 

我一开始的想法有点简单了,后来百度查了一下了解到了凸多边形的定义,就是任意两个临近的点画一条直线,所有其他的点都在直线的一侧就可以判断出是凸多边形了。

 

具体代码实现给大家讲一个思路,循环临近的所有两点,根据其他点的x坐标,算出临近两点画出直线对应的y坐标,这个y坐标是在直线上的,跟判断点的y坐标对比一下,看看其他的各点是否都大于(或都小于)y坐标。

 

最后讲一下实现锁帧的效果,当然也是GameMain处的代码:

DWORD start_time = GetTickCount();	//获取开始的时间
//画点画线的各种处理
while ((GetTickCount() - start_time) < 1000);// 延时代码

这里的代码就增强的Sleep的效果,没想到锁帧这么容易吧?

 

对了,突然想起来忘记比较重要的定时器了,嗯……简单介绍一下:

UNIT SetTimer(HWND hWnd,	//图形设备表
UINT nIDevent,	//定时器的id
UINT nElapse,	//延时的毫秒数
TIMERPROC lpTimerFunc);	//延时的回调函数,NULL的话默认WinProc处理

待定时完成,就会触发处理事件WinProc,事件的类型是WM_TIMER,然后根据参数wparam就能判断出定时器的id,进行相应的处理。

 

KillTimer(hwnd, timer)是删除定时器的函数。具体例子就不说了,其实跟cocos的schdule非常像。

 

简单却很重要,就是这个东西吧。



1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:49229次
    • 积分:1317
    • 等级:
    • 排名:千里之外
    • 原创:80篇
    • 转载:0篇
    • 译文:0篇
    • 评论:62条
    最新评论