国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于C++的簡易版《球球大作戰(zhàn)》游戲設計

這篇具有很好參考價值的文章主要介紹了基于C++的簡易版《球球大作戰(zhàn)》游戲設計。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

全套資料下載地址:https://download.csdn.net/download/sheziqiong/85602628

全套資料下載地址:https://download.csdn.net/download/sheziqiong/85602628

1 引言

《球球大作戰(zhàn)》雖然在玩法上類似于大球吃小球的模式看起來很單薄。但是在游戲過程中會出現(xiàn)無數種意外情況,這就需要玩家運用一系列策略來達到不被吃和吃掉別人球的目的,大大增加了游戲的耐玩性。游戲徹底拋棄了枯燥無味的單機模式,采取全球玩家聯(lián)網實時對戰(zhàn)。當競技在PC端打的火熱的時候,《球球大作戰(zhàn)》率先引進了微競技的新模式,讓玩家在休閑的同時還能體驗到競技的樂趣,這種嘗試也博得了一片稱贊聲。

1.1 編寫目的

球球大作戰(zhàn)在在最近幾年風靡全球,其版本也在不斷迭代。本項目取其最核心的玩

法,給玩家一個最純粹的休閑游戲體驗。此外《球球大作戰(zhàn)(簡易版)》是基于Easyx圖形庫開發(fā)出來的,在用戶界面顯示方面表現(xiàn)良好,相信一定會給用戶一個不錯的游戲體驗。

1.2開發(fā)背景

《球球大作戰(zhàn)》是民族自研,積極健康休閑競技游戲的代表。輕快明亮的畫風、休閑有趣的玩法、富有深度的競技性,使其成為國產手游創(chuàng)新模范。作為目前最具人氣的移動電競游戲,《球球大作戰(zhàn)》累積用戶數已超過1.7億,最高同時在線人數突破175萬。月活躍用戶達到6000萬。年輕化也是《球球大作戰(zhàn)》的一大特色,朝氣活力的學生群體是游戲主力軍,95后及00后用戶占比極高。

1.3 可行性分析

1.3.1 經濟可行性

本項目是基于C語言開發(fā),開發(fā)平臺我們選擇Visual Studio 2017 Community,此版本為免費版,由Microsoft公司免費提供給開發(fā)者使用;主流的開發(fā)環(huán)境有Windows和Linux,我們選擇使用Windows進行開發(fā),因為Windows我們比較熟悉,方便我們快速入手項目開發(fā),所以需要一臺安裝了Windows操作系統(tǒng)的計算機;此外還使用了Easyx圖形庫,這個圖形庫也是免費提供給開發(fā)者使用和學習的。因此,總的經濟方面付出不高,故經濟可行性較高。

1.3.2 技術可行性

本項目大部分使用了C語言的語法,還使用少量的C++語法,調用了Easyx圖形庫。C語言方面,大部分知識是可以比較容易實現(xiàn)的,少部分通過翻書和查閱資料也是能夠實現(xiàn)的。C++方面的語法,我們則較為不熟悉,需要花費較多的時間去了解。

1.4 問題定義

完成一個簡易版的球球大作戰(zhàn)項目,如何實現(xiàn)大球吃小球的功能?如何實現(xiàn)小球的移動和地圖的刷新?如何實現(xiàn)游戲的暫停?等等…

2 需求分析

2.1 需求分析圖

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-m7OqYnwh-1645933074363)(img/structure.jpg)]

2.2 功能需求分析

1)地圖。利用easyx圖形庫生成一個適當大小的白色背景地圖,和在右上角生成一個淺灰色的小地圖用于顯示玩家和AI的縮略圖與位置。

2)文件存儲。利用文件操作存儲累計游戲次數和游戲時間。

3)玩家。初始化玩家球(包括坐標、生命值、顏色、大小、形狀)。

4)AI(機器人)。初始化AI,生成指定數量的AI,每個AI隨機坐標,生命值均為1,顏色隨機,大小固定與玩家相同,形狀為圓形。

5)生命。玩家和AI初始生命值均為1表示活,死后生命值變?yōu)?。

6)食物。隨機位置生成指定數量的食物,顏色隨機,大小在一定范圍內隨機,形狀為圓形、橢圓形、圓角矩形等隨機。

7)思路。玩家通過方向鍵控制球移動;大球吃小球,若a.r>b.r且a和b 圓心距d<a.r+b.r,則a.r = sqrt(a.ra.r + b.rb.r),b.r=0,b的生命變?yōu)?。所有AI的生命都變?yōu)?時,游戲結束,獲得勝利。

