用C语言和Easyx图形库实现飞机大战小游戏

实现过程:

首先要先创建一个图像化窗口,设置该窗口的宽和高,然后将背景图片加载并粘贴到窗口上,再将飞机图片加载并粘贴到窗口上(透明化贴图),再利用鼠标交互功能,通过鼠标的移动来控制飞机的移动,然后再将子弹图片加载并粘贴到窗口上,通过自减函数使子弹自动向上移动直至消失,再将敌机图片加载并粘贴到窗口上,通过自加函数使敌机自动向下移动,设置如果子弹和敌机靠近在一定范围之内为子弹击中敌机,同理如果玩家飞机和敌机靠近在一定范围为敌机消灭玩家,玩家飞机发生爆炸,游戏结束。

源码展示:

#include<stdio.h>   
#include<graphics.h>  //调用eaxyx中的函数
#include<math.h>
#pragma comment(lib,"Winmm.lib")//引用Windows Multimedia API

void startup();
void show();
void updateWithoutInput();
void updateWithInput();
void gameover();

enum MyEnum    //枚举定义·  设置游戏画面尺寸
{
	WIDTH = 550,    //窗口的宽度和高度
	HEIGHT = 700,
};
//全局变量
IMAGE   img_bk;// 背景图片
IMAGE   img_planeNormal[2];  //正常飞机图片  
IMAGE  img_bullet[2];//子弹图片
IMAGE   img_enemyPlane[2];  //敌机图片 
IMAGE img_planeExplode[2];//爆炸飞机图片

int position_x, position_y;//飞机位置
int bullet_x, bullet_y;//子弹坐标(位置)
int enemy_x, enemy_y;//敌机坐标(位置)

int isExpolde = 0;//飞机是否爆炸
int score = 0;//得分

int main()
{
	startup();//数据初始化
	//BeginBatchDraw();
	while (1)//游戏循环执行
	{
		BeginBatchDraw();// 用于批量绘图,但在执行后 任何绘图操作都将暂时不输出到屏幕上,直到执行FlushBatchDraw或EndBatchDraw才将之前的绘图输
		show();//显示画面
		updateWithoutInput();//与用户输入无关的更新
		FlushBatchDraw();//用于执行未完成的绘制任务
		updateWithInput();//与用户输入有关的更新
		EndBatchDraw(); // 用于结束批量绘制,并执行未完成的绘制任务   FlushBatchDraw这个函数用于执行未完成的绘制任务
	}
	gameover();//游戏结束
	return 0;
}



void startup()//加载背景音乐和图片
{
	mciSendString("open C://images//game_music.mp3 alias bkmusic", NULL, 0, NULL);//打开背景音乐
	mciSendString("play bkmusic repeat", NULL, 0, NULL);//循环播放背景音乐

	initgraph(WIDTH, HEIGHT, SHOWCONSOLE);//创建一个图形窗口 黑框框是控制台窗口是自动创建的 而图形窗口需要自己手动创建

	loadimage(&img_bk, "C://images//background.jpg"); //加载背景图(分辨率 591*864像素)  可能会报错 参数有误,因为字符集不对,将unicode 改为多字节字符集   两个重载中没有一个可以转换所有参数类型
	loadimage(&img_planeNormal[0], "C://images//planeNormal_1.jpg");//加载正常飞机图
	loadimage(&img_planeNormal[1], "C://images//planeNormal_2.jpg");
	loadimage(&img_bullet[0], "C://images//bullet1.jpg");//加载子弹图
	loadimage(&img_bullet[1], "C://images//bullet2.jpg");
	loadimage(&img_enemyPlane[0], "C://images//enemyPlane1.jpg");//加载敌方飞机图
	loadimage(&img_enemyPlane[1], "C://images//enemyPlane2.jpg");
	loadimage(&img_planeExplode[0], "C://images//planeBoom_1.jpg");//加载爆炸飞机图
	loadimage(&img_planeExplode[1], "C://images//planeBoom_2.jpg");

	position_x = WIDTH / 2;
	position_y = HEIGHT - 120;
	bullet_x = position_x;
	bullet_y = -85;
	enemy_x = WIDTH / 2;
	enemy_y = 10;

	BeginBatchDraw();
}
void show()//粘贴图像
{
	putimage(0, 0, &img_bk);      //把背景图贴到创建的图形窗口上
	if (isExpolde == 0)
	{
		putimage(position_x - 50, position_y - 60, &img_planeNormal[0], NOTSRCERASE);//把飞机图像贴到创建的图形窗口上
		putimage(position_x - 50, position_y - 60, &img_planeNormal[1], SRCINVERT);
		putimage(bullet_x - 7, bullet_y, &img_bullet[0], NOTSRCERASE);//把子弹图像贴到创建的图形窗口上
		putimage(bullet_x - 7, bullet_y, &img_bullet[1], SRCINVERT);
		putimage(enemy_x, enemy_y, &img_enemyPlane[0], NOTSRCERASE);//把敌机图像贴到创建的图形窗口上
		putimage(enemy_x, enemy_y, &img_enemyPlane[1], SRCINVERT);
	}
	else
	{
		putimage(position_x - 50, position_y - 60, &img_planeExplode[0], NOTSRCERASE);//把爆炸飞机图像贴到创建的图形窗口上
		putimage(position_x - 50, position_y - 60, &img_planeExplode[1], SRCINVERT);
	}
	outtextxy(WIDTH / 2 - 50, HEIGHT - 100, "得分:");
	char s[5];
	sprintf_s(s, "%d", score);
	outtextxy(WIDTH / 2, HEIGHT - 100, s);
	FlushBatchDraw();
	Sleep(2);
}

