激情六月丁香婷婷|亚洲色图AV二区|丝袜AV日韩AV|久草视频在线分类|伊人九九精品视频|国产精品一级电影|久草视频在线99|在线看的av网址|伊人99精品无码|午夜无码视频在线

高校合作1:010-59833514 ?咨詢電話:400-810-1418 服務(wù)與監(jiān)督電話:400-810-1418轉(zhuǎn)接2

2d游戲用什么開發(fā)(C/C++項(xiàng)目實(shí)戰(zhàn):2D射擊游戲開發(fā)!(簡易版) 440 行源碼分享來啦~)

發(fā)布時(shí)間:2023-11-27 04:57:43 瀏覽量:118次

?C/C++項(xiàng)目實(shí)戰(zhàn):2D射擊游戲開發(fā)?。ê喴装妫?440 行源碼分享來啦~

2d游戲用什么開發(fā)(C/C++項(xiàng)目實(shí)戰(zhàn):2D射擊游戲開發(fā)!(簡易版) 440 行源碼分享來啦~)

每天一個(gè)C語言小項(xiàng)目,提升你的編程能力!

【第一版】

花了一天時(shí)間,用 easyx 做了一個(gè)小游戲,程序中所有的類函數(shù)都是內(nèi)聯(lián)函數(shù),大約 300 行。

【第二版】

主要做了代碼優(yōu)化,加強(qiáng)可讀性。

同時(shí)改了操作方式,玩家和敵人都可以在 x、y 方向上移動(dòng),敵人每隔一段時(shí)間會(huì)隨機(jī)換向。

游戲運(yùn)行截圖如下:


操作方式

玩家通過方向鍵移動(dòng),z 鍵射擊,左 Shift 進(jìn)入低速移動(dòng)模式提高操作精度。

代碼說明

關(guān)于無阻塞延時(shí),首先,先要 ctime 創(chuàng)建一個(gè) clock_t 變量 a,初始化為 clock(),貌似是自從 1970 年到現(xiàn)在的毫秒數(shù)。

2d游戲用什么開發(fā)(C/C++項(xiàng)目實(shí)戰(zhàn):2D射擊游戲開發(fā)?。ê喴装妫?440 行源碼分享來啦~)

我們要每隔 0.5 秒執(zhí)行函數(shù) func() 一次。

那么創(chuàng)建主循環(huán) while(1),調(diào)用前用 clock() - a;如果 clock() - a > 500,那么執(zhí)行 func(),并把 a 重新賦值為 clock()。

如果使用 Sleep(500) 的話,這個(gè)循環(huán)就只能執(zhí)行 func 函數(shù)了,在此期間什么也做不了。

(直接上源碼,大家可以看注釋)

/* 作者:STF(QQ:2292683261)*/
#include <easyx.h>
#include <cstdlib>
#include <ctime>


void hp_bar();
void show_player();
void show_enemy();
void move_enemy();
void draw_background();
int generate_line();					// 若返回 -1,表示生成線條失敗

int create_p_b();						// 創(chuàng)建自機(jī)的子彈
int create_e_b();						// 創(chuàng)建敵機(jī)的子彈

int destroy_p_b(int index);
int destroy_e_b(int index);				// 刪除一個(gè)子彈

#define FRAMERATE 20					// 畫面刷新的周期(ms)
#define FIRERATE 350					// 射擊間隔時(shí)間
#define E_FIRERATE 350					// 敵人射擊間隔
#define BLEED_TIME 150					// 受傷閃爍時(shí)間

#define BACKGROUND 80					// 繪制背景線條的周期

#define MAX_LINES 75					// 最多同屏背景線條數(shù)目
#define MAX_PLAYER_BULLETS 40			// 最多同屏自機(jī)子彈數(shù)目
#define MAX_ENEMY_BULLETS 40			// 最多同屏敵機(jī)子彈數(shù)目


int player_pos[2] = { 30,30 };						// 自機(jī)位置xy
int enemy_bullet[MAX_ENEMY_BULLETS][2];				// 敵人的子彈位置
int player_bullet[MAX_PLAYER_BULLETS][2];			// 自機(jī)的子彈位置
int enemy_pos[2] = { 580,240 };						// 敵機(jī)位置
bool p_b_slots[MAX_PLAYER_BULLETS] = { false };		// 用于判斷 player_bullet 的某個(gè)位置是否可用
bool e_b_slots[MAX_ENEMY_BULLETS] = { false };
int number_p_b = 0, number_e_b = 0;					// 記錄自機(jī)和敵機(jī)的子彈數(shù),減少遍歷壓力

int player_health = 100, enemy_health = 100;

bool isBleeding_p = false, isBleeding_e = false;	// 用于實(shí)現(xiàn)命中后的閃爍效果