8)玩家如果被AI吃,玩家生命變?yōu)?,游戲結束,游戲失敗,顯示游戲累 計時間。

2.3 性能需求分析

1)性能:程序總體占用空間較小,響應時間較塊。

2)可修改性:程序代碼層次清晰,主要注釋均有,便于后期修改與維護。

3)可用性:程序目前為止尚未出現(xiàn)崩潰情況,可用性較高。

4)易用性:游戲規(guī)則簡單,即使是新手也能很快熟練的游戲。

3 概要設計

3.1 運行環(huán)境

3.1.1 Windows 10

Windows操作系統(tǒng)是最常見的計算機操作系統(tǒng),是微軟公司開發(fā)的操作軟件。該軟件經歷了多年的發(fā)展歷程,目前推出的win10系統(tǒng)相當成熟。Windows操作系統(tǒng)具有人機操作互動性好,支持應用軟件多,硬件適配性強等特點,未來該系統(tǒng)將更加安全、智能、易用。

操作系統(tǒng)是將人類利用計算機硬件發(fā)揮作用的平臺,是計算機軟件運行工作的環(huán)境,是計算機硬件的翻譯。從計算機誕生發(fā)展到今天,出現(xiàn)了相當多種類的操作系統(tǒng)。Windows操作系統(tǒng)是其中的佼佼者。Windows操作系統(tǒng)是美國微軟公司推出的一款操作系統(tǒng)。該系統(tǒng)從1985年誕生到現(xiàn)在,經過多年的發(fā)展完善,相對比較成熟穩(wěn)定,是當前個人計算機的主流操作系統(tǒng)。

3.2 開發(fā)平臺及技術基礎

3.2.1 Visual Studio 2017

Microsoft Visual Studio是VS的全稱。VS是美國微軟公司的開發(fā)工具包系列產品。VS是一個基本完整的開發(fā)工具集,它包括了整個軟件生命周期中所需要的大部分工具,如UML工具、代碼管控工具、集成開發(fā)環(huán)境(IDE)等等。所寫的目標代碼適用于微軟支持的所有平臺,包括Microsoft Windows、Windows Mobile、Windows CE、.NET Framework、.Net Core、.NET Compact Framework和Microsoft Silverlight 及Windows Phone。

Visual Studio是目前最流行的Windows平臺應用程序的集成開發(fā)環(huán)境。最新版本為 Visual Studio 2019版本,基于.NET Framework 4.7。

3.2.2 Easyx圖形庫

EasyX 是針對 C++ 的圖形庫,可以幫助 C 語言初學者快速上手圖形和游戲編程。比如,可以用 VC + EasyX 很快的用幾何圖形畫一個房子,或者一輛移動的小車,可以編寫俄羅斯方塊、貪吃蛇、黑白棋等小游戲,可以練習圖形學的各種算法,等等。

許多學編程的都是從 C 語言開始入門的,而目前的現(xiàn)狀是:

  • 有些學校以 Turbo C 為環(huán)境講 C 語言,只是 Turbo C 的環(huán)境實在太老了,復制粘貼都很不方便。

  • 有些學校直接拿 VC 來講 C 語言,因為 VC 的編輯和調試環(huán)境都很優(yōu)秀,并且 VC 有適合教學的免費版本??上г?VC 下只能做一些文字性的練習題,想畫條直線畫個圓都很難,還要注冊窗口類、建消息循環(huán)等等,初學者會受嚴重打擊的。初學編程想要繪圖就得用 TC,很是無奈。

  • 還有計算機圖形學,這門課程的重點是繪圖算法,而不是 Windows 編程。所以,許多老師不得不用 TC 教學,因為 Windows 繪圖太復雜了,會偏離教學的重點。新的圖形學的書有不少是用的 OpenGL,可是門檻依然很高。

所以,我們想給大家一個更好的學習平臺,就是 VC 方便的開發(fā)平臺和 TC 簡單的繪圖功能,于是就有了這個 EasyX 庫。如果您剛開始學 C 語言,或者您是一位教 C 語言的老師,再或者您在教計算機圖形學,那么這個庫一定會讓您興奮的。

3.3 基本設計概要及處理流程

3.3.1 基本設計概要
  1. 游戲主界面模塊

基于C++的簡易版《球球大作戰(zhàn)》游戲設計

  1. 游戲運行模塊

基于C++的簡易版《球球大作戰(zhàn)》游戲設計

  1. 游戲暫停模塊

基于C++的簡易版《球球大作戰(zhàn)》游戲設計

  1. 計時模塊

基于C++的簡易版《球球大作戰(zhàn)》游戲設計

