1. 程式人生 > >EasyX小遊戲原始碼

EasyX小遊戲原始碼

EasyX外掛下載地址:www.easyx.cn,點選右上角下載

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 
[email protected]
")); } // 初始化遊戲資料 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();
		}
	}
}