int background_line[MAX_LINES][3];					// 背景的線條,三個(gè)參數(shù)分別是 x、y、長度
bool line_slots[MAX_LINES] = { false };
int number_lines = 0;								// 記錄背景線條數(shù)目


clock_t begin_time = 0;

int main()
{
	initgraph(640, 550, 4);

	srand((unsigned)time(NULL));

	settextcolor(RGB(0, 254, 0));
	settextstyle(30, 0, L"微軟雅黑");
	outtextxy(50, 200, L"方向鍵移動(dòng), Z 攻擊,  Shift 切換低速模式");

	bool win = false, dead = false;

	clock_t firerate = clock();						// 射擊控制
	clock_t e_firerate = clock();					// 控制敵機(jī)的射擊
	clock_t runtime = clock();						// 用于控制畫面刷新頻率
	clock_t bleed_p = clock(), bleed_e = clock();	// 用于實(shí)現(xiàn)受傷閃爍
	clock_t backgroundline_generate = clock();		// 用于生成背景線條
	Sleep(3000);
	BeginBatchDraw();

	bool leftshift = false;

	begin_time = clock();
	while (true)
	{

		if (clock() - runtime >= FRAMERATE)
		{
			runtime = clock();
			cleardevice();
			draw_background();
			hp_bar();// 畫血條
			show_player();
			show_enemy();

			int n_p_b = 1, n_e_b = 1;					// 計(jì)數(shù),遍歷子彈,刷新位置
			int p_b_toprocess = number_p_b, e_b_toprocess = number_e_b;	// 需要處理的子彈數(shù)
			for (int i = 0; i < MAX_PLAYER_BULLETS && (n_p_b <= p_b_toprocess || n_e_b <= e_b_toprocess); ++i)
			{
				if (n_p_b <= p_b_toprocess)				// 如果子彈已經(jīng)處理完就不處理了
				{
					if (p_b_slots[i] == true)
					{
						++n_p_b;
						player_bullet[i][0] += 3;
						setfillcolor(RGB(150, 180, 210));
						if (player_bullet[i][0] >= 635)
						{
							destroy_p_b(i);	// 到達(dá)了屏幕最右端
						}

						// 碰撞檢測,兩個(gè)矩形
						if ((player_bullet[i][0] + 5 >= enemy_pos[0] - 20 && player_bullet[i][0] - 5 <= enemy_pos[0] + 20) && (player_bullet[i][1] - 5 < enemy_pos[1] + 40 && player_bullet[i][1] + 5 > enemy_pos[1] - 40))
							// 擊中敵人
						{
							destroy_p_b(i);
							enemy_health -= 8;
							isBleeding_e = true;
							bleed_e = clock();
						}

						fillrectangle(player_bullet[i][0] - 5, player_bullet[i][1] - 5, player_bullet[i][0] + 5, player_bullet[i][1] + 5);		// 畫子彈
					}

				}

				if (n_e_b <= e_b_toprocess)				// 敵人的子彈
				{
					if (e_b_slots[i] == true)
					{
						++n_e_b;
						enemy_bullet[i][0] -= 3;
						setfillcolor(RGB(255, 180, 20));
						if (enemy_bullet[i][0] < 5)
						{
							destroy_e_b(i);
						}

						// 碰撞檢測,兩個(gè)矩形
						if (enemy_bullet[i][0] - 5 < player_pos[0] + 25 && enemy_bullet[i][0] + 5 > player_pos[0] - 25 && enemy_bullet[i][1] - 5 < player_pos[1] + 25 && enemy_bullet[i][1] + 5 > player_pos[1] - 25)
						{
							// 擊中自機(jī)
							isBleeding_p = true;
							destroy_e_b(i);
							player_health -= 8;
							bleed_p = clock();
						}
						fillrectangle(enemy_bullet[i][0] - 5, enemy_bullet[i][1] - 5, enemy_bullet[i][0] + 5, enemy_bullet[i][1] + 5);
					}

				}
			}

			if (win || dead)
				break;
			FlushBatchDraw();

			move_enemy();

			if (player_health <= 0)
				dead = true;
			if (enemy_health <= 0)
			{
				win = true;
			}

			if (GetAsyncKeyState(VK_LSHIFT) & 0x8000)	// 按住 Shift 減速
			{
				leftshift = true;
			}
			else
			{
				leftshift = false;
			}

			if (GetAsyncKeyState(VK_UP) & 0x8000)
				// 玩家移動(dòng)
			{
				if (player_pos[1] >= 28)
					if (leftshift)
						player_pos[1] -= 2;				// y 的正方向是向下的
					else
						player_pos[1] -= 5;
			}
			if (clock() - firerate >= FIRERATE && GetAsyncKeyState('Z') & 0x8000)
				// 玩家開火
			{
				firerate = clock();
				create_p_b();
			}
			if (GetAsyncKeyState(VK_DOWN) & 0x8000)
				// 玩家移動(dòng)
			{
				if (player_pos[1] <= 452)
					if (leftshift)
						player_pos[1] += 2;
					else
						player_pos[1] += 5;
			}
			if (GetAsyncKeyState(VK_LEFT) & 0x8000)
				// 玩家移動(dòng)
			{
				if (player_pos[0] >= 30)
					if (leftshift)
						player_pos[0] -= 2;
					else
						player_pos[0] -= 5;
			}
			if (GetAsyncKeyState(VK_RIGHT) & 0x8000)
				// 玩家移動(dòng)
			{
				if (player_pos[0] <= 320)
					if (leftshift)
						player_pos[0] += 2;
					else
						player_pos[0] += 5;
			}


			if (clock() - e_firerate >= E_FIRERATE)
			{
				e_firerate = clock();
				create_e_b();
			}


			if (clock() - bleed_p >= BLEED_TIME)		// 受傷時(shí)間結(jié)束后關(guān)閉受傷閃爍效果
			{
				isBleeding_p = false;
			}

			if (clock() - bleed_e >= BLEED_TIME)		// 受傷時(shí)間結(jié)束后關(guān)閉受傷閃爍效果
			{
				isBleeding_e = false;
			}

			if (clock() - backgroundline_generate >= BACKGROUND)
			{
				backgroundline_generate = clock();
				generate_line();
			}
		}
	}
	if (win)
	{
		settextcolor(RGB(0, 254, 0));
		settextstyle(35, 0, L"黑體");
		outtextxy(150, 200, L"你打敗了boss!你贏了??!");
	}
	else
	{
		settextcolor(RGB(254, 0, 0));
		settextstyle(35, 0, L"黑體");
		outtextxy(140, 200, L"你被boss打敗了!");
	}
	FlushBatchDraw();
	Sleep(5000);
	EndBatchDraw();
	return 0;
}