3.3.2 流程處理(流程圖)

基于C++的簡易版《球球大作戰(zhàn)》游戲設計

3.4 結構圖

基于C++的簡易版《球球大作戰(zhàn)》游戲設計

4 詳細設計

4.1 功能模塊實現(xiàn)

4.1.1 程序運行次數和累計時間的存儲與讀寫

定義文件名:

#define FilePath1 "timeer.txt"
#define FilePath "counter.txt"

記錄游戲運行次數的文件讀寫:

int readCount() {
	FILE *fp;
	int count;
	if ((fp = fopen(FilePath, "r")) == NULL) {
		return 0;
	}
	else
		fscanf(fp, "%d", &count);
	fclose(fp);
	return count;
}

void writeCount(int count) {
	FILE *fp;
	if ((fp = fopen(FilePath, "w")) == NULL) {
		printf("無法創(chuàng)建數據文件:counter.txt。\n");
		return;
	}
	else
		fprintf(fp, "%d", count);
	fclose(fp);
}

記錄游戲累計時間的文件的讀寫:

int readTime() {
	FILE *fp1;
	int time;
	if ((fp1 = fopen(FilePath1, "r")) == NULL) {
		return 0;
	}
	else
		fscanf(fp1, "%d", &time);
	fclose(fp1);
	return time;
}

void writeTime(int time) {
	FILE *fp1;
	if ((fp1 = fopen(FilePath1, "w")) == NULL) {
		printf("無法創(chuàng)建數據文件:timeer.txt。\n");
		return;
	}
	else
		fprintf(fp1, "%d", time);
	fclose(fp1);
}

4.1.2 游戲難度的控制

通過改變移動速度增加難度:

void ChooseSpeed() {
	switch (getch()) {
	case 1:speed = 4;
	case 2:speed = 3;
	case 3:speed = 2;
	default:speed = 4;
	}
}
4.1.3 游戲運行時間的計算及其顯示

游戲累計時間的計算及顯示:

void starttime() {
	start_t = clock();
	writeCount(readCount() + 1);
}

void endtime() {
	closegraph();
	initgraph(WIDTH, HEIGHT);
	cleardevice();
	BeginBatchDraw();
	setbkcolor(WHITE);							// 白色背景
	cleardevice();								// 初始化背景
	settextcolor(BLACK);							// 改字體
	setbkmode(TRANSPARENT);
	end_t = clock();
	total_t = (end_t - start_t);
	IMAGE image;
	loadimage(&image, _T("../resourse/start.jpg"), WIDTH, HEIGHT);
	putimage(0, 0, &image);
	settextstyle(50, 0, _T("宋體"));
	setlinestyle(PS_NULL);
	TCHAR str[64];
	swprintf_s(str, _T("本次游戲時間:%d分%d秒"), total_t / 60000, total_t / 1000 - total_t / 60000 * 60);
	settextcolor(WHITE);							// 改字體
	outtextxy(20, 100, str);
	total_t = readTime() + total_t;
	writeTime(total_t);
	TCHAR str1[64];
	swprintf_s(str1, _T("您已累計游戲%d分%d秒"), total_t / 60000, total_t / 1000 - total_t / 60000 * 60);
	settextcolor(WHITE);							// 改字體
	outtextxy(20, 20, str1);
	settextstyle(20, 0, _T("宋體"));
	outtextxy(384, 550, _T("按任意鍵退出游戲"));
	FlushBatchDraw();
	getchar();
	closegraph();
	exit(1);		//考慮增加重新開始游戲
}
4.1.4 游戲結束的判定

通過life的值判斷是否結束游戲:

if (ball->r <= 0)
		ball->life = false;
	if (ball->life == false) {						// 判定游戲是否接束
		HWND hwnd = GetHWnd();
		MessageBox(hwnd, _T("你被吃了"), _T("游戲結束"), MB_ICONEXCLAMATION);
		endtime();

	}

	if (eaten + ai_eaten == AINUM)					// 是否吃掉所有 AI
	{
		HWND hwnd = GetHWnd();
		MessageBox(hwnd, _T("恭喜過關"), _T("游戲結束"), MB_OK | MB_ICONEXCLAMATION);	// 結束
		endtime();
	}
4.1.5 玩家的移動

