大家好 , 我是逼哥 , 记得每天好好学习 , 天天向上 , 尤其是大学生 . 不要荒废学业.
首先说明 , 我使用的开发环境是 vs2017 , 有些函数方法可能不通用 ,大家可以百度下其他方法. 向童老师致敬
第一步:先读取本地的背景图片
1 . 这第一步就非常简单 , 只需要先读取背景图 , 并且显示出来就可以.
#include <graphics.h>
#include <conio.h>
void main()
{
initgraph(350,600);
IMAGE bird_bg; // 小鸟图片背景
loadimage(&bird_bg , _T("D:\\桌面\\super_bird\\background.jpg") );
putimage(0, 0, &bird_bg); // 在坐标(0 , 0 )位置显示IMAGE 对象
_getch(); //防止窗口关闭
closegraph();
}
2 . 处理小鸟
如果直接显示小鸟
因为我们显示的小鸟图片是矩形 , 这样的小鸟是留有白色区域棱角就不好看了 ,此时就需要用函数去处理 , 是白色区域透明化
拿到小鸟的遮罩和原图
可以利用美图秀秀进行抠图 ,扣出原图和遮罩.
NOTSRCERASE 先对遮罩进行处理 , 使得遮罩白色变黑 ,黑色区域变透明
SRCINVERT 在对小鸟原图处理
一定要遮罩在前 ,作为背景 , 小鸟在后
让两张处理过的图片在同一区域进行效果叠加 , 看小效果
#include <graphics.h>
#include <conio.h>
void main()
{
initgraph(350,600);
IMAGE bird_bg; // 小鸟图片背景
loadimage(&bird_bg , _T("D:\\桌面\\super_bird\\background.jpg") );
putimage(0, 0, &bird_bg); // 在坐标(0 , 0 )位置显示IMAGE 对象
IMAGE im_bird_shade; //遮罩
IMAGE im_bird;
loadimage(&im_bird_shade, _T("D:\\桌面\\super_bird\\bird1.jpg"));
loadimage(&im_bird, _T("D:\\桌面\\super_bird\\bird2.jpg"));
// 一定要遮罩在前 ,作为背景 , 小鸟在后
putimage(100, 200, &im_bird_shade, NOTSRCERASE); //NOTSRCERASE -->目标图像 = NOT (目标图像 OR 源图像) //遮罩的黑色进行透明处理 , 白色区域显黑色
putimage(100, 200, &im_bird , SRCINVERT); //SRCINVERT---> 目标图像 = 目标图像 XOR 源图像 (三原色进行系列取反运算)
_getch(); //防止窗口关闭
closegraph(); //
}
版本升级处理 , 对 显示数据 进行 模块化 , 用函数来封装 . 修改后的代码.
#include <graphics.h>
#include <conio.h>
// 引用 Windows Multimedia API
#pragma comment(lib,"Winmm.lib")
//全局变量
IMAGE img_bk, img_bd1, img_bd2, img_bar_up1, img_bar_up2, img_bar_down1, img_bar_down2; int bird_x;
int bird_y;
void startup()
{
initgraph(350, 600);
loadimage(&img_bk, _T("D:\\桌面\\super_bird\\background.jpg") );
loadimage(&img_bd1, _T("D:\\桌面\\super_bird\\bird1.jpg"));
loadimage(&img_bd2, _T("D:\\桌面\\super_bird\\bird2.jpg"));
bird_x = 50;
bird_y = 200;
BeginBatchDraw();
}
void show()
{
putimage(0, 0, &img_bk); // 显示背景
putimage(bird_x, bird_y, &img_bd1, NOTSRCERASE); // 遮罩透明处理
putimage(bird_x, bird_y, &img_bd2, SRCINVERT);// 显示小鸟
FlushBatchDraw();
Sleep(50);
}
void updateWithoutInput()
{
}
void updateWithInput()
{
}
void gameover()
{
EndBatchDraw();
_getch();
closegraph();
}
int main()
{
startup(); // 数据初始化
while (1) // 游戏循环执行
{
show(); // 显示画面
updateWithoutInput(); // 与用户输入无关的更新
updateWithInput(); // 与用户输入有关的更新
}
gameover(); // 游戏结束、后续处理
return 0;
}
第三步: 显示障碍物 ,并且让小鸟自由下落
1. 障碍物 ,和处理小鸟一致 , 只要读取图片 , 处理遮罩 , 处理障碍物原图 , 叠加显示即可
2. 小鸟自由下落 , 就是 改变 小鸟图片的左上角的起始绘画点的坐标. 只能上下自自由下落 ,改变小鸟的Y轴坐标即可 .
3. 移动障碍物
4.障碍物 随机生成 , 并且随机高度
5.小鸟越过障碍物 , 并计算得分 , 撞上柱子则死亡
看下效果
最后, 贴出所有的代码 , 环境是 : VS2017
#include <graphics.h>
#include <conio.h>
// 引用 Windows Multimedia API
#pragma comment(lib,"Winmm.lib")
#define width 350
#define high 600
//全局变量
IMAGE img_bk, img_bd1, img_bd2, img_bar_up1, img_bar_up2, img_bar_down1, img_bar_down2;
int bird_x , bird_y;
int bar1_x, bar1_xDown, bar1_xTop; // 障碍物1的相关坐标
int score; // 得分,经过障碍物的个数
void startup()
{
initgraph(width, high);
loadimage(&img_bk, _T("D:\\桌面\\super_bird\\background.jpg") );
loadimage(&img_bd1, _T("D:\\桌面\\super_bird\\bird1.jpg"));
loadimage(&img_bd2, _T("D:\\桌面\\super_bird\\bird2.jpg"));
//显示上下障碍物
loadimage(&img_bar_up1, _T("D:\\桌面\\super_bird\\bar_up1.gif"));
loadimage(&img_bar_up2, _T("D:\\桌面\\super_bird\\bar_up2.gif"));
loadimage(&img_bar_down1, _T("D:\\桌面\\super_bird\\bar_down1.gif"));
loadimage(&img_bar_down2, _T("D:\\桌面\\super_bird\\bar_down2.gif"));
//小鸟
bird_x = width / 7; // 50
bird_y = high / 3; //200
score = 0;
//障碍物
bar1_x = width;
int randPosition = rand() % (high - 400) +50; // 随机数就只在 50-250
//注意这是上障碍物的起始坐标
bar1_xTop = randPosition - high; // top 的范围就在 -550 ------ -350 之间
// 上障碍物画完 , 画下障碍物 , 间隔100
bar1_xDown = bar1_xTop +high + 100;
BeginBatchDraw();
}
void show()
{
putimage(0, 0, &img_bk); // 显示背景
putimage(bird_x, bird_y, &img_bd1, NOTSRCERASE); // 遮罩透明处理
putimage(bird_x, bird_y, &img_bd2, SRCINVERT);// 显示小鸟
//显示 障碍物
putimage(bar1_x, bar1_xTop, &img_bar_up1, NOTSRCERASE); // 遮罩透明处理
putimage(bar1_x, bar1_xTop, &img_bar_up2, SRCINVERT);// 显示上障碍物
putimage(bar1_x, bar1_xDown, &img_bar_down1, NOTSRCERASE); // 遮罩透明处理
putimage(bar1_x, bar1_xDown, &img_bar_down2, SRCINVERT);// 显示下障碍物
FlushBatchDraw();
Sleep(50);
}
void updateWithoutInput()
{
// 输入空格进行控制小鸟
char input;
if (_kbhit())
{
input = _getch();
if (input == ' ' && bird_y > 20)
bird_y -= 25;
}
}
// 图形更新
void updateWithInput()
{
// 小鸟不能飞出界面
if (bird_y < 0 || bird_y > 556)
_exit(0); // 结束
// 小鸟的坐标不能出框 , Y轴不能小于0 , 不能大于580
if (0 < bird_y && bird_y < 580)
bird_y += 3;
// 障碍物的移动
if (bar1_x > -140)
bar1_x -= 2;
else
{
// 重新生成
bar1_x = width;
//障碍物
int randPosition = rand() % (high - 400) + 50; // 随机数就只在 50-250
//注意这是上障碍物的起始坐标
bar1_xTop = randPosition - high; // top 的范围就在 -550 ------ -350 之间
// 上障碍物画完 , 画下障碍物 , 间隔100
bar1_xDown = bar1_xTop + high + 100;
}
//得分计算 小鸟的宽度为34 , 柱子宽度为140
if ( (bar1_x < bird_x + 34) && (bar1_x +140 > bird_x + 34) )
{
if ((bird_y > bar1_xTop +600) && (bird_y < bar1_xDown))
{
score++;
}
else
{
_exit(0);
}
}
}
void gameover()
{
EndBatchDraw();
_getch();
closegraph();
}
int main()
{
startup(); // 数据初始化
while (1) // 游戏循环执行
{
show(); // 显示画面
updateWithoutInput(); // 界面的更新
updateWithInput(); // 与用户输入有关的更新
}
gameover(); // 游戏结束、后续处理
return 0;
}
到这里,我们可以配上音乐
可以引用 Windows Multimedia API
使用 #pragma comment(lib,"Winmm.lib")
#include <graphics.h>
#include <conio.h>
// 引用 Windows Multimedia API
#pragma comment(lib,"Winmm.lib")
#define width 350
#define high 600
//全局变量
IMAGE img_bk, img_bd1, img_bd2, img_bar_up1, img_bar_up2, img_bar_down1, img_bar_down2;
int bird_x , bird_y;
int bar1_x, bar1_xDown, bar1_xTop; // 障碍物1的相关坐标
int score; // 得分,经过障碍物的个数
void startup()
{
initgraph(width, high);
loadimage(&img_bk, _T("D:\\桌面\\super_bird\\background.jpg") );
loadimage(&img_bd1, _T("D:\\桌面\\super_bird\\bird1.jpg"));
loadimage(&img_bd2, _T("D:\\桌面\\super_bird\\bird2.jpg"));
//显示上下障碍物
loadimage(&img_bar_up1, _T("D:\\桌面\\super_bird\\bar_up1.gif"));
loadimage(&img_bar_up2, _T("D:\\桌面\\super_bird\\bar_up2.gif"));
loadimage(&img_bar_down1, _T("D:\\桌面\\super_bird\\bar_down1.gif"));
loadimage(&img_bar_down2, _T("D:\\桌面\\super_bird\\bar_down2.gif"));
//小鸟
bird_x = width / 7; // 50
bird_y = high / 3; //200
score = 0;
//障碍物
bar1_x = width;
int randPosition = rand() % (high - 400) +50; // 随机数就只在 50-250
//注意这是上障碍物的起始坐标
bar1_xTop = randPosition - high; // top 的范围就在 -550 ------ -350 之间
// 上障碍物画完 , 画下障碍物 , 间隔100
bar1_xDown = bar1_xTop +high + 100;
BeginBatchDraw();
mciSendString(_T("open D:\\桌面\\super_bird\\background.mp3 alias bkmusic"), NULL, 0, NULL);//打开背景音乐
mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL); // 循环播放
}
void show()
{
putimage(0, 0, &img_bk); // 显示背景
putimage(bird_x, bird_y, &img_bd1, NOTSRCERASE); // 遮罩透明处理
putimage(bird_x, bird_y, &img_bd2, SRCINVERT);// 显示小鸟
//显示 障碍物
putimage(bar1_x, bar1_xTop, &img_bar_up1, NOTSRCERASE); // 遮罩透明处理
putimage(bar1_x, bar1_xTop, &img_bar_up2, SRCINVERT);// 显示上障碍物
putimage(bar1_x, bar1_xDown, &img_bar_down1, NOTSRCERASE); // 遮罩透明处理
putimage(bar1_x, bar1_xDown, &img_bar_down2, SRCINVERT);// 显示下障碍物
FlushBatchDraw();
Sleep(50);
}
void updateWithoutInput()
{
// 输入空格进行控制小鸟
char input;
if (_kbhit())
{
input = _getch();
if (input == ' ' && bird_y > 20)
{
bird_y -= 25;
mciSendString(_T("close jpmusic"), NULL, 0, NULL); // 先把前面一次的音乐关闭
mciSendString(_T("open D:\\Jump.mp3 alias jpmusic"), NULL, 0, NULL);// 打开跳动音乐
mciSendString(_T("play jpmusic"), NULL, 0, NULL); // 仅播放一次
}
}
}
// 图形更新
void updateWithInput()
{
// 小鸟不能飞出界面
if (bird_y < 0 || bird_y > 556)
_exit(0); // 结束
// 小鸟的坐标不能出框 , Y轴不能小于0 , 不能大于580
if (0 < bird_y && bird_y < 580)
bird_y += 3;
// 障碍物的移动
if (bar1_x > -140)
bar1_x -= 2;
else
{
// 重新生成
bar1_x = width;
//障碍物
int randPosition = rand() % (high - 400) + 50; // 随机数就只在 50-250
//注意这是上障碍物的起始坐标
bar1_xTop = randPosition - high; // top 的范围就在 -550 ------ -350 之间
// 上障碍物画完 , 画下障碍物 , 间隔100
bar1_xDown = bar1_xTop + high + 100;
}
//得分计算 小鸟的宽度为34 , 柱子宽度为140
if ( (bar1_x < bird_x + 34) && (bar1_x +140 > bird_x + 34) )
{
if ((bird_y > bar1_xTop +600) && (bird_y < bar1_xDown))
{
score++;
}
else
{
_exit(0);
}
}
}
void gameover()
{
EndBatchDraw();
_getch();
closegraph();
}
int main()
{
startup(); // 数据初始化
while (1) // 游戏循环执行
{
show(); // 显示画面
updateWithoutInput(); // 界面的更新
updateWithInput(); // 与用户输入有关的更新
}
gameover(); // 游戏结束、后续处理
return 0;
}
好了 , 到此结束 . 大家记得每天提醒自己 , 好好学习 , 天天向上