带一盏油灯去巡视仓库
2013-11-11 ~ 2021-4-3
(0)
今天是 2013 年光棍节,写个程序庆祝一下,呵呵。
本程序模拟了这样一个场景:一个空地上乱七八糟地堆了一些货物,一个孤独的仓库管理员,带了一盏油灯,去巡视这些货物。
在鼠标的位置会亮起一盏油灯,随着鼠标的移动,部分光线会被仓库的货物遮挡。
就不抓图了,有兴趣的运行一下代码看看效果吧,【点这里下载编译后的 exe 文件】。
以下是全部源代码:
/////////////////////////////////////////////////////////
// 程序名称:带一盏油灯去巡视仓库
// 编译环境:Visual C++ 6.0 / 2010,EasyX 2013霜降版
// 作 者:yangw80 <http://hi.baidu.com/yangw80>
// 最后修改:2013-11-11
//
#include <graphics.h>
#include <conio.h>
#include <math.h>
#define RANGE 80 // 灯光照射半径
#define WIDTH 320 // 场景宽度
#define HEIGHT 240 // 场景高度
#define ZOOM 2 // 显示时的缩放倍数
#define PI 3.1415926536 // 圆周率
DWORD* g_bufMask; // 指向“建筑物”IMAGE 的指针
DWORD* g_bufRender; // 指向渲染 IMAGE 的指针
// 创建“仓库”
void MakeMask()
{
// 创建“仓库” IMAGE 对象
static IMAGE g_imgMask(WIDTH, HEIGHT);
g_bufMask = GetImageBuffer(&g_imgMask);
// 设置绘图目标
SetWorkingImage(&g_imgMask);
// 绘制“仓库”
settextstyle(100, 0, _T("Courier"));
outtextxy(8, 60, _T("EasyX"));
// 恢复绘图目标为默认窗口
SetWorkingImage(NULL);
}
// 在指定位置“照明”
void Lighting(int _x, int _y)
{
int i; // 定义循环变量
// 清空 Render 对象
memset(g_bufRender, 0, WIDTH * HEIGHT * 4);
// 计算灯光照亮的区域
for(double a = 0; a < 2 * PI; a += PI / 180) // 圆周循环
{
for(int r = 0; r < RANGE; r++) // 半径循环
{
// 计算照射到的位置
int x = (int)(_x + cos(a) * r);
int y = (int)(_y + sin(a) * r);
// 光线超出屏幕范围,终止
// (为了简化全凭模糊运算,不处理最上和最下一行)
if (x < 0 || x >= WIDTH || y <= 0 || y >= HEIGHT - 1)
break;
// 光线碰到建筑物,终止
if(g_bufMask[y * WIDTH + x])
break;
// 光线叠加
g_bufRender[y * WIDTH + x] += 0x101000; // 0x101000 是很淡的黄色
}
}
// 修正曝光过度的点
for (i = WIDTH * HEIGHT - 1; i >= 0; i--)
if (g_bufRender[i] > 0xffff00)
g_bufRender[i] = 0xffff00;
// 将光线模糊处理(避开建筑物)
for(i = WIDTH; i < WIDTH * (HEIGHT-1); i++)
if (!g_bufMask[i])
for (int j = 0; j < 2; j++)
{
g_bufRender[i] = RGB(
(GetRValue(g_bufRender[i - WIDTH]) + GetRValue(g_bufRender[i - 1]) + GetRValue(g_bufRender[i])
+ GetRValue(g_bufRender[i + 1]) + GetRValue(g_bufRender[i + WIDTH])) / 5,
(GetGValue(g_bufRender[i - WIDTH]) + GetGValue(g_bufRender[i - 1]) + GetGValue(g_bufRender[i])
+ GetGValue(g_bufRender[i + 1]) + GetGValue(g_bufRender[i + WIDTH])) / 5,
(GetBValue(g_bufRender[i - WIDTH]) + GetBValue(g_bufRender[i - 1]) + GetBValue(g_bufRender[i])
+ GetBValue(g_bufRender[i + 1]) + GetBValue(g_bufRender[i + WIDTH])) / 5);
}
}
// 主函数
void main()
{
// 初始化绘图窗口
initgraph(WIDTH * ZOOM, HEIGHT * ZOOM);
BeginBatchDraw();
DWORD* bufScreen = GetImageBuffer(NULL);
// 制作建筑
MakeMask();
// 创建渲染对象
IMAGE imgRender(WIDTH, HEIGHT);
g_bufRender = GetImageBuffer(&imgRender);
// 定义鼠标消息变量
MOUSEMSG msg;
while(true)
{
// 获取一条鼠标移动的消息
do
{
msg = GetMouseMsg();
}
while((msg.uMsg != WM_MOUSEMOVE) || MouseHit());
// 在鼠标位置模拟灯光
Lighting(msg.x / ZOOM, msg.y / ZOOM);
// 将渲染的内容拉伸后显示在绘图窗口中
int ps = 0, pr = 0;
for (int y = 0; y < HEIGHT; y++)
for (int x = 0; x < WIDTH; x++, pr++)
{
ps = y* ZOOM * WIDTH * ZOOM + x * ZOOM;
for (int zy = 0; zy < ZOOM; zy++)
{
for (int zx = 0; zx < ZOOM; zx++)
bufScreen[ps++] = g_bufRender[pr];
ps += ZOOM * (WIDTH - 1);
}
}
// 刷新显示,并延时
FlushBatchDraw();
Sleep(20);
// 按任意键退出
if (_kbhit())
{
EndBatchDraw();
closegraph();
}
}
}
添加评论
取消回复