向鍵控制移動:

	static int mx = 0, my = 0;						// 記錄偏移量

	if (GetAsyncKeyState(VK_UP) && (ball->y - ball->r > 0 && ball->y <= (MAPH - ball->r + 10))) {
		ball->y -= speed;
		my += speed;
	}
	if (GetAsyncKeyState(VK_DOWN) && (ball->y - ball->r >= -10 && ball->y < (MAPH - ball->r))) {
		ball->y += speed;
		my -= speed;
	}
	if (GetAsyncKeyState(VK_LEFT) && ball->x - ball->r > 0 && (ball->x <= (MAPW - ball->r + 10))) {
		ball->x -= speed;
		mx += speed;
	}
	if (GetAsyncKeyState(VK_RIGHT) && ball->x - ball->r >= -10 && (ball->x < (MAPW - ball->r))) {
		ball->x += speed;
		mx -= speed;
	}
4.1.6 游戲暫停

按空格鍵游戲暫停:

if (GetAsyncKeyState(VK_SPACE)) {
		settextcolor(WHITE);
		settextstyle(32, 0, _T("宋體"));
		outtextxy(384 - mx, 350 - my, _T("游戲已暫停!"));
		outtextxy(20 - mx, 500 - my, _T("(ESC)退出"));
		outtextxy(780 - mx, 500 - my, _T("(回車鍵)繼續(xù)"));
		FlushBatchDraw();
		getch();
		if (GetAsyncKeyState(VK_ESCAPE))
			exit(0);
		else
			getch();
	}

4.1.7 食物的生成

食物的隨機生成:

void Food() {
	for (int i = 0; i < FNUM; i++) {				// 食物刷新
		if (food[i].eat == 0) {
			food[i].eat = 1;
			food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
			food[i].x = rand() % MAPW;
			food[i].y = rand() % MAPH;
			food[i].type = rand() % 10 + 1;
		}
	}
}http://www.biyezuopin.vip

繪制食物:

for (int i = 0; i < FNUM; i++) {				// 畫出食物
		if (food[i].eat == 0) continue;
		setfillcolor(food[i].color);
		switch (food[i].type) {					// 形狀
		case 1:		solidellipse(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4); break;
		case 2:		solidellipse(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2);	break;
		case 3:		solidrectangle(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2); break;
		case 4:		solidrectangle(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4); break;
		case 5:		solidroundrect(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4, 2, 2); break;
		case 6:		solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 2, 2); break;
		case 7:		solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 4, 2); break;
		case 8:		solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 2, 4); break;
		case 9:		solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 1, 1); break;
		case 10:	fillcircle(food[i].x, food[i].y, 4); break;
		}
	}

4.2 重難點分析

4.2.1 時間的計算:調用“time.h”頭文件。

時間的計算:

	clock_t start_t, end_t;
	int total_t;
	...
	end_t = clock();
	total_t = (end_t - start_t);
	...
	total_t = readTime() + total_t;
	writeTime(total_t);
4.2.2 游戲結束的判斷:通過為生命賦值來解決,true表示存活,false表示死亡。

游戲結束的判斷:

if (ball->r <= 0)
		ball->life = false;
	if (ball->life == false) {						// 判定游戲是否接束
		HWND hwnd = GetHWnd();
		MessageBox(hwnd, _T("你被吃了"), _T("游戲結束"), MB_ICONEXCLAMATION);
		endtime();

	}
4.2.3 小地圖的繪制:調用了Easyx圖形庫里面的一些函數得到解決。

小地圖的繪制:

