EasyX小游戏源代码

 

EasyX插件下载地址:www.easyx.cn,点击右上角下载

实例来自:https://www.easyx.cn/samples/

1.贪吃蛇

///
// 程序名称:贪吃蛇
// 编译环境:Visual C++ 6.0 / 2008,EasyX 2013冬至版
// 最后修改:2014-5-20
// 操作方式:以蛇为第一视角,左 左转;右 右转;下 暂停;上 快进。
// 状态: 黄色 蛇头;红色 蛇身;绿色 食物。
#include <graphics.h>
#include <string.h>
#include <time.h>
#define NUM_R 10		//半径
#define NUM_X 25		//横向个数
#define NUM_Y 25		//纵向个数
#define NUM 30			//所需节点个数
void exe(int x,int y,int f);
int  GetCommand();
void eat(int x,int y);
void clear();
void set();
void flush();
void over(bool a);

struct pos				//建立链表储存每个关节的位置
{
	int x;
	int y;
	struct pos*next;
};
struct pos*head=(pos*)malloc(sizeof(pos));	//建立头指针
int n=0;				//记录节点个数

void main()				//初始化游戏
{
	int x,y,f;			//储存初始化点的位置方向
	srand((unsigned) time(NULL));			//初始化随机库
	do 
	{
		x=rand()%NUM_X*NUM_R*2+NUM_R;
		y=rand()%NUM_Y*NUM_R*2+NUM_R;
	} while(x<4*NUM_R || y<4*NUM_R || 2*NUM_R*(NUM_X-2)<x || 2*NUM_R*(NUM_Y-2)<y);		//产生不在矩形边缘的初始点
	f=rand()%4;										//随机方向
	struct pos*a=(pos*)malloc(sizeof(pos)),*p=head; //建立链表第一个节点
	a->x=x;					//指针a储存第一个点数据
	a->y=y;
	head->next=a;			//接链
	a->next=NULL;			//结尾
	initgraph(2*NUM_R*NUM_X,2*NUM_R*NUM_Y+50);		//初始绘图窗口
	setcolor(WHITE);
	line(0,2*NUM_R*NUM_Y+1,2*NUM_R*NUM_X,2*NUM_R*NUM_Y+1);
	setcolor(getbkcolor());	//取消圆的边缘
	setfillcolor(YELLOW);	//设置填充颜色
	fillcircle(x,y,NUM_R);	//绘出初始点
	set();					//产生食物
	exe(x,y,f);				//进入控制函数
}

void exe(int x,int y,int f)			//操作游戏
{
	int xf,yf,c,i;
	while(1)						//进入循环
	{
		c=0;						//初始化方向
		for(i=0;i<5;i++)			//循环5次获取命令
		{
			Sleep(100-50*n/NUM);	//等待
			if(c==0)				//若没获取到命令就进行获取
			{	
				c=GetCommand();
				if(c==4)			//返回4时退出循环等待
					break;
			}
		}
		f=f+c;						//改变方向
		if(f>3)						//溢出处理
			f=f-4;	
		xf=yf=0;					//初始化方向参数
		switch(f)
		{
		case 0:xf=1;break;			//方向向右时 x坐标增加
		case 1:yf=1;break;			//方向向右时 y坐标增加
		case 2:xf=-1;break;			//方向向右时 x坐标减少
		case 3:yf=-1;break;			//方向向右时 y坐标减少
		}
		x=x+2*NUM_R*xf;				//x坐标变化
		y=y+2*NUM_R*yf;				//y坐标变化
		if(getpixel(x,y)==RED || x<0 || y<0 || 2*NUM_X*NUM_R<x || 2*NUM_Y*NUM_R<y)		//判断是否遇到自身或碰到边界
			over(0);					//结束游戏
		else							//不结束进行下步运算
		{	
			if(getpixel(x,y)==GREEN)	//判断前方是否为食物
				set();					//产生新食物
			else                      
				clear();				//清除尾结点
			eat(x,y);					//在前方生成新结点
			if(n>NUM-1)					//判断胜利条件
				over(1);				//结束游戏
		}
	}
}

int GetCommand()				//获取方向
{
	int c=0;					//初始化方向变量
	if(GetAsyncKeyState(VK_RIGHT) & 0x8000)	c = 1;		//右转为1
	if(GetAsyncKeyState(VK_LEFT) & 0x8000)	c = 3;		//左转为3
	if(GetAsyncKeyState(VK_UP) & 0x8000)	c = 4;		//按上为4 快进
	if(GetAsyncKeyState(VK_DOWN) & 0x8000)	system("pause");	//按下则暂停
	return c;
}

