[图形学] 画圆(基于中点算法) 铜牌收录

图形学中的中点画圆算法,以下是该算法的 C 语言实现:

///////////////////////////////////////////////////
// 程序名称:基于中点算法画圆
// 编译环境:Visual C++ 6.0 / 2010,EasyX_20210730
// 作  者:YangW <yw80@qq.com>
// 最后修改:2011-4-29
//
#include <graphics.h>
#include <conio.h>

// 中点画圆法
void Circle_Midpoint(int x, int y, int r, int color)
{
	int tx = 0, ty = r, d = 1 - r;

	while(tx <= ty)
	{
		// 利用圆的八分对称性画点
		putpixel(x + tx, y + ty, color);
		putpixel(x + tx, y - ty, color);
		p
...

扔香蕉的大猩猩(怀旧) 铜牌收录

又是一个怀旧的游戏,让我想起了以前学习编程的时候。

这个游戏模仿的微软在 20 多年前的一个小游戏,不知道谁也有印象呢?图片都是从原来的游戏中抓图弄出来的,颜色也是从原游戏抓图中取色设置的,应该和原来的风格很像。

你的任务是用香蕉击中你的对手。

你可以通过鼠标调整投掷香蕉的角度和力度,香蕉会受重力加速度的影响。同时,请注意屏幕底部表示风力的箭头,香蕉同样会受风力影响。风力的箭头越长,表示风力越强。还有,周围的楼宇会阻挡你的香蕉。

游戏运行效果如下:

完整的源代码和图片可以【点击这里下载】。

也可以直接查看如下游戏源代码(注意,除了以下代码,还需要两个图片文件,在前面的压缩包里面有):

// 程序名称:扔香蕉的大猩猩
// 编译环境:Visual C++ 6.0 ~ 2019,EasyX_20210730
// 作  者:慢羊羊 <yw80@qq.com>
// 发布日期:2012-9-23
// 最
...

计算任意扇形的最小包围矩形 铜牌收录

今天很偶然需要这样一个东西:

求任意扇形的最小包围矩形,要求矩形的边是水平、垂直的。

这个东西看似很简单,但是仔细一想,需要注意的地方蛮多的,还真有点不好下手。再回想一下,好像没有那本书里面讲过。然后百度了一下,似乎也没找到有效的方法。于是我就花了点时间搞定了这个东西,然后顺手写了一个例子演示效果。

如果您有更好的方法,十分期待交流一下。

以下代码除了包含必要的求解任意扇形的最小包围函数之外,还加上了鼠标操作:按下左键移动鼠标,可以调整终止角的弧度;同时按下 Shift 键移动,可以调整起始角的弧度。

执行效果如图:

完整代码如下:

///////////////////////////////////////////////////
// 程序名称:计算扇形的最小包围矩形
// 编译环境:Visual C++ 6.0 / 2019,EasyX 20210730
// 作  者:yangw80 <yw80
...

解决鼠标左键拖放和双击会触发 _getch() 的问题 铜牌收录

有网友反馈说,鼠标左键按下并拖动后,会相当于一次键盘按键,使 _getch() 触发。鼠标双击也会使 _getch() 触发。经过排查后,发现该问题是某些翻译软件的划词翻译功能引起的。

解决方法:关掉翻译软件的划词翻译功能(比如有道词典就有这个功能)。

或者,使用 getmessage(EM_CHAR) 替代 _getch() 实现按任意键继续。

[图形学] 画任意斜率的直线(基于 DDA 算法) 铜牌收录

图形学中的 DDA (Digital Differential Analyzer) 画直线算法,以下是该算法的 C 语言实现:

///////////////////////////////////////////////////
// 程序名称:基于 DDA 算法画任意斜率的直线
// 编译环境:Visual C++ 6.0 / 2010,EasyX 2011惊蛰版
// 作  者:yangw80 <yw80@qq.com>
// 最后修改:2011-4-26
//
#include <graphics.h>
#include <conio.h>

// 四舍五入
int Round(float x)
{
	return (int)(x < 0 ? x - 0.5 : x + 0.5);
}

// 使用 DDA 算法画任意斜率的直线(包括起始点,不包括终止点)
void Line_DDA(int x1, int y1, int x2, int y2, int co
...

[图形学] 画任意斜率的直线(基于中点算法) 铜牌收录

图形学中的直线的中点算法,以下是该算法的 C 语言实现:

///////////////////////////////////////////////////
// 程序名称:基于中点算法画任意斜率的直线
// 编译环境:Visual C++ 6.0 / 2010,EasyX 2011惊蛰版
// 作  者:yangw80 <yw80@qq.com>
// 最后修改:2011-4-26
//
#include <graphics.h>
#include <conio.h>

// 使用中点算法画任意斜率的直线(包括起始点,不包括终止点)
void Line_Midpoint(int x1, int y1, int x2, int y2, int color)
{
	int x = x1, y = y1;
	int a = y1 - y2, b = x2 - x1;
	int cx = (b >= 0 ? 1 : (b = -b, -1));
	int cy = (a
...

[图形学] 画任意斜率的直线(基于 Bresenham 算法) 铜牌收录

图形学中的 Bresenham 画直线算法,以下是该算法的 C 语言实现:

///////////////////////////////////////////////////
// 程序名称:基于 Bresenham 算法画任意斜率的直线
// 编译环境:Visual C++ 6.0 / 2010,EasyX 2011惊蛰版
// 作  者:yangw80 <yw80@qq.com>
// 发布日期:2011-4-26
//
#include <graphics.h>
#include <conio.h>

// 使用 Bresenham 算法画任意斜率的直线(包括起始点,不包括终止点)
void Line_Bresenham(int x1, int y1, int x2, int y2, int color)
{
	int x = x1;
	int y = y1;
	int dx = abs(x2 - x1);
	int dy = abs(y2 - y1);
	int
...

[图形学] 画圆(基于正负算法) 铜牌收录

图形学中的正负画圆算法,以下是该算法的 C 语言实现:

///////////////////////////////////////////////////
// 程序名称:基于正负算法画圆
// 编译环境:Visual C++ 6.0 / 2010,EasyX_20210115
// 作  者:YangW <yw80@qq.com>
// 最后修改:2011-5-3
//
#include <graphics.h>
#include <conio.h>

// 正负画圆法
void Circle_PN(int x, int y, int r, int color)
{
	int tx = 0, ty = r, f = 0;

	while(tx <= ty)
	{
		// 利用圆的八分对称性画点
		putpixel(x + tx, y + ty, color);
		putpixel(x + tx, y - ty, color);
		putpixel(x -
...

快速画点的原理简述,以及写一个自己的快速画点函数 铜牌收录

EasyX 自带的 putpixel 函数源自 Windows GDI 函数 SetPixel,由于要考虑裁剪区、缩放、原点坐标、坐标方向等等诸多因素,所以性能很低,在一些只要求速度的场合很不实用。这篇文章就教你写一个自己的画点函数。

总的思想,是通过直接操作显示缓冲区来避免额外的运算。

在 EasyX 绘图窗口的显示缓冲区中,每个点占用 4 个字节,用 DWORD 指针指向显示缓冲区就可以像一维数组一样访问了。然后就是将二维坐标 (x, y) 映射到一维数组中,很简单,y * 640 + x 就是。另外需要注意的是,显示缓冲区中颜色的保存和 COLORREF 相比,蓝色和红色是相反的,需要用 BGR 宏转换一下(BGR 宏执行两次就会还原为原值)。

然后,我们整理出画点和读点的函数:
(记得要获取显示缓冲区指针并保存为全局变量)

DWORD* g_pBuf;

// 在 main 函数中
g_pBuf = GetImageBuffer();

void 
...

烟花 铜牌收录

一个基于物理的烟花小程序,考虑了重力。代码基于 c++ 进行编写的,使用 QueryPerformceCount 进行帧率控制。由于在实现烟花小尾巴时候遍历了一遍屏幕上所有的像素点,虽然使用显示缓冲区进行操作,但是这个循环遍历代价还是很大,所以帧率在我的 cpu i7 7700hq 上,以 1920 * 1080 分辨率一直在 35 帧左右,改成 cleardevice 后能变成100多帧,但是小尾巴没了。虽然小尾巴可以画一连串的颜色渐变亮的小圆表示,但是这样表示我看起来没有对屏幕像素取平均效果好。希望有网友能提供更有效、更好的烟花尾巴解决方案。

为什么屏幕分辨率是 640x480? 铜牌收录

常见的屏幕分辨率很奇怪,为什么总用一些不零不整的数字?比如以前最常见的分辨率是 640 x 480,当初为什么这么设计?

因为这个分辨率运算速度比较快,人也相对比较好记。

大家知道,屏幕上的每一个点,都会对应内存中的一个位置。比如 640x480@256色,表示每个点占用一个字节,整个屏幕有 640 x 480 = 300k 个点,占用 300KB 内存。屏幕的每一个像素的保存,在内存中是线性存储结构。在屏幕上的坐标 (x, y) 画一个点,就相当于在对应内存偏移 y * 640 + x 的位置赋值。

PS:在这篇文章中有一段代码,可以实践一下通过内存赋值来直接画点:https://codebus.cn/yangw/fast-putpixel

每绘制一个点,都需要执行一次乘法和一次加法运算。所有的绘图操作都需要调用画点函数,因此提高画点的效率,将会提升所有绘图操作的速度。

现在我们将计算内存偏移量的算法修改一下:

d = y * 640 +
...

VC绘图/游戏简易教程--16:设备上下文句柄(Windows 编程入门2) 铜牌收录

教程总目录:https://codebus.cn/bestans/post/concise-lesson-contents(里面包括VC下的graphics.h的配置方法)

注:学习本节前,请自备 MSDN,以便查阅 Windows GDI 函数。

对于 Windows GDI 中的绘图函数,操作目标通常是 DC(Device Context),因此需要传入一个 DC 的句柄,数据类型为 HDC(Handle of Device Context)。用 GetImageHDC() 函数可以获取 EasyX 的绘图窗口或 IMAGE 对象的句柄,然后就可以使用 Windows GDI 函数进行绘图操作。看以下示例:

#include <graphics.h>
#include <conio.h>

int main()
{
	// 初始化绘图窗口,并获取 HDC 句柄
	initgraph(640, 480);
	HDC hdc = GetImageHDC();
...

VC绘图/游戏简易教程--15:窗体句柄(Windows 编程入门) 铜牌收录

教程总目录:https://codebus.cn/bestans/post/concise-lesson-contents(里面包括VC下的graphics.h的配置方法)

EasyX 库有一个获取窗口句柄的功能,很是强大,这里介绍一下。

【窗体句柄】

窗体句柄是 Windows 下窗口的标识,可以理解为窗口的 ID。Windows SDK 中的许多窗口操作函数都需要指明窗体句柄,也就是说,有了句柄,我们可以通过 Windows SDK 中的 API 实现许多高级的窗体控制。

【函数原型】

窗体句柄为 HWND 类型,通过 GetHWnd() 函数可以返回绘图窗体的句柄。其函数原型是:
HWND GetHWnd();

【使用句柄】

举个例子,设置窗体标题文字的 Windows API 为:
BOOL SetWindowText(HWND hWnd, LPCTSTR lpString);
参数:
   hWnd: 要设置标题文字的窗口句柄

...

VC绘图/游戏简易教程--13:getimage / putimage / loadimag / saveimage / IMAGE 的用法 铜牌收录

教程总目录:https://codebus.cn/bestans/post/concise-lesson-contents(里面包括VC下的graphics.h的配置方法)

 getimage / putimage / loadimage / saveimage 这一组命令和 IMAGE 对象可以实现图像处理的相关功能,下面逐个介绍。
(有点类似 tc 中的 imagesize)

[加载图片]

实现加载图片主要分三步:

  1. 定义 IMAGE 对象
  2. 读取图片至 IMAGE 对象
  3. 显示 IMAGE 对象到需要的位置

很简单,我们看一下完整的代码:

#include <graphics.h>
#include <conio.h>

int main()
{
	initgraph(640, 480);

	IMAGE img;	// 定义 IMAGE 对象
...