void draw() {
	clearcliprgn();
	IMAGE image;
	loadimage(&image, _T("../resourse/background.jpg"), WIDTH * 4, HEIGHT * 4);
	putimage(0, 0, &image);
	setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 20);		// 改變筆的顏色、狀態(tài)
	setlinecolor(RGB(0, 100, 0));
	line(-20, MAPH + 20, -20, -20);				// 左豎
	line(-20, MAPH + 20, MAPW + 20, MAPH + 20);		// 上橫
	line(-20, -20, MAPW + 20, -20);				// 下橫
	line(MAPW + 20, -20, MAPW + 20, MAPH + 20);		// 右豎
	setfillcolor(GREEN);

	if (mover.x - 0.5 * WIDTH / asp < -20)
		floodfill(-20 - 11, mover.y, RGB(0, 100, 0));
	if (mover.x + 0.5 * WIDTH / asp > MAPW + 20)
		floodfill(MAPW + 20 + 11, mover.y, RGB(0, 100, 0));
	if (mover.y - 0.5 * HEIGHT / asp < -20)
		floodfill(mover.x, -20 - 11, RGB(0, 100, 0));
	if (mover.y + 0.5 * HEIGHT / asp > MAPH + 20)
		floodfill(mover.x, MAPH + 20 + 11, RGB(0, 100, 0));

	setlinecolor(WHITE);
	setlinestyle(PS_NULL);

	for (int i = 0; i < FNUM; i++) {				// 畫出食物
		if (food[i].eat == 0) continue;
		setfillcolor(food[i].color);
		switch (food[i].type) {					// 形狀
		case 1:		solidellipse(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4); break;
		case 2:		solidellipse(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2);	break;
		case 3:		solidrectangle(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2); break;
		case 4:		solidrectangle(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4); break;
		case 5:		solidroundrect(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4, 2, 2); break;
		case 6:		solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 2, 2); break;
		case 7:		solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 4, 2); break;
		case 8:		solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 2, 4); break;
		case 9:		solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 1, 1); break;
		case 10:	fillcircle(food[i].x, food[i].y, 4); break;
		}
	}

	for (int i = 0; i < AINUM; i++) {				// 畫 AI
		if (ai[i].life == 0) continue;
		setfillcolor(ai[i].color);
		fillcircle(ai[i].x, ai[i].y, int(ai[i].r + 0.5));
	}

	setfillcolor(mover.color);						// 畫玩家
	fillcircle(mover.x, mover.y, int(mover.r + 0.5));

	IMAGE map(150, 100);							// 小地圖
	SetWorkingImage(&map);
	setbkcolor(RGB(120, 165, 209));					// 淺灰色背景
	cleardevice();
	for (int i = 0; i < AINUM; i++)				// 畫 AI(小地圖)
	{
		if (ai[i].life == 0) continue;
		setfillcolor(ai[i].color);
		fillcircle(ai[i].x * 150 / WIDTH / 4, ai[i].y * 100 / HEIGHT / 4, int(ai[i].r / 28 + 1.5));
	}

	setfillcolor(mover.color);						// 畫玩家(小地圖)
	fillcircle(mover.x * 150 / WIDTH / 4, mover.y * 100 / HEIGHT / 4, int(mover.r / 28 + 3.5));
	setlinecolor(RGB(0, 100, 0));

	SetWorkingImage();							// 恢復繪圖背景
	putimage(mover.x + int(0.5 * WIDTH) - 150, mover.y - int(0.5 * HEIGHT), 150, 100, &map, 0, 0);						// 畫出小地圖
	setlinecolor(LIGHTBLUE);
	setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 4);
	line(mover.x + int(0.5 * WIDTH) - 151, mover.y - int(0.5 * HEIGHT), mover.x + int(0.5 * WIDTH) - 151, mover.y - int(0.5 * HEIGHT) + 99);	// 地圖邊框線
	line(mover.x + int(0.5 * WIDTH) - 151, mover.y - int(0.5 * HEIGHT) + 99, mover.x + int(0.5 * WIDTH), mover.y - int(0.5 * HEIGHT) + 99);	// 地圖邊框線

	setlinestyle(PS_NULL);							// 恢復筆
	TCHAR str[32];
	swprintf_s(str, _T("質量:%.1fg  擊殺:%d"), mover.r, eaten);
	settextcolor(WHITE);							// 改字體
	outtextxy(mover.x - int(0.5 * WIDTH), mover.y - int(0.5 * HEIGHT), str);
	settextcolor(WHITE);
	outtextxy(mover.x - 20, mover.y, _T("user"));
}
4.2.4 AI的移動:相距最近的AI相互靠近。

AI的移動規(guī)則:

double min_DISTANCE = 100000;
		int min = -1;
		for (int k = 0; k < AINUM; k++) {			// AI 靠近 AI
			if (ai[i].r > ai[k].r&&ai[k].life != 0) {
				if (DISTANCE(ai[i].x, ai[i].y, ai[k].x, ai[k].y) < min_DISTANCE) {
					min_DISTANCE = DISTANCE(ai[i].x, ai[i].y, ai[k].x, ai[k].y);
					min = k;
				}
			}
		}
		if ((min != -1) && (rand() % 2 == 1)) {
			if (rand() % 2) {
				if (ai[i].x < ai[min].x)
					ai[i].x++;
				else
					ai[i].x--;
			}
			else {
				if (ai[i].y < ai[min].y)
					ai[i].y++;
				else
					ai[i].y--;
			}
		}

5 編碼與單元測試

5.1 編碼(完整代碼)

#include<stdio.h>
#include<conio.h>
#include<time.h>
#include<math.h>
#include<wchar.h>
#include<graphics.h>

#define WIDTH 1024								// 屏幕寬
#define HEIGHT 576								// 屏幕高
#define MAPW (WIDTH*4)								// 地圖寬
#define MAPH (HEIGHT*4)							// 地圖高
#define AINUM 100									// AI 數量
#define FNUM 2000									// FOOD 數量
#define DISTANCE(x1,y1,x2,y2)	(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)))		//計算距離

