#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;
}
c语言版飞机大战 基础版
最新推荐文章于 2022-02-05 17:01:03 发布