飞机大战的部分思路框架及其代码实现

飞机大战的部分思路框架


实现的功能需求:

  • 背景图片的打开,使用了#include<easyx.h> 的图形处理解决(各种图片的打开绘制),这里因为素材的原因没有实现(实体透明),没有找到相关的黑底白面,白底彩面的图片素材,显示效果不佳,再次基础上通过两张一样的图片对图片显示位置的改变,实现图片的滚动效果;在通过 BeginBatchDraw():开始批量绘制,将各种图片绘制在缓存中,以及 EndBatchDraw () :结束绘图,将一张完整的一帧绘制子在窗口中,实现帧数的刷新,防止闪屏;因为是一直在绘制图片的所以要 使用循环条件
  • 背景音乐,使用一个阻塞的按键控制开关,再通过显示一张小图片的显示表示音乐的开关状态;
  • 飞机的出现,与背景图片的显示一样操作;飞机的移动使用,使用一个非阻塞按键GetAsyncKeyState() 对飞机的细腻操作,同样通过改变飞机图片的出现的位置的改变达到对飞机的移动效果;
  • 子弹的显示,同样与背景图片的显示一样操作;子弹的通过一个标记达到对子弹的有限的重复的利用,嫌少栈帧,;对子弹的出现的配合(联系)飞机坐标的变化,合理设计子弹的出现位置;再通过改变子弹坐标出现的位置的改变实现,子弹的飞行;