void updateWithoutInput()//与用户输入无关的更新
{
	if (isExpolde == 0)
	{
		if (bullet_y > -30) //让子弹出边界以后就不需要移动
		{
			bullet_y -= 2;//子弹向上移动
		}
		if (enemy_y < HEIGHT)//使敌机自动下落
		{
			enemy_y += 1;
		}
		else
		{
			enemy_x = rand() % WIDTH;
			enemy_y = 10;
		}
		if (abs(bullet_x - enemy_x) + abs(bullet_y - enemy_y) < 80)//子弹击中敌机
		{
			enemy_x = rand() % WIDTH;
			enemy_y = -40;
			bullet_y = -85;
			mciSendString("close gemusic", NULL, 0, NULL);//先把前面一次的的关闭
			mciSendString("open C://images//gotEnemy.mp3 alias gemusic", NULL, 0, NULL);//打开音乐
			mciSendString("play gemusic", NULL, 0, NULL);//仅播放一次
			score++;
			if (score > 0 && score % 5 == 0 && score % 2 != 0)//如果玩家获得的分数是五的倍数且不是二的倍数,则播放5music的音乐
			{
				mciSendString("close 5music", NULL, 0, NULL);//先把前面一次的的关闭
				mciSendString("open C://images//5.mp3 alias 5music", NULL, 0, NULL);
				mciSendString("play 5music", NULL, 0, NULL);//仅播放一次
			}
			if (score % 10 == 0)//如果玩家获得的分数是十的倍数,则播放10music的音乐
			{
				mciSendString("close 10music", NULL, 0, NULL);//先把前面一次的的关闭
				mciSendString("open C://images//10.mp3 alias 10music", NULL, 0, NULL);
				mciSendString("play 10music", NULL, 0, NULL);//仅播放一次
			}
		}
		if (abs(position_x - enemy_x) + abs(position_y - enemy_y) < 130)//被敌机击中
		{
			isExpolde = 1;
			mciSendString("close exmusic", NULL, 0, NULL);//先把前面一次的的关闭
			mciSendString("open C://images//explode.mp3 alias exmusic", NULL, 0, NULL);
			mciSendString("play exmusic", NULL, 0, NULL);//仅播放一次
		}
	}
}

void updateWithInput()//与用户输入有关的更新
{
	if (isExpolde == 0)
	{
		MOUSEMSG m;//记录鼠标消息
		while (MouseHit())//此函数用于检测当前是否有鼠标消息
		{
			m = GetMouseMsg();
			if (m.uMsg == WM_MOUSEMOVE)  //鼠标移动时,飞机坐标等于鼠标位置
			{
				position_x = m.x;
				position_y = m.y;

			}
			else if (m.uMsg == WM_LBUTTONDOWN)//按下鼠标左键时,发射子弹
			{
				mciSendString("close f_gun", NULL, 0, NULL);//先把前面一次的音乐关闭
				mciSendString("open C://images//f_gun.mp3 alias f_gun", NULL, 0, NULL);//打开音乐
				mciSendString("play f_gun", NULL, 0, NULL);//仅播放一次
				bullet_x = position_x;
				bullet_y = position_y - 100;
			}
		}
	}
}
void gameover()//游戏结束
{
	EndBatchDraw();
	closegraph();
}

 

难点:

1.透明化贴图

2.鼠标交互

3.自增自减函数实现子弹和敌机的移动

4.双缓冲绘图解决闪屏问题

不足:

这是我大一上学期时候的课程设计(若需要详细文档可联系我),时间有限(两个星期),只是实现了简单基本的内容,仍有很多不足,希望大佬们多多指导!

开发环境:Visual Studio 2019

编程语言:C语言

  • 5
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值