void eat(int x,int y)				//增加新结点
{
	struct pos*a=(pos*)malloc(sizeof(pos)),*p=head;		//声明指针变量
	while(p->next!=NULL)			//寻找链表尾节点
		p=p->next;
	a->x=x;							//把数据储存到结点
	a->y=y;
	p->next=a;						//指针a接到尾节点后
	a->next=NULL;					//结尾
	setcolor(getbkcolor());			//取消圆的边缘
	setfillcolor(RED);				//设置填充颜色
	fillcircle(p->x,p->y,NUM_R);	//绘制新结点
	setfillcolor(YELLOW);			//设置填充颜色
	fillcircle(x,y,NUM_R);			//绘制新结点
}

void clear()							//清除尾结点
{
	setcolor(getbkcolor());				//取消圆的边缘
	setfillcolor(getbkcolor());			//设置填充颜色
	fillcircle(head->next->x,head->next->y,NUM_R);    //擦除结点
	head->next=head->next->next;		//删除节点数据
}

void set()			//产生食物和胜利判断
{	
	flush();			
	int x,y;		//声明变量
	do 
	{
		x=rand()%NUM_X*NUM_R*2+NUM_R;
		y=rand()%NUM_Y*NUM_R*2+NUM_R;
	} while (getpixel(x,y)==RED);		//随机产生食物在非蛇的位置
	setcolor(getbkcolor());
	setfillcolor(GREEN);				//设置填充颜色
	fillcircle(x,y,NUM_R);				//产生食物
}

void flush()
{
	n++;			//节点计数累加
	char strnum[20],string[10]="进度:";
	itoa(n,strnum,10);					//转换
	strcat(string,strnum);				//链接
	strcpy(strnum,"/");					//赋值
	strcat(string,strnum);				//连接
	itoa(NUM,strnum,10);
	strcat(string,strnum);
	setcolor(WHITE);
	settextstyle(32,0,_T("宋体"));		//设置字体类型
	outtextxy(20,2*NUM_R*NUM_Y+2,"          ");
	outtextxy(20,2*NUM_R*NUM_Y+2,string);
}

void over(bool a)						//结束游戏
{
	setcolor(WHITE);                    //设置字体颜色
	settextstyle(48,0,_T("宋体"));		//设置字体类型
	if(a)								//判断条件
		outtextxy(NUM_X*NUM_R-20,NUM_Y*NUM_R-20,"胜利");		//输出结果
	else
		outtextxy(NUM_X*NUM_R-20,NUM_Y*NUM_R-20,"失败");		//输出结果
	Sleep(2000);
	system("pause");
	exit(0);
}

2.矿井逃生

///
// 程序名称:矿井逃生
// 编译环境:Visual C++ 6.0 / 2010,EasyX 2013霜降版
// 最后修改:2013-11-15
//
#include <easyx.h>
#include <time.h>
#include <math.h>
#include <stdio.h>

// 定义常量
#define PI			3.141592653589		// 圆周率
#define UNIT_GROUND	0					// 表示地面
#define UNIT_WALL	1					// 表示墙
#define LIGHT_A		PI / 3				// 灯光的角度范围
#define	LIGHT_R		120					// 灯光的照射距离
#define	WIDTH		480					// 矿井的宽度
#define	HEIGHT		480					// 矿井的高度
#define SCREENWIDTH	640					// 屏幕宽度
#define	SCREENHEIGHT 480				// 屏幕高度
#define	UNIT		20					// 每个墙壁单位的大小
#define PLAYER_R	5					// 游戏者的半径

// 定义常量
const	SIZE	g_utMap = {23, 23};		// 矿井地图的尺寸(基于 UNIT 单位)
const	POINT	g_utPlayer = {1, 1};	// 游戏者的位置(基于 UNIT 单位)
const	POINT	g_utExit = {21, 22};	// 出口位置(基于 UNIT 单位)
const	POINT	g_ptOffset = {10, 10};	// 矿井显示在屏幕上的偏移量

