#include<stdio.h> //基本输入输出库(用于控制台中的输出显示)
#include<conio.h> //不缓冲输入输出库(用于键盘交互)
#include<math.h> //用于某些数学运算,比如sin,cos 等
#include<stdlib.h> //用于随机数运算等场合
#include<time.h> //用于获取系统时间
#include<graphics.h> //VC++下最简单的图形库,但功能很强大
POINT *g_pDst; // 点集(目标)
POINT *g_pSrc; // 点集(源)
int g_nWidth; // 文字的宽度
int g_nHeight; // 文字的高度
int g_nCount; // 点集包含的点的数量
#define MAXSTAR 1000 // 星星总数
void GetDstPoints()
{
// 设置临时绘图对象
IMAGE img;
SetWorkingImage(&img);
// 定义目标字符串
TCHAR s[] = _T("母亲节快乐!");
// 计算目标字符串的宽高,并调整临时绘图对象的尺寸
setcolor(WHITE);
settextstyle(100, 0, _T("Arial"));
g_nWidth = textwidth(s);
g_nHeight = textheight(s);
Resize(&img, g_nWidth, g_nHeight);
// 输出目标字符串至 img 对象
outtextxy(0, 0, s);
// 计算构成目标字符串的点的数量
int x, y;
g_nCount = 0;
for (x = 0; x < g_nWidth; x++)
for (y = 0; y < g_nHeight; y++)
if (getpixel(x, y) == WHITE)
g_nCount++;
// 计算目标数据
g_pDst = new POINT[g_nCount];
int i = 0;
for (x = 0; x < g_nWidth; x++)
for (y = 0; y < g_nHeight; y++)
if (getpixel(x, y) == WHITE)
{
g_pDst[i].x = x + (640 - g_nWidth) / 2;
g_pDst[i].y = y + (480 - g_nHeight) / 2;
i++;
}
// 恢复对屏幕的绘图操作
SetWorkingImage(NULL);
}
// 获取源点集
void GetSrcPoints()
{
// 设置随机种子
srand((unsigned int)time(NULL));
// 设置随机的源数据
g_pSrc = new POINT[g_nCount];
for (int i = 0; i < g_nCount; i++)
{
g_pSrc[i].x = rand() % 640;
g_pSrc[i].y = rand() % 480;
}
}
// 全屏模糊处理(忽略屏幕第一行和最后一行)
void Blur(DWORD* pMem)
{
for (int i = 640; i < 640 * 479; i++)
{
pMem[i] = RGB(
(GetRValue(pMem[i]) + GetRValue(pMem[i - 640]) + GetRValue(pMem[i - 1]) + GetRValue(pMem[i + 1]) + GetRValue(pMem[i + 640])) / 5,
(GetGValue(pMem[i]) + GetGValue(pMem[i - 640]) + GetGValue(pMem[i - 1]) + GetGValue(pMem[i + 1]) + GetGValue(pMem[i + 640])) / 5,
(GetBValue(pMem[i]) + GetBValue(pMem[i - 640]) + GetBValue(pMem[i - 1]) + GetBValue(pMem[i + 1]) + GetBValue(pMem[i + 640])) / 5);
}
}
void IceWorld()
{
DWORD* pBuf = GetImageBuffer(); // 获取显存指针
GetDstPoints(); // 获取目标点集
GetSrcPoints(); // 获取源点集
// 运算
int x, y;
for (int i = 2; i <= 128; i += 2)
{
COLORREF c = RGB(i-1,i-1,2*i-2);
Blur(pBuf); // 全屏模糊处理
for (int d = 0; d < g_nCount; d++)
{
x = g_pSrc[d].x + (g_pDst[d].x - g_pSrc[d].x) * i / 128;//256;
y = g_pSrc[d].y + (g_pDst[d].y - g_pSrc[d].y) * i / 128;//256;
pBuf[y * 640 + x] = c; // 直接操作显存画点
}
FlushBatchDraw(); // 使显存操作生效
Sleep(10); // 延时
}
// 清理内存
delete g_pDst;
delete g_pSrc;
// 按任意键退出
//getch();
//closegraph();
}
struct STAR
{
double x;
int y;
double step;
int color;
};
STAR star[MAXSTAR];
// 初始化星星
void InitStar(int i)
{
star[i].x = 0;
star[i].y = rand() % 480;
star[i].step = (rand() % 5000) / 1000.0 + 1;
star[i].color = (int)(star[i].step * 255 / 6.0 + 0.5); // 速度越快,颜色越亮
star[i].color = RGB(star[i].color, star[i].color, star[i].color);
}
// 移动星星
void MoveStar(int i)
{
// 擦掉原来的星星
putpixel((int)star[i].x, star[i].y, 0);
// 计算新位置
star[i].x += star[i].step;
if (star[i].x > 640) InitStar(i);
// 画新星星
putpixel((int)star[i].x, star[i].y, star[i].color);
}
// 主函数
void Stars()
{
srand((unsigned)time(NULL)); // 随机种子
//initgraph(640, 480); // 创建绘图窗口
HRGN rgn1 = CreateRectRgn(0, 0, 640, 100);
HRGN rgn2 = CreateRectRgn(0, 380, 640, 480);
HRGN rgn = CreateRectRgn(0, 0, 640, 100);
CombineRgn(rgn, rgn1, rgn2, 2);
// 将该矩形区域设置为裁剪区
setcliprgn(rgn);
// 不再使用 rgn,清理 rgn 占用的系统资源
DeleteObject(rgn1);
DeleteObject(rgn2);
DeleteObject(rgn);
// 取消之前设置的裁剪区
// setcliprgn(NULL);
// 初始化所有星星
for (int i = 0; i < MAXSTAR; i++)
{
InitStar(i);
star[i].x = rand() % 640;
}
// 绘制星空,按任意键退出
while (!_kbhit())
{
for (int i = 0; i < MAXSTAR; i++)
MoveStar(i);
Sleep(20);
}
_getch();
closegraph(); // 关闭绘图窗口
}
int main()
{
void Stars();
void IceWorld();
initgraph(640,480);
IceWorld();
Stars();
}