飞机大战——图文详解

  • Post author:
  • Post category:其他

1.前言

本次需要用到easyx图形库,关于easyx的安装和一些基本函数,我在另外一篇推箱子小游戏中也有介绍,需要了解的小伙伴也可以点击进去看一看,下面会附上链接;

在写程序过程中需要的图片,可以去百度找,也可以自己制作,有想要了解如何制作的小伙伴也可以点击我下面的博客链接;

图片素材如何制作链接
easyx介绍链接

2.效果展示

在这里插入图片描述

3.图片素材的准备

如下图所示,我将我用到的图片的背景图和原码图都放在了源文件的文件夹,这样访问的时候直接填写图片文件名即可;
有个小建议,图片名字别乱取,因为找起来特别麻烦,啊哈哈;
在这里插入图片描述

4.需要构建的函数

下图中,展示了我们需要构建的函数以及定义的结构体,下面我将会解释各个函数的实现
在这里插入图片描述

5.变量的定义

我们使用变量时需要定义,我们的图片在使用之前也需要定义和加载,如下图所示:
在这里插入图片描述

6.数据的初始化

由上面可知我们定义了飞机结构体变量,变量中的的x,y即代表了飞机的坐标,我们的飞机在出生时,应该在界面的最低的中央处。子弹和敌机的初始化一目了然这里就不再赘述了;

下图展现了窗口的坐标,和飞机的起始坐标取值:
在这里插入图片描述

7.画面的呈现

通过判断我方飞机,子弹,敌机的结构体中的bool值来确定是否打印图案;
我们的子弹和敌机的设置为数组,通过数组元素形成的时间差,来营造连绵不断的动态效果;
在这里插入图片描述

8.飞机移动的实现

在这里插入图片描述

9.子弹的构建和移动

9.1子弹的构建

在这里插入图片描述

9.2子弹的移动

在这里插入图片描述

10.敌机的创建和移动

敌机的创建和移动就是子弹的复制版本,两者逻辑是一样的
在这里插入图片描述

11.敌机消灭函数

在这里插入图片描述

12.结束语

非常感谢大家的访问,期待你们的指导。
这次只实现了飞机大战基本的功能,后面会继续更新其它有趣的内容;

13.完整代码

#ifndef _PLANE_H_
#define _PLANE_H_

#include <stdio.h>
#include <graphics.h>
#include <time.h>

#define  SIZE 600 //背景大小
#define  PSIZE 80 //飞机大小
#define  BSIZE 40 //子弹大小
#define  MAX 10//子弹数目
#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();//消灭敌机

#endif
#include"plane.h"

//定义图片变量
IMAGE background;//背景图
IMAGE plane_back;//飞机背景图
IMAGE plane_mask;//飞机掩码图
IMAGE fplane_back;//敌机背景图
IMAGE fplane_mask;//敌机掩码图
IMAGE bullte_back;//子弹背景图
IMAGE bullte_mask;//子弹掩码图

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

DWORD time_start, time_last; //时间变化量

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(&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);
}
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;//子弹没按空间前是不存在的
	}

	time_start = time_last = GetTickCount();//开机到现在的毫秒数

	//敌机初始化
	for (int i = 0; i>FMAX; i++)
	{
		fplane[i].lable = false;
	}

}

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) &&time_last - time_start>80)//发射子弹,每颗子弹间接为80毫秒
	{
		BullterCre();//空格发射子弹
		time_start = time_last;
	}
	time_last = GetTickCount();
}

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

	putimage(0, 0, &background);
	if (plane.lable)//飞机存活就打印飞机
	{
		putimage((int)plane.x, (int)plane.y, &plane_mask, SRCAND);
		putimage((int)plane.x, (int)plane.y, &plane_back, 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 (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&&time_last-time_start>100)//没有敌机就进行构建,用时间函数控制产生速度
		{
			fplane[i].lable = true;
			fplane[i].x = rand() % SIZE - PSIZE;//不让敌出现在窗口外
			fplane[i].y = 0;
			time_start = time_last;
			break;//每次一个
		}
		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) 
			{
				bullte[j].lable = false;
				fplane[i].lable = false;
			}
		}
	}
}


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

	while (1)
	{
		Show();//图像显示
		PlaneCtr();//操控
		BullterMove();//子弹移动
		FplaneCre();//敌机创建		
		Hit();//判断是否打中敌机
		FplaneMove();//敌机往下走
	}
}
#include"plane.h"

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

}

14.内容更新

内容更新链接,点击进入


版权声明:本文为ych9527原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。