//
// 定义全局变量
//
POINT	g_ptPlayer;						// 游戏者的位置
POINT	g_ptMouse;						// 鼠标位置
IMAGE	g_imgMap(WIDTH, HEIGHT);		// 矿井平面图
DWORD*	g_bufMap;						// 矿井平面图的显存指针
IMAGE	g_imgRender(WIDTH, HEIGHT);		// 渲染
DWORD*	g_bufRender;					// 渲染的显存指针
DWORD*	g_bufScreen;					// 屏幕的显存指针

// 枚举用户的控制命令
enum CMD { CMD_QUIT = 1, CMD_UP = 2, CMD_DOWN = 4, CMD_LEFT = 8, CMD_RIGHT = 16, CMD_RESTART = 32 };



//
// 函数声明
//

// 初始化
void	Welcome();									// 绘制游戏界面
void	ReadyGo();									// 准备开始游戏
void	InitGame();									// 初始化游戏数据

// 矿井生成
void	MakeMaze(int width, int height);			// 初始化(注:宽高必须是奇数)
void	TravelMaze(int x, int y, BYTE** aryMap);	// 遍历 (x, y) 四周
void	DrawWall(int x, int y, bool left, bool top, bool right, bool bottom);
													// 画一面墙
// 绘制
void	Paint();									// 绘制视野范围内的矿井
void	Lighting(int _x, int _y, double _a);		// 在指定位置和角度“照明”
void	DrawPlayer();								// 绘制游戏者
void	DrawExit();									// 绘制出口

// 处理用户控制
int		GetCmd();									// 获取用户输入的命令
void	OnUp();										// 向上移动
void	OnLeft();									// 向左移动
void	OnRight();									// 向右移动
void	OnDown();									// 向下移动
bool	CheckWin();									// 检查是否到出口



//
// 函数定义
//

