利用GDI+制作Flappy Bird
上次介绍用GDI+写了个验证码图片生成器,这次再来介绍下用GDI+写之前流行过一段时间的小游戏:Flappy Bird。通过写这个游戏再来熟悉下GDI+的一些简单利用。
这是一个粗糙的游戏画面,大家不要介意啊,毕竟这是美工做的事:
先来分析一下这个游戏要怎么写。游戏过程是:1、小鸟不停的往下掉,而且越掉越快;2、障碍物柱子不停地出现并往左移动;3、游戏一开始下面的前进条就不停地转动。
游戏规则:1、小鸟的身体不能触碰障碍物;2、小鸟的身体不能触及底部及上部;3、每当小鸟穿过一个障碍物时统计通过障碍物的数量加1。
知道了游戏过程和游戏规则,我们来编写游戏:
由于游戏中出现的障碍物高度不一,宽度统一。我们可以写一个障碍物类用于生成障碍物对象与小鸟对象。
class Diamonds { int _width = 40; /// <summary> /// 图形的宽,默认40 /// </summary> public int Width { get { return _width; } set { _width = value; } } int _heigth; /// <summary> /// 图形高 /// </summary> public int Heigth { get { return _heigth; } set { _heigth = value; } } float _x; /// <summary> /// X轴坐标 /// </summary> public float X { get { return _x; } set//X轴坐标不能小于零 { if (value < 0) { value = 0; } _x = value; } } float _y; /// <summary> /// Y轴坐标不能大于300或小于0 /// </summary> public float Y { get { return _y; } set { if (value > 400) { value = 400; } if (value < 0) { value = 0; } _y = value; } } float _speed = 0; /// <summary> /// 坐标增减的速度 /// 小鸟对象的初速度 /// 正数为上升速度 /// 负数为下降速度 /// </summary> public float Speed { get { return _speed; } set { _speed = value; } } /// <summary> /// 改变X轴坐标 /// </summary> public void ChangeX() { if (this.X == 0)//每次X轴为0时宽度减1 { this.Width -= 1; } else { this.X -= 1; } } /// <summary> /// 改变Y轴坐标 /// 控制小鸟对象的上升与下降速度 /// </summary> public void ChangeY() { //改变Y轴的速度先减速降低后加速增加 this.Y -= this.Speed; this.Speed -= 0.2f; } /// <summary> /// 构造函数 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="heigth"></param> public Diamonds(float x, float y, int heigth) { this.X = x; this.Y = y; this.Heigth = heigth; }
生成障碍物及小鸟的类已经写完了,并且有了左右移动和上下移动的方法。
接下来开始写游戏过程:
一、绘制游戏图
利用GDI+绘制游戏图,利用时间控件不停的重绘游戏图,以产生动态的效果。
首先申明全局变量及对象:
//设置障碍物之间的空隙高度 static int width = 100; //判断绘制哪个前进条 bool b = true; //统计当前通过障碍物的数量 int count = 0; int _maxCount = 0; /// <summary> /// 记录最大通过数量 /// </summary> public int MaxCount { get { return _maxCount; } set { _maxCount = value; } } //创建画布,大小为300*400 static Bitmap bmp = new Bitmap(300, 400); static Bitmap bmp1 = new Bitmap(300, 20); //创建一只笔,画小鸟 static Pen penOne = new Pen(Brushes.Red, 5); //创建一支笔,画前进条 static Pen penTwo = new Pen(Color.Black, 2); //创建鸟 static Diamonds bird = new Diamonds(100, 190, 15); //创建随机数产生器 static Random r = new Random(); //从画布bmp中创建GDI+对象 static Graphics gp = Graphics.FromImage(bmp); static Graphics gp1 = Graphics.FromImage(bmp1); //创建两个障碍物的对象 static int up1Height = r.Next(80, 241); Diamonds up1 = new Diamonds(300, 0, up1Height); Diamonds down1 = new Diamonds(300, width + up1Height, 400 - width - up1Height); static int up2Height = r.Next(80, 241); Diamonds up2 = new Diamonds(450, 0, up1Height); Diamonds down2 = new Diamonds(450, width + up1Height, 400 - width - up1Height);
绘制游戏图:
//小鸟飞 bird.ChangeY(); //障碍物移动 up1.ChangeX(); down1.ChangeX(); up2.ChangeX(); down2.ChangeX(); //判断游戏是否结束 IsEnd(); //统计通过个数 PassCount(); //清除画面 gp.Clear(Color.Blue); //如果一个障碍物消失,则新出现一个障碍物 if (up1.Width == 0) { up1Height = r.Next(80, 241); up1 = new Diamonds(300, 0, up1Height); down1 = new Diamonds(300, width + up1Height, 400 - width - up1Height); } //如果一个障碍物消失,则新出现一个障碍物 if (up2.Width == 0) { up2Height = r.Next(80, 241); up2 = new Diamonds(300, 0, up2Height); down2 = new Diamonds(300, width + up2Height, 400 - width - up2Height); } //画出各个对象 //鸟 gp.DrawRectangle(penOne, bird.X, bird.Y, bird.Width - 10, bird.Heigth); //障碍 gp.FillRectangle(Brushes.Green, up1.X, up1.Y, up1.Width, up1.Heigth); gp.FillRectangle(Brushes.Green, down1.X, down1.Y, down1.Width, down1.Heigth); gp.FillRectangle(Brushes.Green, up2.X, up2.Y, up2.Width, up2.Heigth); gp.FillRectangle(Brushes.Green, down2.X, down2.Y, down2.Width, down2.Heigth); //将图片给图片框 pbxImage.Image = bmp; } /// <summary> /// 画面前进条运转 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void timer2_Tick(object sender, EventArgs e) { gp1.Clear(Color.Blue); //画前进条 gp1.DrawLine(penTwo, 0, 0, 300, 0); gp1.DrawLine(penTwo, 0, 20, 300, 20); if (b) { for (int i = 0; i < 300; i += 20) { gp1.FillRectangle(Brushes.Green, i, 0, 10, 20); } b = false; } else { for (int i = 10; i < 300; i += 20) { gp1.FillRectangle(Brushes.Green, i, 0, 10, 20); } b = true; } pbxLines.Image = bmp1; } /// <summary> /// 游戏结束条件 /// </summary> private void IsEnd() { //由于小鸟身体线条粗细问题,宽相应要增加5个像素左右,高增加2个像素 if (((bird.X + 33 >= up1.X) && (bird.X <= up1.X + 40)) && ((bird.Y <= up1.Heigth + 5) || (bird.Y >= up1.Heigth + width - 20)))//当小鸟头部进入障碍物1则结束 { GameOver(); } else if (((bird.X + 33 >= up2.X) && (bird.X <= up2.X + 40)) && ((bird.Y <= up2.Heigth + 5) || (bird.Y >= up2.Heigth + width - 20)))//当小鸟头部进入障碍物2则结束 { GameOver(); } else if (bird.Y >= 375 || bird.Y <= 0)//当小鸟碰头或触地 { GameOver(); } } /// <summary> /// 游戏结束判断 /// </summary> private void GameOver() { //显示控件 timer1.Enabled = false; lblEnd.Visible = true; btnStart.Visible = true; lblMaxCount.Visible = true; label1.Visible = true; //得到最高分 if (this.MaxCount < count) { this.MaxCount = count; } lblMaxCount.Text = this.MaxCount.ToString(); return; } /// <summary> /// 计算通过的数量 /// </summary> private void PassCount() { //当障碍物的末点X轴过了小鸟则通过一个 if (up1.X == 65 || up2.X == 65) { count++; } lblCount.Text = count.ToString(); } /// <summary> /// 开始游戏 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnStart_Click(object sender, EventArgs e) { //开始,结束控件不可见 btnStart.Visible = false; lblEnd.Visible = false; lblMaxCount.Visible = false; label1.Visible = false; btnStart.Text = "重新开始"; //当前数量归零 count = 0; //重新初始化图片 bird = new Diamonds(100, 190, 15); up1Height = r.Next(80, 241); up1 = new Diamonds(300, 0, up1Height); down1 = new Diamonds(300, width + up1Height, 400 - width - up1Height); up2Height = r.Next(80, 241); up2 = new Diamonds(450, 0, up1Height); down2 = new Diamonds(450, width + up1Height, 400 - width - up1Height); //激活 timer1.Enabled = true; } /// <summary> /// 点击小鸟飞 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void pbxImage_Click(object sender, EventArgs e) { //经过调试,这个速度可玩性较高 bird.Speed = 4.5f; } /// <summary> /// 双击加速上升 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void pbxImage_DoubleClick(object sender, EventArgs e) { bird.Speed = 7; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。