C语言开发打气球小游戏

首先我们写一下项目所需要的头文件

#include<stdio.h>//标准输入输出头文件
#include<math.h>//数学库头文件
#include<graphics.h>//EasyX图形库头文件
#include<mmsystem.h>//多媒体音乐库头文件
#pragma comment(lib,"winmm.lib")//导入winmm库
#pragma warning(disable : 4996)//4996警告杂注

接下来在涵盖几个宏定义进来

#define WIDTH 600//窗口宽度
#define WEIGHT 400//窗口高度
#define NUM 10//屏幕上所产生气球,子弹的最大数量

然后我们开始打造一个漂亮的欢迎界面,这里需要二张图片,我把它贴出来。
1.jpg:

2.jpg:

图片有了,上代码,首先先在全局部分定义图片属性

IMAGE img[2];
void Welcome()//实现欢迎界面的函数
{loadimage(&img[0], "1.jpg",150,400);//加载图片loadimage(&img[1], "2.jpg", 450, 400);//参数含义(图片地址,图片路径,图片宽,图片高)putimage(0,0,&img[0]);//显示图片putimage(150, 0, &img[1]);//参数含义(显示坐标x,y+图片属性)while (1){if (MouseHit())//判断是否有鼠标消息{MOUSEMSG msg = GetMouseMsg();//获取当前鼠标消息if (msg.uMsg == WM_LBUTTONDOWN)//如果鼠标左键按下{return;//返回主函数}}}
}

接下来我们开始准备音乐部分(音乐不方便贴出来,可以自己去网上找合适的)
我们为了不影响程序运行效率,决定使用多线程的方式实现音乐播放
背景音乐:

DWORD WINAPI Music(LPVOID lpParamter)
{mciSendString("open music.mp3 alias BGM", 0, 0, 0);//加载音乐mciSendString("play BGM repeat", 0, 0, 0);//播放音乐//repeat代表无限循环播放while (1);
}

气球爆炸音效:

DWORD WINAPI MCC(LPVOID lpParamter)
{mciSendString("open fill.mp3 alias BCC", 0, 0, 0);mciSendString("play BCC", 0, 0, 0);return 0;
}

做游戏之前,我们先把游戏中的炮台,气球,子弹这3个元素用结构体抽象出来

struct Battery//炮台
{//炮管二点的横纵坐标int x;int y;int endx;int endy;int len;//炮管发射出来的子弹的速度int speed;//炮管倾斜的弧度double radian;//玩家的游戏得分int score;
}bat;
struct bullet
{//子弹的横纵坐标int x;int y;//子弹的半径int r;//子弹向炮管方向的位移量int vx;int vy;//子弹是否存在的标志bool falg;//炮管倾斜的弧度double radian;//子弹的颜色DWORD color;
}ball[NUM];
struct Balloon
{//气球的横纵坐标int x;int y;//气球的颜色DWORD color;//气球是否存在的标志bool falg;
}boon[NUM];

下面我们来初始化数据

void GameInit()
{srand(GetTickCount());bat.x = WIDTH / 2;bat.y = WEIGHT - 10;bat.len = 50;bat.endx = bat.x;bat.endy = bat.y-bat.len;bat.speed = 7;bat.score = 0;for (int i = 0; i < NUM; i++){ball[i].falg = false;}//因为一开始子弹不存在,子弹需要鼠标点击才生成一个,所以我们先初始化为不存在(false代表不存在)for (int i = 0; i < NUM; i++){//随机坐标boon[i].x = rand() % (WIDTH-30);boon[i].y = rand() % (WEIGHT-60);//随机颜色boon[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);boon[i].falg = true;}//因为气球是游戏一开始就要有的,所以我们把它全部初始化为true(存在),并且初始化坐标,颜色
}

接下来我们来把数据变得“看的见”

