前言
flappy bird是一款在2014年爆火的游戏,相信大家都曾听说过或者玩过,今天我们将会采用C语言来写这个游戏的基本玩法,最重要的是从中接触可视化编程。
代码效果
可视化编程需要图形库,需要自己下载(点击前往下载安装教程),这里我们选择easyx,这个图形库对新手比较友好。
贴图技术
我选择的开发工具是vs2019,去掉了安全检查以及将字符集换成了多字符集(点击前往教程)。
这个游戏主要运用到了一些贴图技术和利用多线程播放音乐的方法。
我们首先需要构建一个窗口并且将我们的背景图片贴上去。
#include <graphics.h>
IMAGE bg[2];// 定义图形变量数组
initgraph(288, 624);// 构建一个宽288,高624的窗口
loadimage(&bj[0], "图片路径");// 将图片赋给图形变量,就相当于给图片起一个名字
loadimage(&bj[1], "图片路径");
putimage(0, 0, &bg[0]);// 在0,0的位置贴上图片
putimage(0, 512, &bg[1]);
因为我使用的素材是天空与地面分开的背景图,所以这里贴了2次。
柱子与鸟
接着便是贴小鸟和柱子的图片了,但是与贴背景图不同的是这里的小鸟和柱子并不是一个规则的图形,所以我们采用透明贴图技术将小鸟和柱子贴上去。具体方法可以参考下面这篇文章。
https://blog.csdn.net/qq969422014/article/details/44536375
因为柱子的高度是随机而且成对出现的,我们需要一个随机数去模拟上面柱子及下面柱子的高度,我们使用结构体的方法去写柱子。
//下面的x,y都指其所在窗口的位置
//定义小鸟的结构体
struct huoyin
{
int x;
int y;
int speed;//小鸟弹跳的距离
};
struct huoyin hero = {
100 , 240 , 70 };
//三对柱子的结构体
struct walls
{
int x, y;
int height;//上面柱子的高
};
struct walls pillar[3];
void pillars(struct walls pillar[],int i)
{
pillar[i].height = rand() % 100 + 120;
pillar[i].x = 288;
pillar[i].y = 0;
}
//贴柱子
void drawWall(struct walls nowpillar)
{
//上面柱子
putimage(nowpillar.x, 0, 52, nowpillar.height, wall, 0, 320 - nowpillar.height, SRCAND);
putimage(nowpillar.x, 0, 52, nowpillar.height, wall + 1, 0, 320 - nowpillar.height, SRCPAINT);
//下面柱子
putimage(nowpillar.x, 512 - (320 - nowpillar.height), 52, 320 - nowpillar.height, wall + 2, 0, 0, SRCAND);
putimage(nowpillar.x, 512 - (320 - nowpillar.height), 52, 320 - nowpillar.height, wall + 3, 0, 0, SRCPAINT);
}
//以时间为种子构建随机函数
#include <time.h>//需要的头文件
srand(time(NULL));
//移动柱子
for (int i = 0; i < 3; i++)
{
pillar[i].x -= 10;
}
//柱子的初始化
for (int i = 0; i < 3; i++)
{
pillars(pillar, i);
//每对柱子等距离
pillar[i].x = 288 + i * 150;
}
//不断创造新的柱子
for (int i = 0; i < 3; i++)
{
drawWall(pillar[i]);
if (pillar[i].x <= -158)
{
pillars(pillar, i);
}
}
介绍一下在贴柱子使用的 putimage(x,y,width,height,&IMAGE,xx,yy)函数,这个函数是从图片(&IMAGE)的 x,y 坐标截取 width 宽与 height 高贴在窗口的 xx,yy 坐标上。
多线程播放音乐
为了不让播放音乐影响画面,我们采用多线程播放音乐。
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")
//播放音乐
DWORD WINAPI playMusic(LPVOID lpvoid)
{
mciSendString("open 卡通弹跳.wav alias music", 0, 0, 0);
mciSendString("play music wait", 0, 0, 0);
mciSendString("close music", 0, 0, 0);
return 0;
}
小鸟的弹跳
接着就要实现使用空格让小鸟弹跳了。
//按键响应
void keyDown()
{
char keys = _getch();
switch(keys)
{
case ' ':
hero.y -= hero.speed;
CreateThread(NULL, NULL, playMusic, NULL, NULL, NULL);
break;
default:
break;
}
}
判断游戏是否结束
//判断游戏是否结束
int overs()
{
if (hero.y < 0 || hero.y > 440 )
return 1;
for (int i = 0; i < 3; i++)
{
if (hero.x > pillar[i].x && hero.x < pillar[i].x + 52 - 12)
{
if(hero.y < pillar[i].height || hero.y > pillar[i].height + 112 + 38)
return 1;
}
else return 0;
}
}
判断游戏结束方面还存在一些问题,如有高见可以留言指出来,感谢!
游戏结束动画
//游戏结束动画
void overMovies()
{
int x = 42, y = 700;
while (y >= 200)
{
putimage(0, 0, &bg[0]);
putimage(0, 512, &bg[1]);
putimage(x, y, &end[0], SRCAND);
putimage(x, y, &end[1], SRCPAINT);
y -= 30;
Sleep(100);//防止出现掩码图与彩图交替出现
}
}
完整代码
#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <time.h>
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")
//背景图\小鸟图\游戏结束图\柱子图
IMAGE bg[2],bird[2][3],end[2],wall[4];
//定义小鸟的结构体
struct huoyin
{
int x;
int y;
int speed;
};
struct huoyin hero = {
100 , 240 , 70 };
//三对柱子的结构体
struct walls
{
int x, y;
int height;
};
struct walls pillar[3];
void pillars(struct walls pillar[],int i)
{
pillar[i].height = rand() % 100 + 120;
pillar[i].x = 288;
pillar[i].y = 0;
}
//批量加载资源(给文件夹里的图片命名)
void jiazai()
{
loadimage(&bg[0], "4.jpg");
loadimage(&bg[1], "5.jpg");
loadimage(&bird[0][0], "bird0_0.png");
loadimage(&bird[1][0], "bird1_0.png");
loadimage(&bird[0][1], "bird0_1.png");
loadimage(&bird[1][1], "bird1_1.png");
loadimage(&bird[0][2], "bird0_2.png");
loadimage(&bird[1][2], "bird1_2.png");
loadimage(&end[0], "11.jpg");
loadimage(&end[1], "8.jpg");
loadimage(&wall[0], "9.jpg");
loadimage(&wall[1], "6.jpg");
loadimage(&wall[2], "10.jpg");
loadimage(&wall[3], "7.jpg");
}
//透明贴图(掩码图加原图)
/* void drawHero() { putimage(hero.x, hero.y, &bird[0][1], SRCAND); putimage(hero.x, hero.y, &bird[1][1], SRCPAINT); }*/
//贴柱子*****
void drawWall(struct walls nowpillar)
{
//上面柱子
putimage(nowpillar.x, 0, 52, nowpillar.height, wall, 0, 320 - nowpillar.height, SRCAND);
putimage(nowpillar.x, 0, 52, nowpillar.height, wall + 1, 0, 320 - nowpillar.height, SRCPAINT);
//下面柱子
putimage(nowpillar.x, 512 - (320 - nowpillar.height), 52, 320 - nowpillar.height, wall + 2, 0, 0, SRCAND);
putimage(nowpillar.x, 512 - (320 - nowpillar.height), 52, 320 - nowpillar.height, wall + 3, 0, 0, SRCPAINT);
}
//播放音乐
DWORD WINAPI playMusic(LPVOID lpvoid)
{
mciSendString("open 卡通弹跳.wav alias music", 0, 0, 0);
mciSendString("play music wait", 0, 0, 0);
mciSendString("close music", 0, 0, 0);
return 0;
}
//按键响应
void keyDown()
{
char keys = _getch();
switch(keys)
{
case ' ':
hero.y -= hero.speed;
CreateThread(NULL, NULL, playMusic, NULL, NULL, NULL);
break;
default:
break;
}
}
//判断游戏是否结束
int overs()
{
if (hero.y < 0 || hero.y > 440 )
return 1;
for (int i = 0; i < 3; i++)
{
if (hero.x > pillar[i].x && hero.x < pillar[i].x + 52 - 12)
{
if(hero.y < pillar[i].height || hero.y > pillar[i].height + 112 + 38)
return 1;
}
else return 0;
}
}
//游戏结束动画
void overMovies()
{
int x = 42, y = 700;
while (y >= 200)
{
putimage(0, 0, &bg[0]);
putimage(0, 512, &bg[1]);
putimage(x, y, &end[0], SRCAND);
putimage(x, y, &end[1], SRCPAINT);
y -= 30;
Sleep(100);
}
}
int main()
{
srand(time(NULL));
jiazai();
//柱子的初始化
for (int i = 0; i < 3; i++)
{
pillars(pillar, i);
//每对柱子等距离
pillar[i].x = 288 + i * 150;
}
initgraph(288, 624);
for (int num = 0; num < 3; num++)
{
putimage(0, 0, &bg[0]);
putimage(0, 512, &bg[1]);
putimage(hero.x, hero.y, &bird[1][num], SRCAND);
putimage(hero.x, hero.y, &bird[0][num], SRCPAINT);
//移动柱子
for (int i = 0; i < 3; i++)
{
pillar[i].x -= 10;
}
if (overs())
break;
//不断创造新的柱子
for (int i = 0; i < 3; i++)
{
drawWall(pillar[i]);
if (pillar[i].x <= -158)
{
pillars(pillar, i);
}
}
if (overs())
break;
hero.y += 20;
if (overs())
break;
if (_kbhit())
{
keyDown();
if (overs())
break;
}
if (num == 2)num = 0;
Sleep(100);
}
Sleep(240);
overMovies();
_getch();
closegraph();
system("pause");
return 0;
}
因为我还给小鸟做了扇动翅膀的动画,所以这个for (int num = 0; num < 3; num++)循环是加载鸟的三张图片。
用到的素材
由于有小伙伴找反映不到对应的素材,所以我将素材也放在网盘上分享了
链接:https://pan.baidu.com/s/1ovDvFtqIKIhoCfn0Z11PkA
提取码:1234
游戏素材网站
-
The Spriters Resource
地址:https://www.spriters-resource.com
https://www.sounds-resource.com
介绍:非常丰富齐全的游戏素材网站,并且按照游戏主机分类,包括 NES、PS、GBA 等各大游戏平台的游戏,素材基本都是抠好图的 PNG 格式,非常好用。想做高仿游戏的同学不要错过。还有 3D 模型、贴图、音效等素材。就是国外网站,访问速度有点慢。
-
Open Game Art
地址:https://opengameart.org介绍:很全很好用的游戏资源网站,就是国外网站的访问速度有点慢。
-
爱给网
地址:http://www.aigei.com介绍:国内的游戏素材网站,也很好用齐全。不过有个不足:不登录不让下载。
总结
这是第一次在CSDN上写文章,如有不妥之处还请多多包涵。
今天的文章C语言实现flappy bird(可视化编程)分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/9255.html