void hp_bar()
{
	setlinecolor(RGB(255, 255, 255));
	line(0, 481, 640, 481);										// 一條分割線
	settextstyle(20, 0, L"黑體");
	outtextxy(10, 485, L"BOSS的生命值:");
	outtextxy(10, 520, L"玩家的生命值:");
	setfillcolor(RGB(0, 255, 1));
	setlinecolor(WHITE);
	rectangle(160, 515, 560, 540);								// 血條外框
	setfillcolor(RGB(0, 255, 1));
	setlinecolor(RGB(255, 255, 255));
	if (player_health > 0)
		fillrectangle(160, 515, 160 + player_health * 4, 540);	// 玩家血條
	setlinecolor(WHITE);
	rectangle(160, 485, 560, 510);								// 敵人血條外框
	setfillcolor(RGB(230, 0, 1));
	setlinecolor(RGB(255, 255, 255));
	if (enemy_health > 0)
		fillrectangle(160, 485, 160 + enemy_health * 4, 510);	// 敵人血條

}

void show_player()
{
	if (isBleeding_p)
		setfillcolor(RGB(255, 0, 0));
	else
		setfillcolor(RGB(150, 180, 210));
	fillrectangle(player_pos[0] - 25, player_pos[1] - 25, player_pos[0] + 25, player_pos[1] + 25);
	setfillcolor(RGB(100, 200, 180));
	fillrectangle(player_pos[0], player_pos[1] + 5, player_pos[0] + 40, player_pos[1] - 5);
}

void show_enemy()
{
	if (isBleeding_e)
		setfillcolor(RGB(255, 0, 0));
	else
		setfillcolor(RGB(0, 130, 125));
	fillrectangle(enemy_pos[0] - 20, enemy_pos[1] - 40, enemy_pos[0] + 20, enemy_pos[1] + 40);
	setfillcolor(RGB(100, 200, 180));
	fillrectangle(enemy_pos[0], enemy_pos[1] + 5, enemy_pos[0] - 40, enemy_pos[1] - 5);
}

void move_enemy()
{
	static bool angle_v;		// 控制敵機(jī)的豎直移動(dòng)方向,true 為向上,到邊緣就換向
	static bool angle_h;		// 控制敵機(jī)的水平移動(dòng)方向,true 為向左,到邊緣就換向
	static clock_t interval;	// 定時(shí)隨機(jī)換向

	if (clock() - interval >= 2000)
	{
		interval = clock();
		if (rand() % 2)			// 一般的概率換向
			angle_v = !angle_v;
		if (rand() % 2)
			angle_h = !angle_h;
	}

	if (angle_v == true)		// 到了地圖邊緣就調(diào)頭
		enemy_pos[1] -= 3;
	else
		enemy_pos[1] += 3;
	if (angle_h == true)
		enemy_pos[0] -= 3;
	else
		enemy_pos[0] += 3;


	if (enemy_pos[1] >= 440)
		angle_v = true;
	else if (enemy_pos[1] <= 40)
		angle_v = false;


	if (enemy_pos[0] >= 580)
		angle_h = true;
	else if (enemy_pos[0] <= 380)
		angle_h = false;

}

