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