飞机大战------功能更新

1.前言

在上次的基础上继续添加新的功能:击毁敌机效果,被击毁效果,复活无敌效果,得分和生命值的显示
上次飞机大战博客链接,点击进入

2.效果展示

在这里插入图片描述

3.击中敌机效果

因为需要展现击中多架敌机的效果,因此同样需要一个结构体数组来表示击中效果的图片坐标。击中图片坐标是原先敌机的坐标。
在这里插入图片描述

飞机和子弹的移动效果是不停的改变图片的坐标来达成的,我们子弹击中敌机后不能让击中效果马上消失,也不
能让它移动那么该怎么办呢?我们可以利用随机数来延缓效果消失的时间;

在这里插入图片描述

4.飞机生命值,死亡效果,以及复活3秒无敌

生命值的设立:给一个变量,每被击毁一次生命值就减1;

死亡效果:被击中后,通过判断输出爆炸效果图片并且保持一段时间

复活和无敌:在亡效果展现完毕后,展现灰色机体;此时的plane.lable=false,不满足判断条件因此是无敌的,通过时间控制函数,控制3秒后恢复正常状态

下面通过代码的形式描述实现过程
在这里插入图片描述

在这里插入图片描述

5.得分显示和生命值的显示

在这里插入图片描述

6.完整代码

#ifndef _PLANE_H_
#define _PLANE_H_

#include <stdio.h>
#include <graphics.h>
#include <time.h>
#pragma warning (disable :4996)

#define  SIZE 650 //背景大小
#define  PSIZE 80 //飞机大小
#define  BSIZE 40 //子弹大小
#define  MAX 100//子弹数目
#define  FMAX 10//敌机数目
typedef struct Member
{
    
    
	double x;
	double y;
	bool lable;
}mem;

void Game();
void Load();//图片加载
void DataInit();//数据初始化
void PlaneCtr();//通过输入上下左右来改变飞机的坐标
void Show();//画面呈现
void BullterCre();//按了空格,调用函数,创建子弹
void BullterMove();//子弹移动
void FplaneCre();//敌机创建
void FplaneMove();//敌机移动
void Hit();//消灭敌机

void FdieRetain();//击中后效果保留一段时间
void PDie();//被敌机击中
void Score();//分数显示

#endif
#include"plane.h"

//定义图片变量
IMAGE background;//背景图
IMAGE plane_back;//飞机背景图
IMAGE plane_mask;//飞机掩码图
IMAGE fplane_back;//敌机背景图
IMAGE fplane_mask;//敌机掩码图
IMAGE bullte_back;//子弹背景图
IMAGE bullte_mask;//子弹掩码图
IMAGE fdie_back;//击中敌机效果背景图
IMAGE fdie_mask;//击中敌机效果掩码图
IMAGE pdie_back;//被击中背景图
IMAGE pdie_mask;//被击中掩码图
IMAGE god_plane;//飞机复活时呈现状态

//定义全局变量
mem plane;//飞机结构体
mem bullte[MAX];//子弹结构体数组
mem fplane[FMAX];//敌机结构体
mem fdie[FMAX];//击中敌机


DWORD b_time_start, b_time_last; //子弹时间变化量
DWORD pf_time_start, pf_time_last; //敌机产生时间变化量
DWORD p_time_start, p_time_last; //被击中无敌时间变化量

int flag;//本机生命值
int boom;//爆炸标志
int count;//得分计数器


void Load()//图片加载
{
    
    
	loadimage(&background, "background.jpg", SIZE, SIZE);
	loadimage(&plane_back, "plane_back.jpg", PSIZE, PSIZE);
	loadimage(&plane_mask, "plane_mask.jpg", PSIZE, PSIZE);
	loadimage(&god_plane, "god_plane.jpg", PSIZE, PSIZE);
	loadimage(&fplane_back, "fplane_back.jpg", PSIZE, PSIZE);
	loadimage(&fplane_mask, "fplane_mask.jpg", PSIZE, PSIZE);
	loadimage(&bullte_back, "bullte_back.jpg", BSIZE, BSIZE);
	loadimage(&bullte_mask, "bullte_mask.jpg", BSIZE, BSIZE);
	loadimage(&fdie_back, "fdie_back.jpg", PSIZE, PSIZE);
	loadimage(&fdie_mask, "fdie_mask.jpg", PSIZE, PSIZE);
	loadimage(&pdie_back, "pdie_back.jpg", PSIZE, PSIZE);
	loadimage(&pdie_mask, "pdie_mask.jpg", PSIZE, PSIZE);
}
void DataInit()//数据初始化
{
    
    
	//飞机的数据初始化
	plane.x = SIZE / 2 - PSIZE / 2; //飞机起始位置在背景图的中央
	plane.y = SIZE - PSIZE;
	plane.lable = true; //飞机出生是存活的

	//子弹初始化
	for (int i = 0; i < MAX; i++)
	{
    
    
		bullte[i].lable = false;//子弹没按空间前是不存在的
	}

	//时间变化初始化
	b_time_start = b_time_last = GetTickCount();//开机到现在的毫秒数
	pf_time_start = pf_time_last = GetTickCount();
	p_time_start = p_time_last = GetTickCount();//被击中无敌时间变化量

	//敌机初始化
	for (int i = 0; i<FMAX; i++)
	{
    
    
		fplane[i].lable = false;
	}
	//击中敌机效果初始化
	for (int i = 0; i < FMAX; i++)
	{
    
    
		fdie[i].lable = false;
	}

	//生命值初始化
	flag = 5;

	//死亡爆炸效果控制
	boom = 0;

	//得分计数器
	count = 0;

}