这次项目的实现,让我明白了项目架构的重要性,写项目的时候

  1. 仔细分析项目功能的需求

  2. 设计合理清晰的架构,不然几百行代码下来自己都不知道自己在写什么

    1. 头文件的定义(不要放变量,防止重定义),结构体,枚举,数据(数值)的信息化(#define),不要写死了,影响需求的改变维护,可变;
    2. 各种功能函数使用文件(见闻知意),分开来定义,实现功能函数;如 ** 文件(使用来实现初始化数据的), ** 文件(用来实现数据可视化,显示图片效果)
  3. 数据的初始化

  4. 数据的可视化(图片效果的显示)

  5. 数据的更新(一些操作上实现的改变),以及一些消失的条件的更新判断

  6. 退出的设定

目前在这个项目领悟的就这些了:

为了方便大家查看先给个大概图示: 说明一个我用的是 C语言编写的 这里用c++是因为 Easyx 不支持 c语言的,支持c++ 但是 c++兼容 C语言 所以影响不大,如果要运行下面代码的朋友,需要安装 Easyx 图形处理工具的,免费的,百度即可,具体安装详细: [Easyx的详细安装教程]((57条消息) (EasyX入门与实战)第一章 下载并安装easyX库_代码骑士的博客-CSDN博客)

在这里插入图片描述


代码:

头文件 代码: GameHead.h

#pragma once // 注意不要删除了,为了避免头文件的重复引入,影响效率


#include<stdio.h> // 标准输入输出
#include<windows.h> // 操作系统 注意要在 头文件mmsystem.h的前面,不然会报错的,因为音乐是要通过操作系统打开的
#include<mmsystem.h> // 多媒体
#include<conio.h> // 输入按键的头文件
#include<easyx.h> // 图形处理


#pragma comment (lib, "winmm.lib") // 预处理


// 定义窗口的大小
#define WIDTH 365        // 窗口的宽度
#define HEIGHT 650       // 窗口的高度
#define PLANEWIDTH 38    // 飞机的宽度
#define PLANEHEIGHT 73   // 飞机的高度
#define BULLEtWIDTH 31   // 子弹的宽度
#define BuLLEHEIGHT 124  // 子弹的高度


// 定义一个飞机的结构体
typedef struct My_plane
{
    IMAGE myPlanephoto; // 存放自己飞机的图片
    int plang_x = 0;    // 自己飞机的X轴的位置
    int plang_y = 0;    // 自己飞机的Y轴的位置
    int myPlaneblood;   // 定义自己飞机的血量

}My_plane;


typedef struct Bullet
{
    IMAGE myBulletPhoto;  // 存放自己的子弹的图片
    int bullet_x = 0;     // 自己子弹的X轴的位置
    int bullet_y = 0;     // 自己子弹的Y轴的位置
    bool Isexit;          // 自己子弹是否存在的
}Bullet;

                                                                              

 // 游戏场景
void GameInit(IMAGE* background_image, My_plane* myPlane,Bullet* bullet);


// 绘制界面(数据可视化)
void GameDraw(IMAGE* background_image, int* background_image_y1, int *background_image_y2);



// 数据更新
void GameUpdate(int* Background_image_y1, int* Background_image_y2, Bullet* bullet, My_plane* myPlane);


// 实现图片的上下滚动
void PhotosRoll(int* Background_image_y1, int* Background_image_y2);


// 显示音乐的状态
void MusicState();


// 实现开关音乐的控制
void ControlMusic(Bullet* bullet, My_plane* myplane);


//实现绘制(显示)自己的飞机
void ShowMyplane(My_plane* myPlane);


// 实现自己飞机的移动效果 
void PlanexMoving(My_plane* myPlane);

// 绘制(显示)自己的子弹
void ShowMybullet(Bullet* bullet);
                                                                                                                               
// 实现移动子弹
void MoveBullet(Bullet* bullet);



main 代码文件(Game.cpp):

#define  _CRT_SECURE_NO_WARNINGS  1


#include"GameHead.h" // 自行定义的头文件使用 双引号 “ ” ;
					 // 查找路径的不同,“” 双引号可以查找自己本身所在的路径

// 定义背景图片的位置
int  Background_image_y1 = 0; // 最开头
int  Background_image_y2 = -HEIGHT;  // 最末尾


IMAGE Background_image = 0; // 定义一个变量存放背景图片
IMAGE* background_image = &Background_image; // 定义一个IMAGE 的指针类型

extern bool musicState ; // 定义一个bool 类型用于表示音乐的播放关闭的状态;

My_plane myPlane = { 0 }; // 定义一个自己的飞机

Bullet bullet[10] = { 0 }; // 定义自己的子弹 10 发



int main()
{


	// 创建窗口
	initgraph(WIDTH, HEIGHT); // x,y
	cleardevice(); // 刷新窗口
	
	// 游戏场景
	GameInit(background_image,&myPlane,bullet);


	while (1)
	{

		// 绘制界面 (数据可视化)
		GameDraw(background_image, &Background_image_y1, &Background_image_y2);

		//实现绘制(显示)自己的飞机
	    ShowMyplane(&myPlane);

		// 绘制(显示)自己的子弹
		ShowMybullet(bullet);


		// 实现移动子弹
		MoveBullet(bullet);

		// 实现自己飞机的移动效果
		PlanexMoving(&myPlane);

	
		// 数据的更新
		GameUpdate(&Background_image_y1, &Background_image_y2,bullet,&myPlane);

		Sleep(10); // 图片减缓速度
	}


	system("pause"); // 防止闪退
	return 0;
}



代码文件初始化数据(GameInit.cpp):

#define  _CRT_SECURE_NO_WARNINGS  1

#include"GameHead.h" // 自行定义的头文件使用 双引号 “ ” ;
// 查找路径的不同,“” 双引号可以查找自己本身所在的路径


// 初始化背景图片
void GameInit(IMAGE* background_image,My_plane*myPlane,Bullet*bullet)
{
	// 存放背景的图
	loadimage(background_image, "setting2.png"); // 把图片存放到使用IMAGE定义的变量(Background_image)

	// 初始化音乐
	mciSendString("open 封茗囧菌-东京不太热.mp3", 0, 0, 0); // open 打开音乐文件
	mciSendString("play 封茗囧菌-东京不太热.mp3", 0, 0, 0); // play 播放音乐
	/* 注意 音乐的名称不要有空格因为该函数mciSendString() 是通过空格来分割字符串的*/

	 
	//初始化自己的飞机
	// 1.存放自己飞机的图片,
	loadimage( &myPlane->myPlanephoto, "plane.png");
	// 2.飞机的初始位置
	myPlane->plang_x = (WIDTH - PLANEWIDTH) / 2;  // 自己飞机的x轴,WIDTH 窗口的宽度
	myPlane->plang_y = HEIGHT - PLANEHEIGHT;      // 自己飞机的Y轴 HEIGHT 窗口的高度
	myPlane->myPlaneblood = 100;                  // 自己飞机的血量 100


	// 初始化自己的子弹
	loadimage(&(bullet->myBulletPhoto), "bullet.png");

	// 将十颗子弹初始化为 空 状态;
	for (int i = 0; i < 10; i++)
	{
		bullet[i].Isexit = false; 
	}

}


代码文件数据的可视化(GameDraw.cpp)

#define  _CRT_SECURE_NO_WARNINGS  1


#include"GameHead.h" // 自行定义的头文件使用 双引号 “ ” ;
// 查找路径的不同,“” 双引号可以查找自己本身所在的路径


extern bool musicState = true; // 定义一个bool 类型用于表示音乐的播放关闭的状态;



// 绘制界面(数据可视化)
void GameDraw(IMAGE* background_image,int* Background_image_y1,int* Background_image_y2)
{

	BeginBatchDraw(); // 开始批量绘制,将各种图片绘制在缓存中,

	putimage(0, 0, background_image);
	putimage(0, *Background_image_y1, background_image);
	putimage(0, *Background_image_y2, background_image);

	MusicState(); // 显示音乐的状态

	EndBatchDraw(); // 结束批量绘制,将完整的一帧绘制在窗口中
}


// 显示音乐的状态
void MusicState()
{
	IMAGE VoicePhoto[2]; // 定义一个IMAGE类型的数组存放声音状态的图片
	loadimage(&VoicePhoto[0], "playvoice.png"); // 把声音播放图片存放到数组下标[0]的位置地址
	loadimage(&VoicePhoto[1], "pausvoice.png"); // 把声音关闭图片存放到数组下标[1]的位置地址 


	if (musicState)
	{
		//outtextxy(10, 10, "playing");
		putimage(0, 0, &VoicePhoto[0]); // 把存放在数组下标[0]的图片显示在窗口 0,-10的位置
	}
	else
	{
		//outtextxy(10, 10, "pausing");
		putimage(0, -20, &VoicePhoto[1]); // 把存放在数组下标[1]的图片显示在窗口 0,-10的位置
	}

}


//实现绘制(显示)自己的飞机
void ShowMyplane(My_plane* myPlane)
{
	BeginBatchDraw(); // 开始批量绘制,将各种图片绘制在缓存中,

	if (myPlane->myPlaneblood > 0)
	{
		putimage(myPlane->plang_x, myPlane->plang_y, &myPlane->myPlanephoto);

	}

	EndBatchDraw(); // 结束批量绘制,将完整的一帧绘制在窗口中
}


// 绘制(显示)自己的子弹
void ShowMybullet(Bullet*bullet)
{
	BeginBatchDraw(); // 开始批量绘制,将各种图片绘制在缓存中,

	for (int i = 0; i < 10; i++)
	{
		if (bullet[i].Isexit)
		{
			putimage(bullet[i].bullet_x, bullet[i].bullet_y, &(bullet->myBulletPhoto));
		}
	}

	EndBatchDraw(); // 结束批量绘制,将完整的一帧绘制在窗口中

}

代码文件数据的更新(GameUpdate.cpp)

#define  _CRT_SECURE_NO_WARNINGS  1

#include"GameHead.h" // 自行定义的头文件使用 双引号 “ ” ;
// 查找路径的不同,“” 双引号可以查找自己本身所在的路径

extern bool musicState ; // 定义一个bool 类型用于表示音乐的播放关闭的状态;



// 数据更新
void GameUpdate(int* Background_image_y1, int* Background_image_y2, Bullet* bullet, My_plane* myPlane)
{
	// 实现图片的上下滚动
	PhotosRoll(Background_image_y1, Background_image_y2);

	// 实现开关音乐的控制
	ControlMusic(bullet, myPlane);

}



// 实现图片的上下滚动
void PhotosRoll(int* Background_image_y1, int* Background_image_y2)
{
	(*Background_image_y1)++;

	if ((*Background_image_y1) > HEIGHT)  // HEIGT 窗口的高度
	{
		(*Background_image_y1) = -HEIGHT;
	}

	(*Background_image_y2)++;


	if ((*Background_image_y2) > HEIGHT)
	{
		(*Background_image_y2) = -HEIGHT;
	}

}



 
// 实现开关音乐的控制
void ControlMusic(Bullet* bullet, My_plane* myPlane)
{

	if (_kbhit())
	{
		char key = _getch(); // 接受按键的信息  

		if (key == '1')
		{
			if (musicState)
			{
				mciSendString("pause 封茗囧菌-东京不太热.mp3", 0, 0, 0); //暂听音乐
				musicState = !musicState; // 修改音乐的状态
			}
			else
			{
				mciSendString("play 封茗囧菌-东京不太热.mp3", 0, 0, 0); // 播放音乐
				musicState = !musicState; // 修改音乐的状态
			}
		}
		else if (key == ' ')
		{
			for (int i = 0; i < 10; i++)
			{
				if (!bullet[i].Isexit) // 将false 变成 true
				{
					bullet[i].Isexit = true;
					bullet[i].bullet_x = myPlane->plang_x;
					bullet[i].bullet_y = myPlane->plang_y - BuLLEHEIGHT;
					break;
				}
			}
		}


	}

}






// 实现自己飞机的移动效果
void PlanexMoving(My_plane* myPlane)
{
	// 飞机向下移动
	// `这里运行了一个非阻塞按键的使用
	if (GetAsyncKeyState(VK_UP))
	{
		if (myPlane->plang_y >= HEIGHT)
		{
			myPlane->plang_y = HEIGHT - PLANEHEIGHT;
		}

		if (myPlane->plang_y <= -3)
		{
			myPlane->plang_y = PLANEHEIGHT;
		}

		myPlane->plang_y -= 3;

	}

	// 飞机向上移动
	if (GetAsyncKeyState(VK_DOWN))
	{
		if (myPlane->plang_y >= HEIGHT)
		{
			myPlane->plang_y = HEIGHT - PLANEHEIGHT;
		}

		if (myPlane->plang_y <= -3)
		{
			myPlane->plang_y = PLANEHEIGHT;
		}

		myPlane->plang_y += 3;

	}

	// 飞机向左移动
	if (GetAsyncKeyState(VK_LEFT))
	{

		if (myPlane->plang_x >= WIDTH)
		{
			myPlane->plang_x = WIDTH - PLANEWIDTH;
		}

		if (myPlane->plang_x <= -3)
		{
			myPlane->plang_x = PLANEWIDTH;
		}

		myPlane->plang_x -= 3;

	}

	// 飞机向右移动
	if (GetAsyncKeyState(VK_RIGHT))
	{
		if (myPlane->plang_x >= WIDTH)
		{
			myPlane->plang_x = WIDTH - PLANEWIDTH;
		}

		if (myPlane->plang_x <= -3)
		{
			myPlane->plang_x = PLANEWIDTH;
		}

		myPlane->plang_x += 3;

	}

}




// 实现移动子弹
void MoveBullet(Bullet* bullet)
{
	for (int i = 0; i < 10; i++)
	{
		if (bullet[i].Isexit)
		{
			bullet[i].bullet_y -= 7;
			if (bullet[i].bullet_y < -BuLLEHEIGHT)
			{
				bullet[i].Isexit = false;
			}
		}
	}

}


代码效果:

在这里插入图片描述

当然其中有一些图片的素材,音乐素材,你们可以复制粘贴 自行替换,而我这里的素材以为CSDN 的一些原因无法上传,真需要的朋友,可以评论留言:向我所要的: 还有可以查看我的主页,其中有一些我在写该项目的一些问题的出现,以及解决方案:


最后:

限于自己的水平的原因:其中的错误,不足,希望大家多多给予指教:韩信点兵——多多益善,谢谢大家!

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值