c语言版飞机大战 基础版

#include <graphics.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <Windows.h>
#include <stdlib.h> 
#include <time.h>

void gameDraw();
void loadImg();
void gameInit();
void playerMove(int speed);
void createBullet();
void CreateEnemyPlane();
void EnemyMove(int speed);
void BulletMove(int speed);
void enemyHP(int i);
bool Timer(int ms, int id);

//枚举
enum My
{
	//窗口的宽度和高度
	WIDTH = 480,
	HEIGHT = 700,
	BULLET_NUM = 15, //子弹的数量
	ENEMY_PLANE_NUM = 10,  //每次上方同时出现几个敌机
	BIG,
	SMAIL
};



//***********************玩家飞机定义********************************
struct Plane
{
	int x;
	int y;  //飞机的坐标
	bool live; //是否存活
	int width;
	int height;
	int hp; //不同种类飞机的血量不同
	int type; // big,samll

}player, bull[BULLET_NUM], Eplane[ENEMY_PLANE_NUM]; //bull[]这里是定义了一个子弹的结构体数组

void gameInit()  //飞机位置的初始化
{
	loadImg();

	//玩家飞机
	player.x = WIDTH / 2;
	player.y = HEIGHT - 120;
	player.live = true;

	//对子弹的处理,初始化15个子弹的初始位置
	for (int i = 0; i < BULLET_NUM; i++)
	{
		bull[i].x = 0;
		bull[i].y = 0;
		bull[i].live = false;
	}

	//对敌机的处理
	//还需要根据飞机的类型,来对血量进行不同初始化
	for (int i = 0; i < ENEMY_PLANE_NUM; i++)
	{
		Eplane[i].live = false;  
		enemyHP(i);
	}

	//测试
	Eplane[0].live = true;
	Eplane[0].x = 50;
	Eplane[0].y = 50;
}

void playerMove(int speed)
{
	检测是否有键盘按下  这种方法卡顿会比较严重
	//if (_kbhit)
	//{
	//	//1._getch(),阻塞函数,同scanf,如果没有输入,就会卡住主程序,一直等待输入
	//	char key = _getch();
	//	switch (key)
	//	{
	//	case 'w':
	//	case 'W':
	//		player.y -= speed;
	//		break;
	//	case 's':
	//	case 'S':
	//		player.y += speed;
	//		break;
	//	case 'a':
	//	case 'A':
	//		player.x -= speed;
	//		break;
	//	case 'd':
	//	case 'D':
	//		player.x += speed;
	//		break;
	//	}
	//}
	//if (GetAsyncKeyState(VK_SPACE) )
	//{
	//	createBullet();
	//}


	//2.使用windows获取键盘的输入,按小键盘的上下左右
	//需要考虑飞机图片本身的长宽
	if (GetAsyncKeyState(VK_UP))
	{
		if (player.y > 0)
		{
			player.y -= speed;
		}
	}
	if (GetAsyncKeyState(VK_DOWN))
	{
		if (player.y + 100 < HEIGHT)
		{
			player.y += speed;
		}
	}
	if (GetAsyncKeyState(VK_LEFT))
	{
		if (player.x + 40 > 0)
		{
			player.x -= speed;
		}
	}
	if (GetAsyncKeyState(VK_RIGHT))
	{
		if (player.x + 70 < WIDTH)
		{
			player.x += speed;
		}
	}


	//按下按键就发射一组子弹//
	//static DWORD t1 = 0, t2 = 0;
	//if (GetAsyncKeyState(VK_SPACE) && t2 - t1 > 100)
	//{
	//	createBullet();
	//	t1 = t2;

	//}
	//t2 = clock();
	if (GetAsyncKeyState(VK_SPACE) && Timer(200, 1))
	{
		createBullet();
	}
}


//***********************敌机定义*************************

void CreateEnemyPlane()
{
	//对敌机的处理,初始化n个敌机的初始位置
	for (int i = 0; i < ENEMY_PLANE_NUM; i++)
	{
		if (!Eplane[i].live)   //子弹的状态是false,就给他初始化成真,且子弹的位置初始化为飞机位置的头部中间
		{
			Eplane[i].live = true;
			Eplane[i].x = rand() % WIDTH;
			Eplane[i].y = 0;
			enemyHP(i);

			break; //这里的break语句,会使得,每次进入if语句之后,值执行一次,然后结束循环,函数结束,也就是说,每次调用这个函数,都只产生一个飞机
		}

	}
}

void EnemyMove(int speed)
{
	for (int i = 0; i < ENEMY_PLANE_NUM; i++)
	{
		if (Eplane[i].live)   //子弹的状态是false,就给他初始化成真,且子弹的位置初始化为飞机位置的头部中间
		{
			Eplane[i].y += speed;  //子弹是向上移动的,只需要改变一个坐标
			if (Eplane[i].y > HEIGHT)
			{
				Eplane[i].live = false;
			}
		}

	}
}

void enemyHP(int i)
{
	if (rand() % 10 == 0 || rand() % 10 == 5) //d随机数等于0,产生一辆大飞机
	{
		Eplane[i].type = BIG;
		Eplane[i].hp = 3;
		Eplane[i].width = 104;  //导入图片的大小
		Eplane[i].height = 148;
	}
	else
	{
		Eplane[i].type = SMAIL;
		Eplane[i].hp = 1;
		Eplane[i].width = 49;
		Eplane[i].height = 40;
	}
}


//***********************子弹的处理*************************
void createBullet()
{
	//对子弹的处理,初始化15个子弹的初始位置
	for (int i = 0; i < BULLET_NUM; i++)
	{
		if (!bull[i].live)   //子弹的状态是false,就给他初始化成真,且子弹的位置初始化为飞机位置的头部中间
		{
			bull[i].x = player.x + 50;
			bull[i].y = player.y;
			bull[i].live = true;
			break;
		}

	}
}

