(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)
今天我们来尝试一下用easyx窗口创建飞翔的小鸟游戏
(相关游戏图片我已在末尾给出,欢迎大家保存收藏)
首先与之前的打砖块游戏一样,先引用相关头文件,这里的头文件在我之前的博客中都有讲到,大家可以打开我之前的头文件进行查阅
#include<stdio.h>
#include<graphics.h> //便于引入easyx窗口及其函数
#include<conio.h> //按键控制
#include<time.h> //便于生成随机函数
#include<mmsystem.h>//这是包含多媒体设备接口头文件
#pragma comment(lib,"winmm.lib")//加载静态库
为了使游戏动画变得更加逼真 ,我上网查阅了很多图片,如果与需要,大家可以联系我,我可以发给大家
定义相关图片(关于图片操作如果有明白的可以查阅http://t.csdn.cn/YJX2h)
IMAGE background;//背景图片
IMAGE bigbird[2];//两张鸟的照片
IMAGE endimg[2];//结束照片
IMAGE down[2];//上边管道的照片
IMAGE up[2];//下边管道的照片
void load()//加载相关图片
{
loadimage(&background, "../background.bmp");//加载图片
loadimage(&bigbird[0], "./birdy.bmp",48,48);//照片大小
loadimage(&bigbird[1], "./bird.bmp",48,48);
loadimage(&endimg[0], "./end.bmp");
loadimage(&endimg[1], "./end.bmp");
loadimage(&down[0], "./downy.bmp");
loadimage(&down[1], "./down.bmp");
loadimage(&up[0], "./upy.bmp");//管道宽度为52,高度为320
loadimage(&up[1], "./up.bmp");
}
接下来就是对鸟的相关数据进行定义了
struct bird
{
int x;//鸟的x,y坐标
int y;
int speed;//鸟的速度
};
struct bird mybird = { 70,1,70 };
接下来就是对鸟进行绘制 ,这里我们用两张图片对鸟进行绘制,这样的话才能更好得实现动态图画,减少图片背景的影响
void drawbird(int x, int y)//画鸟
{
putimage(x, y, &bigbird[0], SRCAND);//SRCAND贴掩码图
putimage(x, y, &bigbird[1], SRCPAINT);//SRCPAINT贴背景图
}
然后就是如何控制鸟,这里的每一个函数我之前在easyx基础中都有讲到,这里我就不多做解释了,如果有需要,可以查阅我之前的easyx键盘控制博客(http://t.csdn.cn/KkFwU)
void keybird()//控制鸟
{
char input = _getch();
if (input == 72)//暂停功能,便于暂停游戏
{
while (_getch() != 72);
}
switch (input)//移动鸟
{
case ' ':
mybird.y -= mybird.speed;
CreateThread(NULL, NULL, playMusic, NULL, NULL, NULL);//开辟多线程,防止音乐使游戏变卡
break;
default:
break;
}}
这里我们讲到的多线程,是因为在运行过程中音乐的存在会使游戏变得卡顿,所以在此之前我们先创建一个多线程
DWORD WINAPI playMusic(LPVOID pVoid)
{
mciSendString("open ./jump.mp3", 0, 0, 0);//打开音乐
mciSendString("play ./jump.mp3 wait", 0, 0, 0);//播放音乐
mciSendString("close ./jump.mp3", 0, 0, 0);//关闭音乐
return 0;
}
接下来就是对管道进行定义
struct pillar//定义管道
{
int x1 = 288;
int x2 = 288 + 190;
int y1 = rand() % 250;
int y2 = rand() % 250;
int vx = -2;
}pillar;
//碰撞边界或者管道
int hitfloor()
{
if (mybird.y <= 0 || mybird.y > 512||
(mybird.x>=pillar.x1&&mybird.x<=(pillar.x1+52)&&(mybird.y<=(pillar.y1+20)||mybird.y>=(pillar.y1+160)))||
(mybird.x >= pillar.x2 && mybird.x <= (pillar.x2 + 52) && (mybird.y <= (pillar.y2 + 20) || mybird.y >= (pillar.y2 + 160))))
return 1;
return 0;
}
//结束动画
void gameover()
{
int x = 60;
int y = 608;
while (y >= 240)
{
putimage(0, 0, &background);
putimage(x, y, &endimg[0], SRCAND);
putimage(x, y, &endimg[1], SRCPAINT);
y -= 50;
Sleep(50);
}
HWND hwnd = GetHWnd();//获得窗口句柄
MessageBox(hwnd, "gameover", "提示", MB_OK);//弹出窗口
}
在上面我们加载了相关的图片,现在我们将其进行输出
void drawpillar()//输出相关图片
{
putimage(pillar.x1, pillar.y1-300, &down[0], SRCAND);
putimage(pillar.x1, pillar.y1-300, &down[1], SRCPAINT);
putimage(pillar.x1, pillar.y1 + 160, &up[0], SRCAND);
putimage(pillar.x1, pillar.y1 + 160, &up[1], SRCPAINT);
putimage(pillar.x2, pillar.y2 - 300, &down[0], SRCAND);
putimage(pillar.x2, pillar.y2 - 300, &down[1], SRCPAINT);
putimage(pillar.x2, pillar.y2 + 160, &up[0], SRCAND);
putimage(pillar.x2, pillar.y2 + 160, &up[1], SRCPAINT);
}
接下来就是管道的移动以及不断循环了,因为我们上面只定义了两组管道,所以需要不断循环才能实现管道的不断输出
void movepillar()//移动管道
{
pillar.x1 += pillar.vx;
pillar.x2 += pillar.vx;
if (pillar.x1 <= -52)//管道循坏处理
pillar.x1 = pillar.x2 + 190;
if (pillar.x2 < -52)
pillar.x2 = pillar.x1 + 190;
}
最后就是将其集中在主函数之中,主函数的相关细节在我之前的easyx基础中均有涉及,欢迎大家查阅
int main()
{
srand((unsigned int)time(NULL));//生成随机数种子
initgraph(288,608);//创建主窗口
load();
while (1)
{
cleardevice();//清屏函数,防止图片加载卡顿
putimage(0, 0, &background);//输出图片,坐标,地址
drawbird(mybird.x, mybird.y);
drawpillar();
movepillar();
if (hitfloor())
{
gameover();
break;
}
mybird.y += 10;
//如果不加kbhit,图像在不按键时就不会动
if (_kbhit())//判断是否有按键,有按键才处理,无按键就不处理
{
keybird();
}
Sleep(50);
}
getchar();//防止闪退
closegraph();
return 0;
}
总体代码就是这样,如果大家发现bug或者有更好的方法 ,欢迎大家一起来讨论
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<graphics.h> //便于引入easyx窗口及其函数
#include<conio.h> //按键控制
#include<time.h>
#include<mmsystem.h>//这是包含多媒体设备接口头文件
#pragma comment(lib,"winmm.lib")//加载静态库
IMAGE background;//背景图片
IMAGE bigbird[2];//两张鸟的照片
IMAGE endimg[2];//结束照片
IMAGE down[2];//上边柱子的照片
IMAGE up[2];//下边柱子的照片
//定义鸟的变量
struct bird
{
int x;//鸟的x,y坐标
int y;
int speed;//鸟的速度
};
struct bird mybird = { 70,1,70 };
void load()//加载相关图片
{
loadimage(&background, "../background.bmp");//加载图片
loadimage(&bigbird[0], "./birdy.bmp",48,48);//照片大小
loadimage(&bigbird[1], "./bird.bmp",48,48);
loadimage(&endimg[0], "./endy.bmp");
loadimage(&endimg[1], "./end.bmp");
loadimage(&down[0], "./downy.bmp");
loadimage(&down[1], "./down.bmp");
loadimage(&up[0], "./upy.bmp");//管道宽度为52,高度为320
loadimage(&up[1], "./up.bmp");
}
void drawbird(int x, int y)//画鸟
{
putimage(x, y, &bigbird[0], SRCAND);//SRCAND贴掩码图
putimage(x, y, &bigbird[1], SRCPAINT);//SRCPAINT贴背景图
}
DWORD WINAPI playMusic(LPVOID pVoid)
{
mciSendString("open ./jump.mp3", 0, 0, 0);//打开音乐
mciSendString("play ./jump.mp3 wait", 0, 0, 0);//播放音乐
mciSendString("close ./jump.mp3", 0, 0, 0);//关闭音乐
return 0;
}
void keybird()//控制鸟
{
char input = _getch();
if (input == 72)//暂停功能
{
while (_getch() != 72);
}
switch (input)//移动鸟
{
case ' ':
mybird.y -= mybird.speed;
CreateThread(NULL, NULL, playMusic, NULL, NULL, NULL);//开辟多线程,防止音乐使游戏变卡
break;
default:
break;
}
}
struct pillar//定义柱子
{
int x1 = 288;
int x2 = 288 + 190;
int y1 = rand() % 250;
int y2 = rand() % 250;
int vx = -2;
}pillar;
//碰撞边界
int hitfloor()
{
if (mybird.y <= 0 || mybird.y > 512||
(mybird.x>=pillar.x1&&mybird.x<=(pillar.x1+52)&&(mybird.y<=(pillar.y1+20)||mybird.y>=(pillar.y1+160)))||
(mybird.x >= pillar.x2 && mybird.x <= (pillar.x2 + 52) && (mybird.y <= (pillar.y2 + 20) || mybird.y >= (pillar.y2 + 160))))
return 1;
return 0;
}
//结束动画
void gameover()
{
int x = 60;
int y = 608;
while (y >= 240)
{
putimage(0, 0, &background);
putimage(x, y, &endimg[0], SRCAND);
putimage(x, y, &endimg[1], SRCPAINT);
y -= 50;
Sleep(50);
}
HWND hwnd = GetHWnd();//获得窗口句柄
MessageBox(hwnd, "gameover", "提示", MB_OK);//弹出窗口
}
void drawpillar()//输出相关图片
{
putimage(pillar.x1, pillar.y1-300, &down[0], SRCAND);
putimage(pillar.x1, pillar.y1-300, &down[1], SRCPAINT);
putimage(pillar.x1, pillar.y1 + 160, &up[0], SRCAND);
putimage(pillar.x1, pillar.y1 + 160, &up[1], SRCPAINT);
putimage(pillar.x2, pillar.y2 - 300, &down[0], SRCAND);
putimage(pillar.x2, pillar.y2 - 300, &down[1], SRCPAINT);
putimage(pillar.x2, pillar.y2 + 160, &up[0], SRCAND);
putimage(pillar.x2, pillar.y2 + 160, &up[1], SRCPAINT);
}
void movepillar()//移动管道
{
pillar.x1 += pillar.vx;
pillar.x2 += pillar.vx;
if (pillar.x1 <= -52)//管道循坏处理
{
pillar.x1 = pillar.x2 + 190;
pillar.y1 = rand() % 250;//使每一次管道的位置都不一样
}
if (pillar.x2 < -52)
{
pillar.x2 = pillar.x1 + 190;
pillar.y2 = rand() % 250;
}
}
int main()
{
srand((unsigned int)time(NULL));//生成随机数种子
initgraph(288,608);//创建主窗口
load();
while (1)
{
cleardevice();
putimage(0, 0, &background);//输出图片,坐标,地址
drawbird(mybird.x, mybird.y);
drawpillar();
movepillar();
if (hitfloor())
{
gameover();
break;
}
mybird.y += 10;
//如果不加kbhit,图像在不按键时就不会动
if (_kbhit())//判断是否有按键,有按键才处理,无按键就不处理
{
keybird();
}
Sleep(50);
}
getchar();//防止闪退
closegraph();
return 0;
}
加油
游戏相关代码的掩码图和背景图:










1417

被折叠的 条评论
为什么被折叠?