void PlaneCtr()//通过输入上下左右来改变飞机的坐标
{
    
    
	if (GetAsyncKeyState(VK_UP))//向上移动
	{
    
    
		if (plane.y>0)//不能越界
		plane.y-=0.8;
	}
	if (GetAsyncKeyState(VK_DOWN))//向下移动
	{
    
    
		if (plane.y<SIZE-PSIZE)//y最大值600,飞机图片大小为80
		plane.y+=0.8;
	}
	if (GetAsyncKeyState(VK_LEFT))//向左移动
	{
    
    
		if (plane.x>-PSIZE/2)//可以缩入墙壁一半机体
		plane.x-=0.8;
	}
	if (GetAsyncKeyState(VK_RIGHT))//向右移动
	{
    
    
		if (plane.x<SIZE-PSIZE/2)
		plane.x+=0.8;
	}
	if (GetAsyncKeyState(VK_SPACE) && b_time_last - b_time_start>80)//发射子弹,每颗子弹间接为80毫秒
	{
    
    
		BullterCre();//空格发射子弹
		b_time_start = b_time_last;
	}
	b_time_last = GetTickCount();
}

void Show()//画面呈现
{
    
    	
	BeginBatchDraw();//双缓冲绘图,防闪烁

	putimage(0, 0, &background);
	Score();//分数和生命值显示

	if (plane.lable)//飞机存活就打印飞机
	{
    
    
		putimage((int)plane.x, (int)plane.y, &plane_mask, SRCAND);
		putimage((int)plane.x, (int)plane.y, &plane_back, SRCPAINT);
	}
	if (boom)
	{
    
    
		putimage((int)plane.x, (int)plane.y, &pdie_mask, SRCAND);
		putimage((int)plane.x, (int)plane.y, &pdie_back, SRCPAINT);
		if (rand() % 80 == 2)
		{
    
    
			boom = 0;
			//飞机复活
			plane.x = SIZE / 2 - PSIZE / 2; //飞机起始位置在背景图的中央
			plane.y = SIZE - PSIZE;
		}
	}
	if (plane.lable == false&&boom==0&&flag!=0)
	{
    
    
		if (p_time_last - p_time_start>=4000)//无敌时间3秒
		{
    
    
			plane.lable = true;
			p_time_start = p_time_last;
		}
		p_time_last = GetTickCount();

		putimage((int)plane.x, (int)plane.y, &plane_mask, SRCAND);
		putimage((int)plane.x, (int)plane.y, &god_plane, SRCPAINT);
	}
	for (int i = 0; i < MAX; i++)//循环判断子弹
	{
    
    
		if (bullte[i].lable)//子弹存在就打印子弹
		{
    
    
			putimage((int)bullte[i].x, (int)bullte[i].y, &bullte_mask, SRCAND);
			putimage((int)bullte[i].x, (int)bullte[i].y, &bullte_back, SRCPAINT);
		}
	}

	for (int i = 0; i < FMAX; i++)
	{
    
    
		if (fdie[i].lable)//打印击中效果
		{
    
    
			putimage((int)fdie[i].x, (int)fdie[i].y, &fdie_mask, SRCAND);
			putimage((int)fdie[i].x, (int)fdie[i].y, &fdie_back, SRCPAINT);
		}

		if (fplane[i].lable)//打印敌机
		{
    
    
			putimage((int)fplane[i].x, (int)fplane[i].y, &fplane_mask, SRCAND);
			putimage((int)fplane[i].x, (int)fplane[i].y, &fplane_back, SRCPAINT);
		}
	}

	EndBatchDraw();
}