struct FOOD {
	bool eat;
	COLORREF color;								// 顏色
	int x, y;									// 坐標
	char type;
};

struct BALL {										//小球結構體
	bool life;									//生命
	COLORREF color;								//顏色
	int x, y;									//坐標
	float r;										//半徑
};

FOOD food[FNUM];									//食物
BALL mover = { 1,RGB(0,0,0),0,0,0 };				//玩家
BALL ai[AINUM] = { 1,RGB(0,0,0),0,0,0 };			//AI

void move(BALL* ball);								// 玩家移動
void draw();										// 繪圖
void start();										// 游戲開始
void setall();									// 初始化
void AI();										// AI
void Food();										// 食物
void delay(DWORD ms);								// 絕對延時

DWORD* pBuffer;									// 顯存指針
int eaten = 0;									// 吃 AI 的數量
int ai_eaten = 0;									// AI 吃 AI的數量
float asp = 1;									// 縮放因子
float Time = 0;									// 時間

int main() {
	initgraph(WIDTH, HEIGHT);
	start();
	setall();
	BeginBatchDraw();
	while (true) {
		move(&mover);
		AI();
		Food();
		draw();
		FlushBatchDraw();							// 顯示緩存的繪制內容
		delay(20);
	}
}

void move(BALL* ball) {
	if (ball->r <= 0)
		ball->life = false;
	if (ball->life == false) {						// 判定游戲是否接束
		HWND hwnd = GetHWnd();
		MessageBox(hwnd, _T("你被吃了"), _T("游戲結束"), MB_ICONEXCLAMATION);
		closegraph();
		exit(0);		//可以增加重新游戲功能
	}

	if (eaten + ai_eaten == AINUM)					// 是否吃掉所有 AI
	{
		HWND hwnd = GetHWnd();
		MessageBox(hwnd, _T("恭喜過關"), _T("游戲結束"), MB_OK | MB_ICONEXCLAMATION);	// 結束
		closegraph();
		exit(0);
	}

	for (int i = 0; i < AINUM; i++) {				// 玩家吃 AI 判定
		if (ball->r >= ai[i].r) {
			if (ai[i].life == 0)	continue;
			if (DISTANCE(ball->x, ball->y, ai[i].x, ai[i].y) < (4 / 5.0 * (ball->r + ai[i].r))) {
				ai[i].life = 0;					//AI被吃
				ball->r = sqrt(ai[i].r*ai[i].r + ball->r*ball->r);
				eaten++;
			}
		}
	}

	for (int n = 0; n < FNUM; n++) {				// 玩家吃食物
		if (food[n].eat == 0)	continue;
		if (DISTANCE(ball->x, ball->y, food[n].x, food[n].y) < ball->r) {
			ball->r += 4 / ball->r;				// 增加面積
			food[n].eat = 0;						// 食物被吃
		}
	}

	static int mx = 0, my = 0;						// 記錄偏移量

	if (GetAsyncKeyState(VK_UP) && (ball->y - ball->r > 0 && ball->y <= (MAPH - ball->r + 10))) {
		ball->y -= 4;
		my += 4;
	}
	if (GetAsyncKeyState(VK_DOWN) && (ball->y - ball->r >= -10 && ball->y < (MAPH - ball->r))) {
		ball->y += 4;
		my -= 4;
	}
	if (GetAsyncKeyState(VK_LEFT) && ball->x - ball->r > 0 && (ball->x <= (MAPW - ball->r + 10))) {
		ball->x -= 4;
		mx += 4;
	}
	if (GetAsyncKeyState(VK_RIGHT) && ball->x - ball->r >= -10 && (ball->x < (MAPW - ball->r))) {
		ball->x += 4;
		mx -= 4;
	}
	setorigin(mx, my);							//坐標修正
}


