前言
有时候我们在访问网页的时候,会看到网页的背景是好多点和线组成的那种动态图,今天我就来实现一下这个动态图的生成,其中包含了随机运动的点和基于距离感知的连线。下面,我们将深入讲解这一系统的生成原理。
一、随机运动点的生成
初始化:每个点(
Point
类的一个实例)在创建时,会被赋予一个随机的初始位置(x
和y
坐标)以及一个随机的速度(xSpeed
和ySpeed
),这些速度决定了点将如何移动。边界回弹:为了防止点移出屏幕,我们设置了边界回弹机制。当点触碰到屏幕的边缘时,它的速度方向会反转,从而使其“反弹”回来,继续在屏幕内移动。
绘制与更新:在每次绘制循环中,我们首先更新每个点的位置(通过在其当前位置上加上速度),然后绘制这些点。这里使用了圆形(
solidcircle
函数)来表示每个点,并设置了统一的填充颜色。
二、距离感知的连线
计算距离:对于屏幕上的每一对点,我们计算它们之间的欧几里得距离。这是通过计算两点在x轴和y轴上距离的平方和,然后开平方根得到的。
条件判断与连线:如果两点之间的距离小于或等于设定的最大距离(
maxDis
),则在这两点之间绘制一条线。这条线的颜色会根据距离动态变化,距离越近,颜色越亮;距离越远,颜色越暗。颜色映射:为了将距离映射到颜色上,我们使用了一个简单的线性插值方法。具体来说,我们根据距离与最大距离的比例,计算出一个介于0和255之间的数值(
NUM
),然后将这个数值加上一个偏移量(offset
),以得到一个更加明亮的颜色范围。最后,我们使用这个计算出的颜色值来设置连线的颜色。
三、整体流程
整个程序运行在一个无限循环中,不断地更新和绘制屏幕上的点和连线。为了提高绘制效率,我们使用了批量绘制技术(BeginBatchDraw
和FlushBatchDraw
),这可以减少绘制过程中的屏幕刷新次数,从而提高程序的性能。
四、源码
///////////////////////////////////////////////////
// 程序名称:动态图
// 编译环境:Mictosoft Visual Studio 2022, EasyX_20200315(beta)
// 作 者:luoyh <2864292458@qq.com>
// 最后修改:2024-9-26
// 公 众 号:C语言研究
//
// 设置随机数产生方法
int getRandom(int min, int max)
{
return rand() % (max - min + 1) + min;
}
// Point类
class Point
{
public:
int x, y;
int xSpeed, ySpeed;
int r;
Point()
{
r = 3; // 点的半径
x = getRandom(0, getwidth() - r);
y = getRandom(0, getheight() - r);
xSpeed = getRandom(-3, 3);
ySpeed = getRandom(-3, 3);
}
void draw()
{
// 更新坐标
x += xSpeed;
y += ySpeed;
// 超出边界回弹
if (x > getwidth() - r)
{
x = getwidth() - r;
xSpeed = -xSpeed;
}
else if (x < 0)
{
x = 0;
xSpeed = -xSpeed;
}
if (y > getheight() - r)
{
y = getheight() - r;
ySpeed = -ySpeed;
}
else if (y < 0)
{
y = 0;
ySpeed = -ySpeed;
}
// 绘制点
setfillcolor(RGB(200,200,200));
solidcircle(x, y, r);
}
};
// Graph类
class Graph
{
private:
Point* points;
int pointNumber;
int maxDis;
public:
Graph(int pointNum = 80, int maxDistance =70)
{
pointNumber = pointNum;
maxDis = maxDistance;
points = new Point[pointNumber];
}
~Graph()
{
delete[] points;
}
void draw()
{
BeginBatchDraw();
while (true)
{
for (int i = 0; i < pointNumber; i++)
{
points[i].draw();
for (int j = i + 1; j < pointNumber; j++)
{
int dx = points[i].x - points[j].x;
int dy = points[i].y - points[j].y;
int distance = sqrt(dx * dx + dy * dy);
if (distance <= maxDis)
{
int NUM = 255-static_cast<int>(distance * 255.0 / maxDis); // 确保NUM是整数
int offset = 50;
setlinecolor(RGB(NUM+ offset, NUM+ offset, NUM+ offset)); // 当NUM接近0时,颜色接近黑色;当NUM接近255时,颜色接近白色
line(points[i].x, points[i].y, points[j].x, points[j].y);
}
}
}
Sleep(20);
FlushBatchDraw();
cleardevice(); // 清空画布
}
EndBatchDraw();
}
};
int main()
{
initgraph(640, 480);
srand(time(NULL));
Graph g;
g.draw();
closegraph(); // 关闭图形窗口
return 0;
}
五、效果