![2ecde37db3c23c2aa609eb207673673f.png](https://img-blog.csdnimg.cn/img_convert/2ecde37db3c23c2aa609eb207673673f.png)
经过之前的学习,我们基本掌握了开发小游戏所需要的语法知识和搭建方法,但是基础C语言的可视化与交互功能实在是太弱了
。
![4314ca80e2e0c8744fab3bcc175b90b2.png](https://img-blog.csdnimg.cn/img_convert/4314ca80e2e0c8744fab3bcc175b90b2.png)
利用免费的EasyX插件,我们可以快速上手,简单实现很酷的视觉效果
。
![ad8f0262d91cc828c726b1e1f51847b5.png](https://img-blog.csdnimg.cn/img_convert/ad8f0262d91cc828c726b1e1f51847b5.png)
EasyX安装包下载链接:下载 -- EasyX Library for C++
怎样安装 EasyX? -- EasyX Library for C++
怎样使用 EasyX?(Visual C++ 6.0) -- EasyX Library for C++
怎样使用 EasyX?(Visual C++ 2008) -- EasyX Library for C++
官网还提供了一套非常好的入门教程,大家可以自学:VC绘图/游戏简易教程--前言 -- EasyX Library for C++
对应的目录:
–前言
–1:创建新项目
–2:简单绘图,学习单步执行
–3:熟悉更多的绘图语句
–4:结合流程控制语句来绘图
–5:数学知识在绘图中的运用
–6:实现简单动画
–7:捕获按键,实现动画的简单控制
–8:用函数简化相同图案的制作
–9:绘图中的位运算
–10:用鼠标控制绘图/游戏程序
–11:随机函数
–12:数组
–13:getimage / putimage / loadimag / saveimage / IMAGE 的用法
–14:通过位运算实现颜色的分离与处理
–15:窗体句柄(Windows 编程入门)
–16:设备上下文句柄(Windows 编程入门2)
学习完后,大家可以试着将前面教程中学习的生命游戏、反弹球、flappy bird、空战游戏用EasyX重新实现,达到类似这样的效果:
![16d4b8e23788ab9bce40593d4b066595.png](https://img-blog.csdnimg.cn/img_convert/16d4b8e23788ab9bce40593d4b066595.png)
![cc953d219c879efa3fcbfc287886a767.png](https://img-blog.csdnimg.cn/img_convert/cc953d219c879efa3fcbfc287886a767.png)
![0a6d9b4e089dd9d6e0be8c40ac21fe00.png](https://img-blog.csdnimg.cn/img_convert/0a6d9b4e089dd9d6e0be8c40ac21fe00.png)
![dddf7756e2f6bc8d888517c6ea34de6c.png](https://img-blog.csdnimg.cn/img_convert/dddf7756e2f6bc8d888517c6ea34de6c.png)
大家可以在网上搜索诸如“flappy bird游戏素材”,下载对应的图片和音乐素材。也可以直接在原始游戏中截图,ps出需要的素材。
下面是用EasyX实现的flappy bird需要的图片:
![5fa126ae7493b68f71a37ca36c5cd36b.png](https://img-blog.csdnimg.cn/img_convert/5fa126ae7493b68f71a37ca36c5cd36b.png)
素材代码可由百度云盘下载:http://pan.baidu.com/s/1o8lnH70,首先大家可以运行flappy birdeasyx birdDebughappyhappy.exe 文件看看游戏效果。
以下为游戏代码,大家可以参考:
/*
画面大小350*600
鸟的大小100*70
柱子宽处宽度140,窄处宽度100,宽处厚度30,颜色
*/
#include<graphics.h>
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include <time.h>
// 引用 Windows Multimedia API
#pragma comment(lib,"Winmm.lib")
void print();
void begin();
void printstone();//人家才不是作柱子的呢
void bird();//控制鸟的下降和上升
void judgement();//判断语句
void scoleprint();
void endorretry();
int bird_x=150,bird_y=300,i=0,k=0;//鸟的左上角坐标
int scole=0,t=0;
int stone_x1,stone_y1;//上截柱子左下坐标
int stone_x2,stone_y2;//上截柱子左下坐标
IMAGE backgrand,bird1[4],bird2[4],scole1[10],scole2[10],stone_up1,stone_up2,stone_down1,stone_down2
,stone_up3,stone_up4,stone_down3,stone_down4;//图片储存变量
MOUSEMSG m; // 定义鼠标消息
int main()
{
if(t==0)
{
begin();
t++;
}
if(t)
print();
getch();//制造停顿
bird_y=300;bird_x=150;i=0;k=0;scole=0;
while(1)
{
bird();
print();
judgement();
}
closegraph();
return 0;
}
void print()
{
putimage(0, 0, &backgrand);//背景图像
printstone();//画柱子
putimage(bird_x, bird_y,&bird1[i%3],NOTSRCERASE);
putimage(bird_x, bird_y,&bird2[i%3],SRCINVERT);
if(k%5==0)
i++;
k++;
scoleprint();
FlushBatchDraw(); // 绘制
}
void printstone()//柱子移动规律/哭
{
Sleep(30);
if(stone_x1>210)//此时画面存在两根柱子
{
putimage(stone_x1, stone_y1, &stone_up2,NOTSRCERASE);
putimage(stone_x1, stone_y1, &stone_up1,SRCINVERT);
putimage(stone_x1, stone_y1+750, &stone_down2,NOTSRCERASE);
putimage(stone_x1, stone_y1+750, &stone_down1,SRCINVERT);
putimage(stone_x2, stone_y2, &stone_up4,NOTSRCERASE);
putimage(stone_x2, stone_y2, &stone_up3,SRCINVERT);
putimage(stone_x2, stone_y2+750, &stone_down4,NOTSRCERASE);
putimage(stone_x2, stone_y2+750, &stone_down3,SRCINVERT);
stone_x1--;stone_x2--;
}
else if(stone_x1==210)//左柱子消失,将stone_x2,stone_y2值归位
{
stone_x2=stone_x1;
stone_y2=stone_y1;
putimage(stone_x1, stone_y1, &stone_up2,NOTSRCERASE);
putimage(stone_x1, stone_y1, &stone_up1,SRCINVERT);
putimage(stone_x1, stone_y1+750, &stone_down2,NOTSRCERASE);
putimage(stone_x1, stone_y1+750, &stone_down1,SRCINVERT);
stone_x1--;
stone_x2--;
}
else if(stone_x1<210&&stone_x1>0)//画面只存在一根柱子的情况
{
putimage(stone_x1, stone_y1, &stone_up2,NOTSRCERASE);
putimage(stone_x1, stone_y1, &stone_up1,SRCINVERT);
putimage(stone_x1, stone_y1+750, &stone_down2,NOTSRCERASE);
putimage(stone_x1, stone_y1+750, &stone_down1,SRCINVERT);
stone_x1--;
stone_x2--;
}
if(stone_x1==0)//柱子左端到站,生成新柱子
{
stone_y1=rand()%310-555;
stone_x1=350;
putimage(stone_x1, stone_y1, &stone_up2,NOTSRCERASE);
putimage(stone_x1, stone_y1, &stone_up1,SRCINVERT);
putimage(stone_x1, stone_y1+750, &stone_down2,NOTSRCERASE);
putimage(stone_x1, stone_y1+750, &stone_down1,SRCINVERT);
stone_x1--;
stone_x2--;
}
}
void begin()
{
mciSendString("open "....soundsbackground.mp3" alias music ", NULL, 0, NULL);//背景音乐
mciSendString("play music", NULL, 0, NULL);
initgraph(350,600);
// 获取窗口句柄
HWND hwnd = GetHWnd();
// 设置窗口标题文字
SetWindowText(hwnd, "江超群制作");
IMAGE beforegame;
loadimage(&beforegame,"....素材库beforegame.jpg");
putimage(0,0,&beforegame);
Sleep(1000);
getch();
BeginBatchDraw();// 开启批量绘图模式
loadimage(&backgrand, "....素材库backgroundfd.jpg");//载入背景图片
//鸟
loadimage(&bird2[0], "....素材库bird1-2.gif");
loadimage(&bird1[0], "....素材库bird1-1.gif");
loadimage(&bird2[1], "....素材库bird2-2.gif");
loadimage(&bird1[1], "....素材库bird2-1.gif");
loadimage(&bird2[2], "....素材库bird3-2.gif");
loadimage(&bird1[2], "....素材库bird3-1.gif");
loadimage(&bird2[3], "....素材库bird4-2.gif");
loadimage(&bird1[3], "....素材库bird4-1.gif");
//柱子
loadimage(&stone_up1,"....素材库stone_up1.gif");
loadimage(&stone_up2,"....素材库stone_up2.gif");
loadimage(&stone_down1,"....素材库stone_down1.gif");
loadimage(&stone_down2,"....素材库stone_down2.gif");
loadimage(&stone_up3,"....素材库stone_up1.gif");
loadimage(&stone_up4,"....素材库stone_up2.gif");
loadimage(&stone_down3,"....素材库stone_down1.gif");
loadimage(&stone_down4,"....素材库stone_down2.gif");
//数字
loadimage(&scole1[0],"....素材库0_1.jpg");
loadimage(&scole2[0],"....素材库0_2.jpg");
loadimage(&scole1[1],"....素材库1_1.jpg");
loadimage(&scole2[1],"....素材库1_2.jpg");
loadimage(&scole1[2],"....素材库2_1.jpg");
loadimage(&scole2[2],"....素材库2_2.jpg");
loadimage(&scole1[3],"....素材库3_1.jpg");
loadimage(&scole2[3],"....素材库3_2.jpg");
loadimage(&scole1[4],"....素材库4_1.jpg");
loadimage(&scole2[4],"....素材库4_2.jpg");
loadimage(&scole1[5],"....素材库5_1.jpg");
loadimage(&scole2[5],"....素材库5_2.jpg");
loadimage(&scole1[6],"....素材库6_1.jpg");
loadimage(&scole2[6],"....素材库6_2.jpg");
loadimage(&scole1[7],"....素材库7_1.jpg");
loadimage(&scole2[7],"....素材库7_2.jpg");
loadimage(&scole1[8],"....素材库8_1.jpg");
loadimage(&scole2[8],"....素材库8_2.jpg");
loadimage(&scole1[9],"....素材库9_1.jpg");
loadimage(&scole2[9],"....素材库9_2.jpg");
srand(time(0));//初始化种子
print();
//第一根柱子,初始化
stone_y1=rand()%310-555;
stone_x1=350;
stone_x2=stone_y2=-9999;
}
void bird()
{
char space;
if(kbhit())//读取空格
{
space=getch();
if(space==' ')
{
bird_y-=80;
}
else if(space==27)
getch();
}
else
{
bird_y+=3;
}
while(MouseHit())
{
// 获取一条鼠标消息
m = GetMouseMsg();
switch(m.uMsg)
{
case WM_LBUTTONDOWN:
bird_y-=80;
break;
case WM_RBUTTONDOWN:
getch();
break;
}
}
}
void judgement()
{
if((stone_x1>10 && stone_x1<20)||(stone_x1>174&&stone_x1<184))
{
if((bird_y>(stone_y1+576)&&bird_y<(stone_y1+600))||((bird_y>(stone_y1+726))&&bird_y<(stone_y1+750)))
endorretry();//结束游戏
}
else if(stone_x1>=20 && stone_x1<=174)
{
if(!(bird_y>(stone_y1+600)&&bird_y<(stone_y1+726)))
endorretry(); //结束游戏
}
if(bird_y>576)
endorretry();//结束游戏
if(stone_x1==150)
scole++;
}
void endorretry()
{
if(bird_y<550 && stone_x1>160)
{
while(bird_y<550)
{
putimage(0, 0, &backgrand);//背景图像
putimage(stone_x1, stone_y1, &stone_up2,NOTSRCERASE);
putimage(stone_x1, stone_y1, &stone_up1,SRCINVERT);
putimage(stone_x1, stone_y1+750, &stone_down2,NOTSRCERASE);
putimage(stone_x1, stone_y1+750, &stone_down1,SRCINVERT);
putimage(stone_x2, stone_y2, &stone_up4,NOTSRCERASE);
putimage(stone_x2, stone_y2, &stone_up3,SRCINVERT);
putimage(stone_x2, stone_y2+750, &stone_down4,NOTSRCERASE);
putimage(stone_x2, stone_y2+750, &stone_down3,SRCINVERT);
putimage(bird_x, bird_y,&bird1[3],NOTSRCERASE);
putimage(bird_x, bird_y,&bird2[3],SRCINVERT);
FlushBatchDraw();
bird_y++;
}
}
IMAGE gameover1,gameover2,atlast;
loadimage(&gameover1, "....素材库gameover1.gif");
loadimage(&gameover2, "....素材库gameover2.gif");
putimage(80, 200, &gameover1,NOTSRCERASE);
putimage(80, 200, &gameover2,SRCINVERT);
FlushBatchDraw();
Sleep(1000);
loadimage(&atlast, "....素材库atlast.jpg");
putimage(0,0,&atlast);
scoleprint();
FlushBatchDraw();
getch();
//第一根柱子
stone_y1=rand()%310-555;
stone_x1=350;
stone_x2=stone_y2=-9999;
bird_y=300;
scole=0;
main();
}
void scoleprint()
{
IMAGE *fen1[6],*fen2[6];
int he,weishu=1,i=0,sdsf=scole;
if(sdsf==0)
{
putimage(250,50,&scole1[0],NOTSRCERASE);
putimage(250,50,&scole2[0],SRCINVERT);
}
while(sdsf>0)
{
he=sdsf%10;
fen1[i]=&scole1[he];
fen2[i]=&scole2[he];
putimage(300-50*weishu,50,fen1[i],NOTSRCERASE);
putimage(300-50*weishu,50,fen2[i],SRCINVERT);
sdsf/=10;
i++;
weishu++;
}
}
做出flappy bird,也可以按照我们之前教程的思路,step by step地实现,遇到问题再参考上面的代码。自己从无到有实现一遍,就能学会类似游戏的开发了。大概步骤可以为:
1. 背景图片的显示
2. 加入小鸟图片
3. 小鸟自由下落,按键后上升
4. 加入静态的障碍物
5. 障碍物向左移动
6. 判断小鸟和障碍物的碰撞
7. 障碍物移动出左边界后,在右边重新出现
8. 加入记分模块
9. 加入音效效果
10. 加入开始界面、结束界面
11. 继续完善细节、整理代码
flappy bird相对比较简单,大家可以先从这个案例开始学习。学会理解别人的代码,也是一个非常重要的能力,大家可以通过这种逐步重现的方法来学习。后面我们再一起学习更复杂的EasyX游戏代码,EasyX官网上也有很多游戏案例可以借鉴参考:
范例程序 -- EasyX Library for C++
CodeBus | 分享代码,一起进步~
下一个教程:英雄联盟连连看 知乎专栏