void GameDraw()
{BeginBatchDraw();//开始双缓冲setbkcolor(RGB(114, 191, 207));//设置窗口背景颜色cleardevice();//清屏for (int i = 0; i < NUM; i++)//遍历所有气球(所有包括存在和不存在){if (boon[i].falg==true)//如果气球存在{//画气球setlinestyle(PS_SOLID, 0.1);//设置线条风格  PS_SOLID表示实线,0.1表示线条粗细程度setlinecolor(WHITE);//设置线条颜色setfillcolor(boon[i].color);//设置填充颜色fillellipse(boon[i].x, boon[i].y, boon[i].x + 40, boon[i].y + 50);//画填充椭圆//画气泡arc(boon[i].x + 5, boon[i].y + 5, boon[i].x + 35, boon[i].y + 45, 0, 1.4);//画弧//画绳子arc(boon[i].x + 15, boon[i].y + 50, boon[i].x + 25, boon[i].y + 75, 5.2, 1.5);}}//画炮台setlinestyle(PS_SOLID, 2);circle(bat.x,bat.y, 40);//画圆setfillcolor(BLACK);solidcircle(bat.x, bat.y, 5);//画实心圆//画炮管setlinecolor(BLACK);setlinestyle(PS_SOLID, 5);line(bat.x, bat.y, bat.endx, bat.endy);//绘制子弹for (int i = 0; i < NUM; i++)//遍历所有子弹(所有包括存在和不存在){if (ball[i].falg == true)//如果子弹存在{setfillcolor(ball[i].color);solidcircle(ball[i].x, ball[i].y, ball[i].r);}}char bar[80];//初始化字符串sprintf(bar, "分数:%d", bat.score);//往这个字符串里写东西setbkmode(0);//去掉文字背景settextcolor(YELLOW);//设置文字颜色settextstyle(40, 0, "楷体");//设置文字字体大小和字体样式(注:0表示编译器自适应)outtextxy(0, 0, bar);//设置文字显示位置,以及所需要显示的字符串EndBatchDraw();//结束双缓冲
}

我们的炮管现在还是固定的,我们需要让它跟着鼠标动起来,走,现在我们去实现鼠标操作

void MouseEvent()
{if (MouseHit())//如果有鼠标消息{MOUSEMSG msg = GetMouseMsg();//获取当前鼠标消息bat.radian = atan2((double)bat.y - msg.y, (double)msg.x - bat.x);//使用数学的正切求出炮台的炮管的倾斜弧度//同样使用数学知识求出二条直角边的长度bat.endx = bat.x + cos(bat.radian) * bat.len;//正弦bat.endy = bat.y - sin(bat.radian) * bat.len;//余弦if (msg.uMsg == WM_LBUTTONDOWN)//如果鼠标左键按下{CreatBullet();//产生子弹}}
}

那么鼠标操作这一步又涉及到子弹的产生,所以我们一起去看看子弹是如何产生的

//生成子弹
void CreatBullet()
{for (int i = 0; i < NUM; i++)//遍历所有子弹(所有包括存在和不存在){if (ball[i].falg == false)//如果子弹不存在才生成{ball[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);//颜色//设置子弹坐标,让子弹从炮管出来ball[i].x = bat.endx;ball[i].y = bat.endy;ball[i].radian = bat.radian;//让子弹运动方向的水平弧度等于当前炮管的水平弧度//利用数学的正弦,余弦知识求出子弹的位移量,bat.speed是子弹的速度,一开始已经在炮台的结构体里面定义好了ball[i].vx = cos(ball[i].radian) * bat.speed;ball[i].vy = sin(ball[i].radian) * bat.speed;//设置子弹的大小(圆的半径)ball[i].r = 5;//最后一定要把子弹改为存在,好让GameDraw函数绘制出来ball[i].falg = true;//生成完一个子弹一定要break跳出for循环,否则程序会把所有子弹全部生成完,但我只要一个break;}}
}

子弹生成完了我们也不能让它摆在那里不动,我们得让它飞,所以我们去实现一个函数让子弹移动