void BulletMove(int speed)
{
	for (int i = 0; i < BULLET_NUM; i++)
	{
		if (bull[i].live)   //子弹的状态是false,就给他初始化成真,且子弹的位置初始化为飞机位置的头部中间
		{
			bull[i].y -= speed;  //子弹是向上移动的,只需要改变一个坐标
			if (bull[i].y < 0)
			{
				bull[i].live = false;
			}
		}

	}
}


//***********************背景绘制*************************

IMAGE bk;  //加载背景
IMAGE img_role[2];  //保存玩家的图片  ,一张正常的图,一张掩码图,用来去掉飞机的周围的背景
IMAGE bullet[2];  //加载子弹图片
IMAGE Enemy_pic[2][2];
void loadImg()
{
	//加载背景图片
	loadimage(&bk, L"C:/Users/LiYan/Desktop/c/c++/飞机大战素材包/images/background.jpg");

	//加载玩家图片
	loadimage(&img_role[0], L"./飞机大战素材包/images/planeNormal_1.jpg");
	loadimage(&img_role[1], L"./飞机大战素材包/images/planeNormal_2.jpg");

	//加载子弹图片
	loadimage(&bullet[0], L"./飞机大战素材包/images/bullet1.jpg");
	loadimage(&bullet[1], L"./飞机大战素材包/images/bullet2.jpg");

	//加载敌机图片
	loadimage(&Enemy_pic[0][0], L"./飞机大战素材包/images/enemyPlane1.jpg");
	loadimage(&Enemy_pic[0][1], L"./飞机大战素材包/images/enemyPlane2.jpg");  //前两张是大飞机
	loadimage(&Enemy_pic[1][0], L"./飞机大战素材包/images/enemyPlane3.jpg");
	loadimage(&Enemy_pic[1][1], L"./飞机大战素材包/images/enemyPlane4.jpg");
}

void gameDraw()
{
	//把背景图片贴到界面上
	putimage(0, 0, &bk);

	//玩家图片
	putimage(player.x, player.y, &img_role[0], NOTSRCERASE);
	putimage(player.x, player.y, &img_role[1], SRCINVERT);

	//画子弹
	for (int i = 0; i < BULLET_NUM; i++)
	{
		if (bull[i].live)   //子弹的状态是false,就给他初始化成真,且子弹的位置初始化为飞机位置的头部中间
		{
			putimage(bull[i].x, bull[i].y, &bullet[0], NOTSRCERASE);
			putimage(bull[i].x, bull[i].y, &bullet[1], SRCINVERT);
			//printf("%d\n", i);
		}
	}

	//画敌机
	for (int i = 0; i < ENEMY_PLANE_NUM; i++)
	{
		if (Eplane[i].live)   //子弹的状态是false,就给他初始化成真,且子弹的位置初始化为飞机位置的头部中间
		{
			if (Eplane[i].type == BIG)
			{
				putimage(Eplane[i].x, Eplane[i].y, &Enemy_pic[0][0], NOTSRCERASE);
				putimage(Eplane[i].x, Eplane[i].y, &Enemy_pic[0][1], SRCINVERT);
			}
			else
			{
				putimage(Eplane[i].x, Eplane[i].y, &Enemy_pic[1][0], NOTSRCERASE);
				putimage(Eplane[i].x, Eplane[i].y, &Enemy_pic[1][1], SRCINVERT);
			}
		}
	}


}

bool Timer(int ms,int id)
{
	//static DWORD t1, t2;  //使用静态变量函数调用只初始化一次,也就是说,下一次调用,会保留上一次执行的结果
	//if (t2 - t1 > ms)
	//{
	//	t1 = t2;
	//	return true;
	//}
	//t2 = clock();
	static DWORD t[10];
	if (clock() - t[id] > ms)
	{
		t[id] = clock();
		return true;
	}
	return false;
}

//***********************子弹和敌机的碰撞*************************

void Collide()
{
	for (int i = 0; i < ENEMY_PLANE_NUM; i++)
	{
		if (!Eplane[i].live)
			continue;
		for (int k = 0; k < BULLET_NUM; k++)
		{
			if (!bull[k].live)
				continue;
			if (bull[k].x > Eplane[i].x && bull[k].x < Eplane[i].x + Eplane[i].width
			&&  bull[k].y > Eplane[i].y && bull[k].y < Eplane[i].y + Eplane[i].height)
			{
				bull[k].live = false;
				Eplane[i].hp--;
			}

		}
		if (Eplane[i].hp <= 0)
		{
			Eplane[i].live = false;
		}
	}
}

//***********************主函数*************************

int main()
{
	//初始化图形界面 640*480
	initgraph(WIDTH, HEIGHT);
	gameInit();

	//双缓冲绘图  目的,图片在不断的移动需要不断的在背景图片上绘制图片,会出现频闪,解决频闪问题
	BeginBatchDraw();
	while (1)
	{
		gameDraw();
		FlushBatchDraw();  //刷新
		playerMove(1);
		BulletMove(1);
		//如果不适用定时器,所有的敌机就全部一起产生
		static DWORD t1, t2;
		if (t2 - t1 > 500)
		{
			CreateEnemyPlane();
			t1 = t2;
		}		
		t2 = clock();
		if (Timer(500,0))
		{
			CreateEnemyPlane();
		}
		
		if (Timer(10, 2))  //控制飞机移动的速度
		{
			EnemyMove(1);
		}

		Collide();

	}
	EndBatchDraw();
	return 0;
}


在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值