// 主程序
void main()
{
	// 初始化
	initgraph(SCREENWIDTH, SCREENHEIGHT);		// 创建绘图窗口
	srand((unsigned)time(NULL));				// 设置随机种子
	
	// 显示主界面
	Welcome();

	// 游戏过程
	int c;
	do
	{
		ReadyGo();

		while(true)
		{
			// 获得用户输入
			c = GetCmd();

			// 处理用户输入
			if (c & CMD_UP)			OnUp();
			if (c & CMD_DOWN)		OnDown();
			if (c & CMD_LEFT)		OnLeft();
			if (c & CMD_RIGHT)		OnRight();
			if (c & CMD_RESTART)
			{
				if (MessageBox(GetHWnd(), _T("您要重来一局吗?"), _T("询问"), MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
					break;
			}
			if (c & CMD_QUIT)
			{
				if (MessageBox(GetHWnd(), _T("您确定要退出游戏吗?"), _T("询问"), MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
					break;
			}

			// 绘制场景
			Paint();

			// 判断是否走出矿井
			if (CheckWin())
			{
				// 是否再来一局
				HWND hwnd = GetHWnd();
				if (MessageBox(hwnd, _T("恭喜你走出来了!\n您想再来一局吗?"), _T("恭喜"), MB_YESNO | MB_ICONQUESTION) != IDYES)
					c = CMD_QUIT;

				break;
			}

			// 延时
			Sleep(16);
		}

	}
	while(!(c & CMD_QUIT));

	// 关闭图形模式
	closegraph();
}


// 准备开始游戏
void ReadyGo()
{
	// 初始化
	InitGame();

	// 停电前兆
	int time[7] = {1000, 50, 500, 50, 50, 50, 50};
	int i, x, y;
	for (i = 0; i < 7; i++)
	{
		if (i % 2 == 0)
		{
			putimage(0, 0, &g_imgMap);
			DrawPlayer();
			DrawExit();
		}
		else
			clearrectangle(0, 0, WIDTH - 1, HEIGHT - 1);
		Sleep(time[i]);
	}
	// 电力缓慢中断
	for (i = 255; i >= 0; i -= 5)
	{
		for (y = (HEIGHT - 1) * SCREENWIDTH; y >= 0; y -= SCREENWIDTH)
			for (x = 0; x < WIDTH; x++)
				if (g_bufScreen[y + x] != 0)
					g_bufScreen[y + x] = g_bufScreen[y + x] - 0x050505;

		FlushBatchDraw();
		DrawPlayer();
		DrawExit();
		Sleep(50);
	}

	// 绘制游戏区
	Paint();
}


// 绘制游戏界面
void Welcome()
{
	setfillcolor(DARKGRAY);
	solidrectangle(WIDTH, 0, SCREENWIDTH - 1, SCREENHEIGHT - 1);

	// 设置字体样式
	settextcolor(WHITE);
	setbkmode(TRANSPARENT);

	// 绘制标题
	settextstyle(24, 0, _T("宋体"));
	outtextxy(512, 40, _T("矿井逃生"));

	// 绘制操作说明
	RECT r = {488, 100, 632, 470};
	settextstyle(12, 0, _T("宋体"));
	drawtext(_T("[游戏说明]\n  矿井里的电路又出问题了。迅速借助你的头灯,在漆黑的矿井里\
		找到出口逃出去吧。\n\n[控制说明]\n方向键: 移动\nA/S/D/W:移动\n鼠标:  控制照射\
		方向\nF2:   重来一局\nESC:  退出游戏"), &r, DT_WORDBREAK);
	outtextxy(495, 465, _T("Powered by yw80@qq.com"));
}


// 初始化游戏数据
void InitGame()
{
	// 获得窗口显存指针
	g_bufRender = GetImageBuffer(&g_imgRender);
	g_bufMap = GetImageBuffer(&g_imgMap);
	g_bufScreen = GetImageBuffer(NULL);

	// 设置 Render 环境
	SetWorkingImage(&g_imgRender);
	setbkmode(TRANSPARENT);
	SetWorkingImage(NULL);

	// 创建矿井
	MakeMaze(g_utMap.cx, g_utMap.cy);

	// 设置游戏者位置
	g_ptPlayer.x = g_utPlayer.x * UNIT + UNIT / 2 + g_ptOffset.x;
	g_ptPlayer.y = g_utPlayer.y * UNIT + UNIT / 2 + g_ptOffset.y;
}


// 生成矿井:初始化(注:宽高必须是奇数)
void MakeMaze(int width, int height)
{
	if (width % 2 != 1 || height % 2 != 1)
		return;

	int x, y;

	// 定义矿井二维数组,并初始化全部为墙壁
	// 宽高比实际多 2,是因为两端各有一个“哨兵”,用于方便处理数据
	BYTE** aryMap = new BYTE*[width + 2];
	for(x = 0; x < width + 2; x++)
	{
		aryMap[x] = new BYTE[height + 2];
		memset(aryMap[x], UNIT_WALL, height + 2);
	}

	// 定义边界(哨兵功能)
	for (x = 0; x <= width + 1; x++)
		aryMap[x][0] = aryMap[x][height + 1] = UNIT_GROUND;
	for (y = 1; y <= height; y++)
		aryMap[0][y] = aryMap[width + 1][y] = UNIT_GROUND;

	// 从任意点开始遍历生成矿井
	TravelMaze(((rand() % (width - 1)) & 0xfffe) + 2, ((rand() % (height - 1)) & 0xfffe) + 2, aryMap);

	// 设置出口
	aryMap[g_utExit.x + 1][g_utExit.y + 1] = UNIT_GROUND;

	// 将矿井绘制在 IMAGE 对象上
	SetWorkingImage(&g_imgMap);
	cleardevice();
	for (y = 1; y <= height; y++)
		for (x = 1; x <= width; x++)
			if (aryMap[x][y] == UNIT_WALL)
				DrawWall(x, y,  aryMap[x - 1][y] == UNIT_WALL,
								aryMap[x][y - 1] == UNIT_WALL,
								aryMap[x + 1][y] == UNIT_WALL,
								aryMap[x][y + 1] == UNIT_WALL);
	SetWorkingImage(NULL);
}


// 生成矿井:遍历 (x, y) 四周
void TravelMaze(int x, int y, BYTE** aryMap)
{
	// 定义遍历方向
	int d[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
	
	// 将遍历方向乱序
	int n, t, i;
	for(i = 0; i < 4; i++)
	{
		n = rand() % 4;
		t = d[i][0], d[i][0] = d[n][0], d[n][0] = t;
		t = d[i][1], d[i][1] = d[n][1], d[n][1] = t;
	}
	
	// 尝试周围四个方向
	aryMap[x][y] = UNIT_GROUND;
	for(i = 0; i < 4; i++)
		if (aryMap[x + 2 * d[i][0]][y + 2 * d[i][1]] == UNIT_WALL)
		{
			aryMap[x + d[i][0]][y + d[i][1]] = UNIT_GROUND;
			TravelMaze(x + d[i][0] * 2, y + d[i][1] * 2, aryMap);		// 递归
		}
}


// 生成矿井:画一面墙
// 参数:left/top/right/bottom 表示墙壁是否与旁边连接
void DrawWall(int x, int y, bool left, bool top, bool right, bool bottom)
{
	// 墙壁厚 4 pixel
	int cx, cy;
	cx = x * UNIT - UNIT / 2 - 2 + 10;
	cy = y * UNIT - UNIT / 2 - 2 + 10;
	if (left)	solidrectangle(x * UNIT - UNIT + 10, cy, cx + 4, cy + 4);
	if (top)	solidrectangle(cx, y * UNIT - UNIT + 10, cx + 4, cy + 4);
	if (right)	solidrectangle(cx, cy, x * UNIT + 9, cy + 4);
	if (bottom)	solidrectangle(cx, cy, cx + 4, y * UNIT + 9);
}


// 绘制视野范围内的矿井
void Paint()
{
	// 设置绘图目标为 Render 对象
	SetWorkingImage(&g_imgRender);

	// 清空 Render 对象
	cleardevice();

	// 计算视野角度
	double dx, dy, a;
	dx = g_ptMouse.x - g_ptPlayer.x;
	dy = g_ptMouse.y - g_ptPlayer.y;
	if (dx == 0 && dy == 0)
		a = 0;
	else if (dx != 0 && dy != 0)
		a = atan(dy / dx);
	else if (dx == 0)
		a = (dy > 0) ? PI / 2 : PI * 3 / 2;
	else
		a = 0;
	if (dx < 0)	a += PI;
	if (a < 0) a += PI * 2;

	// 绘制灯光
	Lighting(g_ptPlayer.x, g_ptPlayer.y, a);

	// 画游戏者
	DrawPlayer();

	// 画出口
	DrawExit();

	// 设置绘图目标为窗口
	SetWorkingImage(NULL);
	
	// 显示到窗口上
	putimage(0, 0, &g_imgRender);
}


// 在指定位置和角度“照明”
void Lighting(int _x, int _y, double _a)
{
	int i;		// 定义循环变量
	int x, y;	// 定义临时坐标
	double a;	// 定义临时角度

	// 计算灯光照亮的角度区域
	double a1 = _a - LIGHT_A / 2;
	double a2 = _a + LIGHT_A / 2;
	for(a = a1; a < a2; a += PI / 360)					// 扇形循环
	{
		for(int r = 0; r < LIGHT_R; r++)				// 半径循环
		{
			// 计算照射到的位置
			x = (int)(_x + cos(a) * r);
			y = (int)(_y + sin(a) * r);

			// 光线超出屏幕范围,终止
			// (为了简化全凭模糊运算,不处理最上和最下一行)
			if (x < 0 || x >= WIDTH || y <= 0 || y >= HEIGHT - 1)
				break;

			// 光线碰到建筑物,终止
			if(g_bufMap[y * WIDTH + x])
				break;

			// 光线叠加
			g_bufRender[y * WIDTH + x] += 0x202000;		// 0x202000 是很淡的黄色
		}
	}

	// 计算光照扇形区域的最小包围矩形
	// 方法:获得 7 个点的最值:圆心、圆弧两端、圆与 xy 轴的 4 个交点
	// 第一步:初始化 7 个点
	POINT pt[7];
	pt[0].x = _x;									pt[0].y = _y;
	pt[1].x = int(_x + LIGHT_R * cos(a1) + 0.5);	pt[1].y = int(_y + LIGHT_R * sin(a1) + 0.5);
	pt[2].x = int(_x + LIGHT_R * cos(a2) + 0.5);	pt[2].y = int(_y + LIGHT_R * sin(a2) + 0.5);

	for (a = ceil(a1 * 4 / (2 * PI)) * (PI / 2), i = 3; a < a2; a += PI / 2, i++)
	{
		pt[i].x = int(_x + LIGHT_R * cos(a) + 0.5);
		pt[i].y = int(_y + LIGHT_R * sin(a) + 0.5);
	}

	// 第二步:获取 7 个点的最大最小值,得到最小包围矩形
	i--;
	RECT r = {pt[i].x, pt[i].y, pt[i].x, pt[i].y};

	for (--i; i >= 0; i--)
	{
		if (pt[i].x < r.left)	r.left = pt[i].x;
		if (pt[i].x > r.right)	r.right = pt[i].x;
		if (pt[i].y < r.top)	r.top = pt[i].y;
		if (pt[i].y > r.bottom)	r.bottom = pt[i].y;
	}

	// 调整矩形范围
	if (r.left < 0)				r.left	= 0;
	if (r.top < 1)				r.top	= 1;
	if (r.right >= WIDTH)		r.right	= WIDTH - 1;
	if (r.bottom >= HEIGHT - 1)	r.bottom = HEIGHT - 2;

	// 修正曝光过度的点
	for (y = r.top; y <= r.bottom; y++)
		for (x = r.left; x <= r.right; x++)
		{
			i = y * WIDTH + x;
			if (g_bufRender[i] > 0xffff00)
				g_bufRender[i] = 0xffff00;
		}

	// 将光线模糊处理(避开建筑物)
	for (y = r.top; y <= r.bottom; y++)
		for (x = r.left; x <= r.right; x++)
		{
			i = y * WIDTH + x;
			if (!g_bufMap[i])
				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 DrawPlayer()
{
	// 画安全帽
	setlinecolor(DARKGRAY);
	circle(g_ptPlayer.x, g_ptPlayer.y, 5);
}


// 绘制出口
void DrawExit()
{
	settextstyle(12, 0, _T("宋体"));
	outtextxy(g_utExit.x * UNIT + g_ptOffset.x, g_utExit.y * UNIT + g_ptOffset.y + 8, _T("出口"));
}


// 获取用户输入的命令
int GetCmd()
{
	int c = 0;

	if ((GetAsyncKeyState(VK_LEFT)	& 0x8000) ||
		(GetAsyncKeyState('A')		& 0x8000))		c |= CMD_LEFT;
	if ((GetAsyncKeyState(VK_RIGHT)	& 0x8000) ||
		(GetAsyncKeyState('D')		& 0x8000))		c |= CMD_RIGHT;
	if ((GetAsyncKeyState(VK_UP)	& 0x8000) ||
		(GetAsyncKeyState('W')		& 0x8000))		c |= CMD_UP;
	if ((GetAsyncKeyState(VK_DOWN)	& 0x8000) ||
		(GetAsyncKeyState('S')		& 0x8000))		c |= CMD_DOWN;
	if (GetAsyncKeyState(VK_F2)		& 0x8000)		c |= CMD_RESTART;
	if (GetAsyncKeyState(VK_ESCAPE)	& 0x8000)		c |= CMD_QUIT;

	MOUSEMSG m;
	while(MouseHit())
	{
		m = GetMouseMsg();
		g_ptMouse.x = m.x;
		g_ptMouse.y = m.y;
	}

	return c;
}


// 向上移动
void OnUp()
{
	int i = (g_ptPlayer.y - 6) * WIDTH + (g_ptPlayer.x - 5) + 1;
	int j;
	for (j = 0; j < 5; j++, i += 2)
		if (g_bufMap[i])
			break;

	if (j == 5)
		g_ptPlayer.y--;
}


// 向左移动
void OnLeft()
{
	int i = (g_ptPlayer.y - 5) * WIDTH + (g_ptPlayer.x - 5);
	int j;
	for (j = 0; j < 5; j++, i += WIDTH)
		if (g_bufMap[i])
			break;

	if (j == 5)
		g_ptPlayer.x--;
}


// 向右移动
void OnRight()
{
	int i = (g_ptPlayer.y - 5) * WIDTH + (g_ptPlayer.x + 5) + 1;
	int j;
	for (j = 0; j < 5; j++, i += WIDTH)
		if (g_bufMap[i])
			break;

	if (j == 5)
		g_ptPlayer.x++;
}


// 向下移动
void OnDown()
{
	int i = (g_ptPlayer.y + 5) * WIDTH + (g_ptPlayer.x - 5) + 1;
	int j;
	for (j = 0; j < 5; j++, i += 2)
		if (g_bufMap[i])
			break;

	if (j == 5)
		g_ptPlayer.y++;
}


// 检查是否到出口
bool CheckWin()
{
	return (g_ptPlayer.y >= g_utExit.y * UNIT + UNIT / 2 + g_ptOffset.y);
}

3.带一盏油灯去巡视仓库

/
// 程序名称:带一盏油灯去巡视仓库
// 编译环境:Visual C++ 6.0 / 2010,EasyX 2013霜降版
// 最后修改: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();
		}
	}
}

 


版权声明:本文为qq_33204709原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。