void BulletMove()
{for (int i = 0; i < NUM; i++)//遍历所有子弹(所有包括存在和不存在){if (ball[i].falg==true)//子弹存在才移动{//ball[i].vx,ball[i].vy我们在生成子弹里面就求出来了,这里我们就直接用ball[i].x += ball[i].vx;ball[i].y -= ball[i].vy;}}
}

这时你会发现你打掉(宏定义)NUM个子弹后就没有了,这是什么原因呢?走,我们一起去升级一下这个函数

void BulletMove()
{for (int i = 0; i < NUM; i++)//遍历所有子弹(所有包括存在和不存在){if (ball[i].falg==true)//子弹存在才移动{//ball[i].vx,ball[i].vy我们在生成子弹里面就求出来了,这里我们就直接用ball[i].x += ball[i].vx;ball[i].y -= ball[i].vy;if (ball[i].x<0 || ball[i].x>WIDTH || ball[i].y<0 || ball[i].y>WEIGHT){ball[i].falg = false;}//如果子弹打出窗口了,就把该子弹设置为不存在,这样鼠标点击就可以继续生成子弹了(保证窗口一直可以容纳(宏定义)NUM个子弹)}}
}

子弹移动了该气球了

//气球移动
void BalloonMove(int speed)
{for (int i = 0; i < NUM; i++)//遍历所有气球(所有涵盖存在和不存在){if (boon[i].falg == true)//如果气球存在{//  %50的概率,让气球随风摇摆if (rand() % 2 == 1){boon[i].x++;}else{boon[i].x--;}//气球上升boon[i].y -= speed;}
}

然后我们会发现会产生与子弹移动同样的问题,气球一去不复返,所以我们升级一下这个函数

//气球移动
void BalloonMove(int speed)
{for (int i = 0; i < NUM; i++)//遍历所有气球(所有涵盖存在和不存在){if (boon[i].falg == true)//如果气球存在{//  %50的概率,让气球随风摇摆if (rand() % 2 == 1){boon[i].x++;}else{boon[i].x--;}//气球上升boon[i].y -= speed;if (boon[i].x-40<0 || boon[i].x>WIDTH+40 || boon[i].y+50<0 || boon[i].y>WEIGHT)//如果气球升到了窗口之外{boon[i].falg = false;//把气球设置为不存在CreatBall();//调用产生气球的函数(气球飞离窗口)}}
}

好,接下来我们来实现一下产生气球的函数

//产生气球
void CreatBall()
{for (int i = 0; i < NUM; i++)//遍历所有气球(所有涵盖存在与不存在){if (boon[i].falg == false)//如果气球不存在{//随机气球坐标boon[i].x = rand() % (WIDTH - 30);boon[i].y = (rand() % 100) + WEIGHT;//随机气球颜色boon[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);//生成完成把气球设置为存在boon[i].falg = true;break;//同理,只需要一个,break}}
}

现在一切准备就绪,开始打气球

//开始游戏
void PlayGame()
{for (int i = 0; i < NUM; i++)//遍历所有气球(所有涵盖存在和不存在){if (boon[i].falg == false)//如果气球不存在continue;//跳过此次循环剩余部分,执行下一次循环判定for (int j = 0; j < NUM; j++)//遍历所有子弹(所有涵盖存在和不存在){if (ball[j].falg == false)//如果子弹不存在continue;//跳过此次循环剩余部分,执行下一次循环判定if (ball[j].x > boon[i].x && ball[j].x<boon[i].x + 40 &&ball[j].y>boon[i].y && ball[j].y < boon[i].y + 50)//如果子弹与气球重叠(打到了气球){CreateThread(NULL, 0, MCC, NULL, 0, NULL);//执行多线程,播放气球爆炸音效ball[j].falg = false;//子弹设置为不存在boon[i].falg = false;//气球设置为不存在bat.score++;//玩家分数加  1CreatBall();//生成气球(气球被打)}}}
}