void BullterCre()//按了空格,调用函数,创建子弹
{
    
    
	for (int i = 0; i < MAX; i++)
	{
    
    
		if (!bullte[i].lable)//子弹不存在就创建子弹
		{
    
    
			//从飞机的正前方发出去
			bullte[i].x = plane.x + PSIZE / 2 - BSIZE / 2;
			bullte[i].y = plane.y - BSIZE;
			bullte[i].lable = true;
			break;//一次空格产生一颗子弹
		}
	}
}
void BullterMove()//子弹移动
{
    
    
	for (int i = 0; i < MAX; i++)
	{
    
    
		if (bullte[i].lable)//子弹存在,它的y坐标就减少
		{
    
    
			bullte[i].y--;//坐标减,产生移动

			if (bullte[i].y < 0)//子弹回收,否则下次全是发射出去的子弹
			{
    
    
				bullte[i].lable = false;
			}
		}
	}
}
void FplaneCre()//敌机创建
{
    
    
	for (int i = 0; i < FMAX; i++)
	{
    
    
		if (!fplane[i].lable&&pf_time_last-pf_time_start>100)//没有敌机就进行构建,用时间函数控制产生速度
		{
    
    
			fplane[i].lable = true;
			fplane[i].x = rand() % SIZE - PSIZE;//不让敌出现在窗口外
			fplane[i].y = 0;
			pf_time_start = pf_time_last;
			break;//每次一个
		}
		pf_time_last = GetTickCount();//获取新的时间
	}
}
void FplaneMove()//敌机移动
{
    
    
	for (int i = 0; i < FMAX; i++)
	{
    
    
		if (fplane[i].lable)
		{
    
    
			fplane[i].y+=0.3;//敌机往下走

			if (fplane[i].y>SIZE)//敌机回收
				fplane[i].lable = false;
		}
	}
}
void Hit()//消灭敌机
{
    
    
	for (int i = 0; i < FMAX; i++)
	{
    
    
		if (!fplane[i].lable)//不存在则换下一个判断
			continue;

		for (int j = 0; j < MAX; j++)
		{
    
    
			if (!bullte[j].lable)
				continue;//子弹不存在也换下一个判断

			if (bullte[j].x>fplane[i].x&&  //子弹和敌机有交集则都消失
				bullte[j].x<fplane[i].x + PSIZE
				&&bullte[j].y>fplane[i].y&&
				bullte[j].y <fplane[i].y + PSIZE) 
			{
    
    
				fdie[i].lable = true;//击中效果
				fdie[i].x = fplane[i].x;
				fdie[i].y = fplane[i].y;
				bullte[j].lable = false;
				fplane[i].lable = false;
				count++;
			}
		}
	}
}



void FdieRetain()//击中后效果保留一段时间
{
    
    
	for (int i = 0; i < FMAX; i++)
	{
    
    
		if (rand() % 40 == 2)
		{
    
    
			fdie[i].lable = false;
		}
	}

}

void PDie()//被敌机击中
{
    
    
	for (int i = 0; i < FMAX; i++)
	{
    
    
		if (!fplane[i].lable)
			continue;

		if (plane.x>fplane[i].x&&plane.x<fplane[i].x + PSIZE
			&&plane.y>fplane[i].y&&plane.y < fplane[i].y + PSIZE&&plane.lable)
		{
    
    
			plane.lable = false;
			flag-=1;//生命值-1

			boom = 1;//输出爆炸图片
			
			break;
		}
	}
}

void Score()//分数显示
{
    
    
	char myscore[MAX] = "当前得分为:";
	char num[20];
	sprintf(num, "%d", count);
	settextcolor(WHITE);
	outtextxy(0, 0, myscore);//输出分数
	outtextxy(80, 0, num);

	char _myscore[MAX] = "当前生命值:";
	char _num[20];
	sprintf(_num, "%d", flag);
	settextcolor(WHITE);
	outtextxy(0, 50, _myscore);
	outtextxy(90, 50, _num);//输出剩余生命值

}

void Game()
{
    
    
	//加载图片数和初始化数据
	Load();
	DataInit();
	srand((unsigned)time(NULL));//种下随机数种子

	while (1)
	{
    
    
		Show();//图像显示
		if (flag==0)
			break;
		PlaneCtr();//操控
		BullterMove();//子弹移动
		FplaneCre();//敌机创建		
		Hit();//判断是否打中敌机
		FplaneMove();//敌机往下走
		FdieRetain();//击中敌机后效果保留一段时间
		PDie();//被敌机击中
	}

}

#include"plane.h"

int main()
{
    
    
	initgraph(SIZE,SIZE);
	Game();
	getchar();
	return 0;

}

猜你喜欢

转载自blog.csdn.net/ych9527/article/details/112172604