void AI() {
	for (int i = 0; i < AINUM; i++) {				// AI 吃玩家
		if (ai[i].r > mover.r) {
			if (DISTANCE(mover.x, mover.y, ai[i].x, ai[i].y) < (ai[i].r + mover.r)) {
				ai[i].r = sqrt(ai[i].r*ai[i].r + mover.r*mover.r);
				mover.life = 0;
				mover.r = 0;
			}
		}
		for (int j = 0; j < AINUM; j++) {			// AI 吃 AI
			if (ai[i].r > ai[j].r) {
				if (ai[j].life == 0) continue;
				if (DISTANCE(ai[i].x, ai[i].y, ai[j].x, ai[j].y) < (ai[i].r + ai[j].r)) {
					ai[i].r = sqrt(ai[i].r*ai[i].r + ai[j].r*ai[j].r);
					ai[j].life = 0;
					ai[j].r = 0;
					ai_eaten++;
				}
			}
		}

		double min_DISTANCE = 100000;
		int min = -1;
		for (int k = 0; k < AINUM; k++) {			// AI 靠近 AI
			if (ai[i].r > ai[k].r&&ai[k].life != 0) {
				if (DISTANCE(ai[i].x, ai[i].y, ai[k].x, ai[k].y) < min_DISTANCE) {
					min_DISTANCE = DISTANCE(ai[i].x, ai[i].y, ai[k].x, ai[k].y);
					min = k;
				}
			}
		}
		if ((min != -1) && (rand() % 2 == 1)) {
			if (rand() % 2) {
				if (ai[i].x < ai[min].x)
					ai[i].x++;
				else
					ai[i].x--;
			}
			else {
				if (ai[i].y < ai[min].y)
					ai[i].y++;
				else
					ai[i].y--;
			}
		}
		for (int n = 0; n < FNUM; n++) {			// AI 吃食物
			if (food[n].eat == 0) continue;
			if (DISTANCE(ai[i].x, ai[i].y, food[n].x, food[n].y) < ai[i].r) {
				ai[i].r += 4 / ai[i].r;
				food[n].eat = 0;
			}
		}
	}
}

void Food() {
	for (int i = 0; i < FNUM; i++) {				// 食物刷新
		if (food[i].eat == 0) {
			food[i].eat = 1;
			food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
			food[i].x = rand() % MAPW;
			food[i].y = rand() % MAPH;
			food[i].type = rand() % 10 + 1;
		}http://www.biyezuopin.vip
	}
}

void draw() {
	clearcliprgn();
	setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 20);		// 改變筆的顏色、狀態(tài)
	setlinecolor(RGB(0, 100, 0));
	line(-20, MAPH + 20, -20, -20);				// 左豎
	line(-20, MAPH + 20, MAPW + 20, MAPH + 20);		// 上橫
	line(-20, -20, MAPW + 20, -20);				// 下橫
	line(MAPW + 20, -20, MAPW + 20, MAPH + 20);		// 右豎
	setfillcolor(GREEN);

	if (mover.x - 0.5 * WIDTH / asp < -20)
		floodfill(-20 - 11, mover.y, RGB(0, 100, 0));
	if (mover.x + 0.5 * WIDTH / asp > MAPW + 20)
		floodfill(MAPW + 20 + 11, mover.y, RGB(0, 100, 0));
	if (mover.y - 0.5 * HEIGHT / asp < -20)
		floodfill(mover.x, -20 - 11, RGB(0, 100, 0));
	if (mover.y + 0.5 * HEIGHT / asp > MAPH + 20)
		floodfill(mover.x, MAPH + 20 + 11, RGB(0, 100, 0));

	setlinecolor(WHITE);
	setlinestyle(PS_NULL);

	for (int i = 0; i < FNUM; i++) {				// 畫出食物
		if (food[i].eat == 0) continue;
		setfillcolor(food[i].color);
		switch (food[i].type) {					// 形狀
		case 1:		solidellipse(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4); break;
		case 2:		solidellipse(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2);	break;
		case 3:		solidrectangle(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2); break;
		case 4:		solidrectangle(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4); break;
		case 5:		solidroundrect(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4, 2, 2); break;
		case 6:		solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 2, 2); break;
		case 7:		solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 4, 2); break;
		case 8:		solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 2, 4); break;
		case 9:		solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 1, 1); break;
		case 10:	fillcircle(food[i].x, food[i].y, 4); break;
		}
	}

	for (int i = 0; i < AINUM; i++) {				// 畫 AI
		if (ai[i].life == 0) continue;
		setfillcolor(ai[i].color);
		fillcircle(ai[i].x, ai[i].y, int(ai[i].r + 0.5));
	}

	setfillcolor(mover.color);						// 畫玩家
	fillcircle(mover.x, mover.y, int(mover.r + 0.5));

	IMAGE map(150, 100);							// 小地圖
	SetWorkingImage(&map);
	setbkcolor(RGB(120, 165, 209));					// 淺灰色背景
	cleardevice();
	for (int i = 0; i < AINUM; i++)				// 畫 AI(小地圖)
	{
		if (ai[i].life == 0) continue;
		setfillcolor(ai[i].color);
		fillcircle(ai[i].x * 150 / WIDTH / 4, ai[i].y * 100 / HEIGHT / 4, int(ai[i].r / 28 + 0.5));
	}

	setfillcolor(mover.color);						// 畫玩家(小地圖)
	fillcircle(mover.x * 150 / WIDTH / 4, mover.y * 100 / HEIGHT / 4, int(mover.r / 28 + 0.5));
	setlinecolor(RGB(0, 100, 0));

	SetWorkingImage();							// 恢復繪圖背景
	putimage(mover.x + int(0.5 * WIDTH) - 150, mover.y - int(0.5 * HEIGHT), 150, 100, &map, 0, 0);						// 畫出小地圖
	setlinecolor(LIGHTBLUE);
	setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 4);
	line(mover.x + int(0.5 * WIDTH) - 151, mover.y - int(0.5 * HEIGHT), mover.x + int(0.5 * WIDTH) - 151, mover.y - int(0.5 * HEIGHT) + 99);	// 地圖邊框線
	line(mover.x + int(0.5 * WIDTH) - 151, mover.y - int(0.5 * HEIGHT) + 99, mover.x + int(0.5 * WIDTH), mover.y - int(0.5 * HEIGHT) + 99);	// 地圖邊框線

	setlinestyle(PS_NULL);							// 恢復筆
	TCHAR str[32];
	swprintf_s(str, _T("質量:%.1fg  擊殺:%d"), mover.r, eaten);
	settextcolor(BLUE);							// 改字體
	outtextxy(mover.x - int(0.5 * WIDTH), mover.y - int(0.5 * HEIGHT), str);
	settextcolor(BLUE);
	outtextxy(mover.x - 36, mover.y - 8, _T("user name"));
}