void draw_background()
{
	setlinecolor(WHITE);
	int n_b_l = number_lines;		// 待處理線條數(shù)目
	for (int i = 0; i < MAX_LINES && (n_b_l > 0); ++i)
	{
		if (line_slots[i] == true)
		{
			if (background_line[i][0] + background_line[i][2] <= 0)		// 說明線條出了屏幕
			{
				--number_lines;
				line_slots[i] = false;
			}
			else
			{
				background_line[i][0] -= 10;				// 線條移動(dòng)
				line(background_line[i][0], background_line[i][1], background_line[i][0] + background_line[i][2], background_line[i][1]);
			}
			--n_b_l;
		}

	}
}

int generate_line()
{
	if (number_lines >= MAX_LINES)
		return -1;
	++number_lines;
	for (int i = 0; i < MAX_LINES; ++i)
	{
		if (line_slots[i] == false)
		{
			line_slots[i] = true;
			background_line[i][0] = 640;				// 線條出現(xiàn)于屏幕最右邊
			background_line[i][1] = rand() % 480;		// 線條高度隨機(jī)
			background_line[i][2] = 10 + rand() % 50;	// 線條長度隨機(jī)在 10-50 像素之間

			break;
		}
	}
	return 0;
}

int create_p_b()
{
	if (number_p_b > MAX_PLAYER_BULLETS)			// 空間不夠
		return -1;
	for (int i = 0; i < MAX_PLAYER_BULLETS; ++i)	// 搜索 slots,尋找空位
	{
		if (p_b_slots[i] == false)
		{
			p_b_slots[i] = true;
			player_bullet[i][0] = player_pos[0] + 45;
			player_bullet[i][1] = player_pos[1];	// 創(chuàng)建子彈
			++number_p_b;
			break;
		}
	}
	return 0;
}

int create_e_b()
{
	if (number_e_b > MAX_ENEMY_BULLETS)				// 空間不夠
		return -1;
	for (int i = 0; i < MAX_ENEMY_BULLETS; ++i)		// 搜索 slots,尋找空位
	{
		if (e_b_slots[i] == false)
		{
			e_b_slots[i] = true;
			enemy_bullet[i][0] = enemy_pos[0] - 45;
			enemy_bullet[i][1] = enemy_pos[1];		// 創(chuàng)建子彈
			++number_e_b;
			break;
		}
	}
	return 0;
}

int destroy_p_b(int index)
{
	if (index > MAX_PLAYER_BULLETS - 1)
		return -2;
	if (p_b_slots[index] == false)
		return -1;
	p_b_slots[index] = false;
	--number_p_b;
	return 0;
}

int destroy_e_b(int index)
{
	if (index > MAX_ENEMY_BULLETS - 1)
		return -2;
	if (e_b_slots[index] == false)
		return -1;
	e_b_slots[index] = false;
	--number_e_b;
	return 0;
}

大家趕緊去動(dòng)手試試吧!

此外,我也給大家分享我收集的其他資源,從最零基礎(chǔ)開始的教程到C語言C++項(xiàng)目案例,幫助大家在學(xué)習(xí)C語言的道路上披荊斬棘!

編程學(xué)習(xí)書籍分享:

編程學(xué)習(xí)視頻分享:

整理分享(多年學(xué)習(xí)的源碼、項(xiàng)目實(shí)戰(zhàn)視頻、項(xiàng)目筆記,基礎(chǔ)入門教程)最重要的是你可以在群里面交流提問編程問題哦!

對(duì)于C/C++感興趣可以關(guān)注小編在后臺(tái)私信我:【編程交流】一起來學(xué)習(xí)哦!可以領(lǐng)取一些C/C++的項(xiàng)目學(xué)習(xí)視頻資料哦!已經(jīng)設(shè)置好了關(guān)鍵詞自動(dòng)回復(fù),自動(dòng)領(lǐng)取就好了!

2d游戲用什么開發(fā)(C/C++項(xiàng)目實(shí)戰(zhàn):2D射擊游戲開發(fā)?。ê喴装妫?440 行源碼分享來啦~)

熱門課程推薦

熱門資訊

請(qǐng)綁定手機(jī)號(hào)

x

同學(xué)您好!

您已成功報(bào)名0元試學(xué)活動(dòng),老師會(huì)在第一時(shí)間與您取得聯(lián)系,請(qǐng)保持電話暢通!
確定