下面我们把主函数(程序的入口,程序的主干)写出来

int main()
{initgraph(WIDTH, WEIGHT);//创建窗口CreateThread(NULL, 0, Music, NULL, 0, NULL);//调用多线程,循环播放背景音乐Welcome();//欢迎界面GameInit();//数据初始化while (1)//死循环{MouseEvent();//鼠标操作GameDraw();//绘制(让游戏可视化)BulletMove();//子弹移动BalloonMove(1);//气球移动Sleep(1);//适当延时PlayGame();//开始打气球}getchar();//防止闪屏
}

最后,博主送你源代码,感谢你认真的观看(因为我自己写代码很少注释,所以源代码注释少)但上面的详解可是注释慢慢,为了方便大家理解。

#include<stdio.h>
#include<math.h>
#include<graphics.h>
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")
#pragma warning(disable : 4996)
#define WIDTH 600
#define WEIGHT 400
#define NUM 10
struct Battery
{int x;int y;int endx;int endy;int len;int speed;double radian;int score;
}bat;
struct bullet
{int x;int y;int r;int vx;int vy;bool falg;double radian;DWORD color;
}ball[NUM];
struct Balloon
{int x;int y;DWORD color;bool falg;
}boon[NUM];
IMAGE img[2];
DWORD WINAPI MCC(LPVOID lpParamter)
{mciSendString("open fill.mp3 alias BCC", 0, 0, 0);mciSendString("play BCC", 0, 0, 0);return 0;
}
DWORD WINAPI Music(LPVOID lpParamter)
{mciSendString("open music.mp3 alias BGM", 0, 0, 0);mciSendString("play BGM repeat", 0, 0, 0);while (1);
}
void Welcome()
{loadimage(&img[0], "1.jpg",150,400);loadimage(&img[1], "2.jpg", 450, 400);putimage(0,0,&img[0]);putimage(150, 0, &img[1]);while (1){if (MouseHit()){MOUSEMSG msg = GetMouseMsg();if (msg.uMsg == WM_LBUTTONDOWN){return;}}}
}
void GameInit()
{srand(GetTickCount());bat.x = WIDTH / 2;bat.y = WEIGHT - 10;bat.len = 50;bat.endx = bat.x;bat.endy = bat.y-bat.len;bat.speed = 7;bat.score = 0;for (int i = 0; i < NUM; i++){ball[i].falg = false;}for (int i = 0; i < NUM; i++){boon[i].x = rand() % (WIDTH-30);boon[i].y = rand() % (WEIGHT-60);boon[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);boon[i].falg = true;}
}
void GameDraw()
{BeginBatchDraw();setbkcolor(RGB(114, 191, 207));cleardevice();for (int i = 0; i < NUM; i++){if (boon[i].falg==true){//画气球setlinestyle(PS_SOLID, 0.1);setlinecolor(WHITE);setfillcolor(boon[i].color);fillellipse(boon[i].x, boon[i].y, boon[i].x + 40, boon[i].y + 50);//画气泡arc(boon[i].x + 5, boon[i].y + 5, boon[i].x + 35, boon[i].y + 45, 0, 1.4);//画绳子arc(boon[i].x + 15, boon[i].y + 50, boon[i].x + 25, boon[i].y + 75, 5.2, 1.5);}}//画炮台setlinestyle(PS_SOLID, 2);circle(bat.x,bat.y, 40);setfillcolor(BLACK);solidcircle(bat.x, bat.y, 5);//画炮管setlinecolor(BLACK);setlinestyle(PS_SOLID, 5);line(bat.x, bat.y, bat.endx, bat.endy);//绘制子弹for (int i = 0; i < NUM; i++){if (ball[i].falg == true){setfillcolor(ball[i].color);solidcircle(ball[i].x, ball[i].y, ball[i].r);}}char bar[80];sprintf(bar, "分数:%d", bat.score);setbkmode(0);settextcolor(YELLOW);settextstyle(40, 0, "楷体");outtextxy(0, 0, bar);EndBatchDraw();
}
//产生气球
void CreatBall()
{for (int i = 0; i < NUM; i++){if (boon[i].falg == false){boon[i].x = rand() % (WIDTH - 30);boon[i].y = (rand() % 100) + WEIGHT;boon[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);boon[i].falg = true;break;}}
}
//开始游戏
void PlayGame()
{for (int i = 0; i < NUM; i++){if (boon[i].falg == false)continue;for (int j = 0; j < NUM; j++){if (ball[j].falg == false)continue;if (ball[j].x > boon[i].x && ball[j].x<boon[i].x + 40 &&ball[j].y>boon[i].y && ball[j].y < boon[i].y + 50){CreateThread(NULL, 0, MCC, NULL, 0, NULL);ball[j].falg = false;boon[i].falg = false;bat.score++;CreatBall();}}}
}
//气球移动
void BalloonMove(int speed)
{for (int i = 0; i < NUM; i++){if (boon[i].falg == true){if (rand() % 2 == 1){boon[i].x++;}else{boon[i].x--;}boon[i].y -= speed;if (boon[i].x-40<0 || boon[i].x>WIDTH+40 || boon[i].y+50<0 || boon[i].y>WEIGHT){boon[i].falg = false;CreatBall();}}}
}
//生成子弹
void CreatBullet()
{for (int i = 0; i < NUM; i++){if (ball[i].falg == false){ball[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);ball[i].x = bat.endx;ball[i].y = bat.endy;ball[i].radian = bat.radian;ball[i].vx = cos(ball[i].radian) * bat.speed;ball[i].vy = sin(ball[i].radian) * bat.speed;ball[i].r = 5;ball[i].falg = true;break;}}
}
//移动子弹
void BulletMove()
{for (int i = 0; i < NUM; i++){if (ball[i].falg==true){ball[i].x += ball[i].vx;ball[i].y -= ball[i].vy;if (ball[i].x<0 || ball[i].x>WIDTH || ball[i].y<0 || ball[i].y>WEIGHT){ball[i].falg = false;}}}
}
//鼠标操作
void MouseEvent()
{if (MouseHit()){MOUSEMSG msg = GetMouseMsg();bat.radian = atan2((double)bat.y - msg.y, (double)msg.x - bat.x);bat.endx = bat.x + cos(bat.radian) * bat.len;bat.endy = bat.y - sin(bat.radian) * bat.len;if (msg.uMsg == WM_LBUTTONDOWN){CreatBullet();}}
}
int main()
{initgraph(WIDTH, WEIGHT);CreateThread(NULL, 0, Music, NULL, 0, NULL);Welcome();GameInit();while (1){MouseEvent();GameDraw();BulletMove();BalloonMove(1);Sleep(1);PlayGame();}getchar();
}

Say your GoodBey!!!
好了,祝大家学习愉快,趁青春,上代码。

C语言开发打气球小游戏相关推荐

  1. java代码实现打气球游戏_javascript+css3开发打气球小游戏完整代码

    效果知识点: css3画气球, 自定义属性运用,随机阵列, DOM元素操作,高级回调函数与参数复传,动态布局,鼠标事件,定时器运用,CSS3新增样式等. css代码如下: {margin:0;padd ...

  2. java代码实现打气球游戏_关于javascript和css3开发打气球小游戏的完整代码

    这篇文章主要介绍了关于javascript和css3开发打气球小游戏的完整代码,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 这是一个简单但是印象深刻的小游戏,打气球小游戏的实现代码, ...

  3. html5 打气球小游戏,javascript开发打气球小游戏

    web前端群,189394454,有视频.源码.学习方法等大量干货分享 效果知识点:css3画气球, 自定义属性运用,随机阵列, DOM元素操作,高级回调函数与参数复传,动态布局,鼠标事件,定时器运用 ...

  4. c语言使用easyX图形库制作打气球小游戏

    大一c语言使用easyX图形库制作打气球小游戏 如果你是入门easyX图形库,那么这个打气球小游戏将会是和不错的入门项目选择,easyX开创了可视化窗口,使用户更加直观的了解到对象的变化,总代码以及素 ...

  5. C语言实训——经典小游戏马里奥开发day 1

    C语言实训--经典小游戏马里奥开发day 1 卷轴式地图 一.关于卷轴式地图 ​ 在之前的开发尝试之中,我曾经使用的是地图移动但是马里奥保持在一个固定的点来实现马里奥的移动,但是我发现了几个问题: 1 ...

  6. python打气球小游戏(一)

    欢迎加入我们卧虎藏龙的python讨论qq群:729683466 导  语 上期 给大家讲了一个<推箱子>游戏 这是是正宗的pygame模块开发的 这一期 给大家介绍一个非常好玩的模块tu ...

  7. 226款H5手机端小游戏源码下载 - HTML+JavaScript开发的网页小游戏开源源码大合集,经过亲测可用!

    演示端:http://game.tutou.wang/  (手机访问)  可在线试玩的分享. 链接:https://pan.baidu.com/s/1-R6wEZjLXYm0iowBJLFS8g?pw ...

  8. 邹伟:如何开发一款小游戏

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 邹伟,后端高级工程师,对前端也有一定开发经验.2010年于华南理工大学毕业后加入腾讯,参与CDB.TGW等云服务研发,现主要负责微信游戏业务 ...

  9. 邹伟:如何开发一款小游戏 1

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 邹伟,后端高级工程师,对前端也有一定开发经验.2010年于华南理工大学毕业后加入腾讯,参与CDB.TGW等云服务研发,现主要负责微信游戏业务 ...

最新文章

  1. Google Duplex语气自然流利,外媒却质疑其演示通话录音是伪造的
  2. 容器:我的java笔记(2)
  3. 前端学习(2133):前端代码复杂带来的问题
  4. 网站 html 中英文切换 - API 总结篇
  5. nmealib linux编译,nmealib的使用可以缩短GPS的开发周期
  6. kafka消息确认机制
  7. 不设置DIV的宽高,让它相对于页面水平垂直居中
  8. python车牌字符分割_OpenCV+Python识别车牌和字符分割的实现
  9. php复姓怎么排序,按姓氏笔画排名怎么排列了
  10. 深度评论 | 雷军这么努力,为什么小米还是干不过OV
  11. eth入门之web2 与 web3 的对比
  12. 计算机显示错误屏幕,如何解决显示器分辨率错误
  13. 我在富士康挨踢了七年(十六. 跳楼年,终于认识了我自己)
  14. 周爱民-javascript
  15. 计算机学院杨洋,杨洋-地球科学与技术学院
  16. 2020年茶艺师(初级)考试及茶艺师(初级)实操考试视频
  17. 基于R语言、MaxEnt模型融合技术的物种分布模拟、参数优化方法、结果分析制图与论文写作
  18. 新经济的蛀虫——互联网大厂反腐那些事
  19. yuv 10bit 8bit
  20. linux安装mysql centos_Linux CentOS安装Mysql

热门文章

  1. 旅行青蛙(旅かえる)的最全攻略(不懂日语的可以看看)
  2. 基于SSM框架的外卖订餐系统
  3. 漫天杂想系列之五:2018年总结
  4. 批量修改指定文件夹里面相同类型文件的扩展名(转自Github,原作者Crag Richards)
  5. 正版Mincraft登录问题:微软账号不能登录
  6. 报错:For input string
  7. 走进Visual C++
  8. 大数据和人工智能的关系,超全解析 1
  9. 二维泊松方程求解--点迭代法
  10. 连续词袋模型(Continous bag of words, CBOW)