void setall() {
	srand((unsigned)time(NULL));					// 隨機數
	mover.color = RGB(rand() % 256, rand() % 256, rand() % 256);		// 隨機顏色
	mover.life = 1;								// 賦初值1
	mover.x = int(WIDTH*0.5);
	mover.y = int(HEIGHT*0.5);
	mover.r = 20;

	for (int i = 0; i < AINUM; i++) {				// AI 的屬性
		ai[i].life = 1;
		ai[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
		ai[i].r = float(rand() % 10 + 10);
		ai[i].x = rand() % (MAPW - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);
		ai[i].y = rand() % (MAPH - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);
	}

	for (int i = 0; i < FNUM; i++)					// 食物的屬性
	{
		food[i].eat = 1;
		food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
		food[i].x = rand() % MAPW;
		food[i].y = rand() % MAPH;
		food[i].type = rand() % 10 + 1;
	}

	pBuffer = GetImageBuffer(NULL);					// 獲取顯存指針
	setbkcolor(WHITE);							// 白色背景
	cleardevice();								// 初始化背景
	settextcolor(LIGHTRED);						// 改字體
	setbkmode(TRANSPARENT);
	settextstyle(16, 0, _T("宋體"));

}

void delay(DWORD ms)								// 絕對延時
{
	static DWORD oldtime = GetTickCount();

	while (GetTickCount() - oldtime < ms)
		Sleep(1);

	oldtime = GetTickCount();
}

void start()
{
	setbkcolor(WHITE);							// 白色背景
	cleardevice();								// 初始化背景
	settextcolor(RED);							// 改字體
	setbkmode(TRANSPARENT);
	settextstyle(128, 0, _T("宋體"));
	outtextxy(320, 40, _T("貪婪球"));
	settextstyle(32, 0, _T("宋體"));
	outtextxy(740, 135, _T("Ver 1.0"));
	settextcolor(BLUE);
	outtextxy(170, 240, _T("   ↑ 上移  ↓ 下移  ← 左移  → 右移  "));
	settextcolor(GREEN);
	outtextxy(112, 340, _T("躲避大球   追補小球   貪吃食物   增強實力"));
	settextcolor(BLACK);
	settextstyle(32, 0, _T("宋體"));
	outtextxy(384, 500, _T("按任意鍵開始游戲"));
	settextstyle(20, 0, _T("宋體"));
	outtextxy(810, 10, _T("2018級軟件工程1班"));
	outtextxy(810, 30, _T("賀巍"));
	outtextxy(810, 50, _T("201810414113"));
	_getch();
}http://www.biyezuopin.vip

全套資料下載地址:https://download.csdn.net/download/sheziqiong/85602628
全套資料下載地址:https://download.csdn.net/download/sheziqiong/85602628文章來源地址http://www.zghlxwxcb.cn/news/detail-497831.html

到了這里,關于基于C++的簡易版《球球大作戰(zhàn)》游戲設計的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包