重庆海天软件学院的WINFORM实训项目-疯狂的小鸟

如图所示效果:

最近学生们学习了2个月的C#和WINFORM,没有学习数据库。故设计了这样的一个小游戏,基本覆盖了C#语言常用的语法,已经面向对象的基本思想。本实训课程分为8个阶段来实践,效果非常好。故录制成视频分为8个阶段,每个阶段15分钟左右。
此游戏开发为在课堂上即兴编写,即兴录制。没有事先准备,故有些地方不是很完美,请见谅!不过,大家可以学习丁老师在完成软件开发中的需求的时候,思考的过程和完整的思路,以及遇到错误如果去调试和解决的方法,这个大家会有收获。
下载地址:http://www.kuaipan.com.cn/file/id_5393847563583517.htm

主要实现思路为:用GDI+在窗体上绘制图形,在主窗体加入了一个Time控件来做游戏循环,不断的绘图。使用的DoubleBuffer技术,屏幕不闪烁。效果还是可以的,但是在面向对象设计这块设计得有点罗嗦了,没有设计好,需要进一步完善。

主窗体代码:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Windows.Forms;
  9 
 10 namespace CrazyBird_GDI
 11 {
 12     /// <summary>
 13     /// 重庆海天软件工程学院 微软7班 WINFORM实训项目----疯狂的小鸟
 14     /// 微软讲师:丁浩   Email:dinghao80@qq.com QQ:37112555
 15     /// 项目需求:射击游戏
 16     /// 实现步骤:1.采用GDI+技术,双缓冲实训精灵的绘制
 17     /// 2.绘制背景 
 18     /// 3.绘制小鸟
 19     /// 4.绘制小猪
 20     /// 5.绘制子弹
 21     /// </summary>
 22     public partial class Form1 : Form
 23     {
 24         public Form1()
 25         {
 26             InitializeComponent();
 27         }
 28         Bitmap bitmap;
 29         Pig pig;
 30         //第七步4
 31         List<Bullet> bullets = new List<Bullet>();
 32         BirdOP birdop;
 33         //第十步6:  当子弹碰到小鸟的开关
 34         bool isTouched = false;
 35         private void timer1_Tick(object sender, EventArgs e)
 36         {
 37             //在time控件中循环绘制,约33帧的FPS
 38             //第一步:导入所需资源
 39             //第二步:搭建双缓冲模型,将资源不断的绘制在虚拟画布上面,这个技术可以消除屏幕闪烁
 40             //最后将虚拟画布bitmap的内容复制在窗体绘图区
 41 
 42             using (Graphics dc=Graphics.FromImage(bitmap))
 43             {
 44                 //第三步:导入背景图片资源
 45                 BackGround bg = new BackGround(this.Width, this.Height);
 46                 bg.Draw(dc);
 47                 //固定窗体不能拖动
 48 
 49                 //**-------//第一阶段完成。思考:BackGround设计成了一个类,为什么?好处在哪儿?-------------------------------------------------------------------------------------------
 50                 //第四步:绘制小鸟  需求一共64只小鸟,成8*8排列 设计小鸟类
 51                
 52                //第九步6:绘制小鸟
 53                 birdop.Draw(dc);//之前要装载小鸟
 54                
 55                 
 56 
 57                 //**------//第二阶段完成。-----------------------------------------------------------------------------------------------
 58                 //第五步:绘制小猪
 59               
 60                 pig.Width = 70;
 61                 pig.Height = 60;
 62                
 63                 pig.Draw(this,dc);
 64 
 65                 //**------  //第三阶段完成----------------------------------------------------------------------------------------------
 66                 //第六步:移动小猪
 67                 //触发键盘事件:注意思考,事件源是什么?----窗体
 68 
 69                 //第七步6:绘制子弹
 70                 foreach (Bullet bullet in bullets)
 71                 {
 72                     //第八步2:让speed值增加 ,现在找个地方赋予speed初始值
 73                   //  bullet.Speed+=10; //没有起到作用 
 74                     bullet.X -= bullet.Speed;
 75                     bullet.Draw(dc);
 76                 }
 77                 //***----------第六阶段完成 (让子弹飞)------------------下一阶段:子弹碰撞小鸟,子弹和小鸟移除集合-------------------------------------------------------------------
 78                 //思考:子弹碰撞小鸟,只需要在time控件中从小鸟集合中绘制,子弹从子弹集合里面绘制。碰撞后,从各种集合移除小鸟或子弹即可。
 79 
 80                 //第十步1:判断子弹和小鸟相撞,实际上就是2个矩形相交。追加子弹的方法。
 81 
 82                 //第十步5:
 83                 for (int i = 0; i < bullets.Count; i++)  //遍历子弹,注意这个时候不能用foreach ,为什么?
 84                 {
 85                     for (int j = 0; j < BirdOP.birds.Count; j++)//遍历小鸟
 86                     {
 87                         if (bullets[i].Intersect(BirdOP.birds[j]))  //每一个子弹去判断所有的小鸟碰撞
 88                         {
 89                             BirdOP.birds.RemoveAt(j);//移除小鸟  测试成功 但是同时要移除子弹
 90                             isTouched = true;
 91                         }
 92                     }
 93                     //移除子弹
 94                     if (isTouched)
 95                     {
 96                         bullets.RemoveAt(i);
 97                         isTouched = false;
 98                     }
 99                     //测试成功
100                     //**-----------------第八阶段完成    到这儿就结束了  思考加入声音,由于机房没有音响,不好测试。----------------------------------------------------------------------------------------
101                     //我们发现在构造Bird BackGround Pig等到类的时候,发现都有共同的属性,这个时候可以用继承来实现,需要进一步改进,还要有更好的扩展性,大家在学习面向对象的时候
102                     //要积极思考面向对象的三大特性,封装 继承 多态 接口 抽象类 结构 枚举等等C#的特性
103                     //实训制作人:丁浩老师    QQ:37112555  这个视频会放在www.ha2ha.com中下载,欢迎大家学习,谢谢!  重庆海天软件工程学院 
104                 
105                 }
106 
107             }
108             //第二步:复制绘制在窗体绘图区
109             using (Graphics g=this.CreateGraphics())
110             {
111                 g.DrawImage(bitmap, 0, 0);
112             }
113         }
114 
115         private void Form1_Load(object sender, EventArgs e)
116         {
117             //第二步:创建和窗体一样大小的画布
118             bitmap = new Bitmap(this.Width, this.Height);
119             //初始化小猪
120             pig = new Pig();
121             pig.Step = 10;
122             //第九步5:初始化小鸟
123             //bird = new Bird();
124             //bird.LoadBird();
125             //做到这个地方,我们发现在bird设计中出现了问题。需要重新设计,没有思考全面。
126             birdop = new BirdOP();
127             //第九步5:初始化小鸟
128             birdop.LoadBirds();
129         }
130 
131         //第六步 触发键盘事件移动小猪
132         private void Form1_KeyUp(object sender, KeyEventArgs e)
133         {
134             switch (e.KeyCode)
135             {
136                 case Keys.Up:            
137                     pig.Move(Direct.UP);
138                     break;
139                 case Keys.Down:
140                     pig.Move(Direct.DOWN);
141                     break;
142                 case Keys.Space:
143                     //第七步5:装载子弹在集合中
144                     bullets.Add(pig.FireABullet());
145                     break;
146           
147             }
148         }
149         //**-----------第四阶段完成--------------------------------------------
150     }
151 }

 背景类:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Drawing;
 6 
 7 namespace CrazyBird_GDI
 8 {
 9     class BackGround
10     {
11         public BackGround(int width,int height)
12         {
13             Width = width;
14             Height = height;
15         }
16         int width;
17 
18         public int Width
19         {
20             get { return width; }
21             set { width = value; }
22         }
23         int height;
24 
25         public int Height
26         {
27             get { return height; }
28             set { height = value; }
29         }
30 
31         //绘制一个背景图片
32         public void Draw(Graphics g)
33         {
34             Rectangle rect=new Rectangle(0,0,Width,Height);
35             g.DrawImage(MyRes.background, rect);
36         }
37     }
38 }

小鸟类:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Drawing;
 6 
 7 namespace CrazyBird_GDI
 8 {
 9     public class Bird
10     {
11         int x;//x坐标
12 
13         public int X
14         {
15             get { return x; }
16             set { x = value; }
17         }
18         int y;//y坐标
19 
20         public int Y
21         {
22             get { return y; }
23             set { y = value; }
24         }
25         int width;
26 
27         public int Width
28         {
29             get { return width; }
30             set { width = value; }
31         }
32         int height;
33 
34         public int Height
35         {
36             get { return height; }
37             set { height = value; }
38         }
39 
40         //小鸟的矩形绘图区  第十步 3
41         private Rectangle rectBird;
42 
43         public Rectangle RectBird
44         {
45             get { return rectBird; }
46             set { rectBird = value; }
47         }
48     }
49 }

小鸟操作类:

View Code
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Drawing;
 6 
 7 namespace CrazyBird_GDI
 8 {
 9     /// <summary>
10     /// 第九步6:重新设计小鸟类
11     /// 增加了一个小鸟操作类
12     /// </summary>
13    public class BirdOP
14     {
15         //第九步2:定义一个集合
16        public static List<Bird> birds = new List<Bird>();//为什么是静态的呢?如
17 
18 果不是静态的,每次new一个小鸟,都会有属于自己的集合,显然不对。所以用静态的
19 
20 ,所有的小鸟对象都对应这一个集合
21 
22        //绘制8*8小鸟阵
23 
24        //第九步3:装入64只小鸟到集合中
25        public void LoadBirds()
26        {
27            for (int i = 0; i < 64; i++)
28            {
29 
30                Bird bird = new Bird();
31                bird.X = i % 8 * 60 + 24;//45是小鸟和小鸟之间的间隔,24是left
32                bird.Y = i / 8 * 60 + 24;
33                bird.Width = 50;
34                bird.Height = 50;
35                birds.Add(bird);  //添加了64个小鸟到集合中
36            }
37 
38 
39        }
40        //第九步1:要改良Draw方法,从集合中不断取出来绘制
41        public void Draw(Graphics g)
42        {
43            //第九步4:从集合中取出小鸟绘制在画布上面
44            foreach (Bird bird in birds)
45            {
46                Rectangle rect = new Rectangle(bird.X, bird.Y, bird.Width, 
47 
48 bird.Height);
49                bird.RectBird = rect;
50                g.DrawImage(MyRes.bird, bird.RectBird);
51            }
52        }
53 
54        //**------第七阶段完成   下一阶段 碰撞 从集合中移
55 
56 除----------------------------------------------------------
57 
58     }
59 }

子弹类:

View Code
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Drawing;
 6 
 7 namespace CrazyBird_GDI
 8 {
 9     /// <summary>
10     /// 第七步1:构建子弹类,思考:按一下回车键,就要发射一个子弹。
11     /// 子弹同样是绘图
12     /// </summary>
13     class Bullet
14     {
15         int x;
16 
17         public int X
18         {
19             get { return x; }
20             set { x = value; }
21         }
22         int y;
23 
24         public int Y
25         {
26             get { return y; }
27             set { y = value; }
28         }
29         int width;
30 
31         public int Width
32         {
33             get { return width; }
34             set { width = value; }
35         }
36         int height;
37 
38         public int Height
39         {
40             get { return height; }
41             set { height = value; }
42         }
43 
44         int speed;//子弹的速度,实际上就是子弹的x坐标不断的减去speed,图形在绘制的过程中向左移动
45 
46         public int Speed
47         {
48             get { return speed; }
49             set { speed = value; }
50         }
51         Rectangle rect;
52         //绘制子弹
53         public void Draw(Graphics  g)
54         {
55             
56             rect = new Rectangle(X,Y,Width,Height);
57             g.DrawImage(MyRes.Bullet, rect);
58         
59         }
60         //思考发射的过程,发射子弹应该属于小猪的事情
61 
62         //第十步2:
63         public bool Intersect(Bird bird)
64         {
65             //第十步4:测试成功,追加了小鸟的矩形区域
66            return rect.IntersectsWith(bird.RectBird);  //相交小鸟的矩形
67            
68         }
69 
70     }
71 }

小猪类:

View Code
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Drawing;
  6 using System.Windows.Forms;
  7 
  8 namespace CrazyBird_GDI
  9 {
 10     class Pig
 11     {
 12         int x;
 13 
 14         public int X
 15         {
 16             get { return x; }
 17             set { x = value; }
 18         }
 19         int y;
 20 
 21         public int Y
 22         {
 23             get { return y; }
 24             set { y = value; }
 25         }
 26         int width;
 27 
 28         public int Width
 29         {
 30             get { return width; }
 31             set { width = value; }
 32         }
 33         int height;
 34 
 35         public int Height
 36         {
 37             get { return height; }
 38             set { height = value; }
 39         }
 40         int step;//小猪上下移动的值
 41 
 42         public  int Step
 43         {
 44             get { return step; }
 45             set { step = value; }
 46         }
 47 
 48         //思考:我们发现小鸟和小猪背景之间有很多共同的属性,可以用什么来解决?----继承
 49 
 50         public void Draw(Form form,Graphics g)
 51         {
 52             X = form.Width - 100;
 53             Y = (form.Height - Height) / 2-Step;
 54             Rectangle rect = new Rectangle(X,Y,Width,Height);
 55             g.DrawImage(MyRes.Pig, rect);
 56         }
 57 
 58         public void Move(Direct direct)
 59         {
 60             switch (direct)
 61             {
 62                 case Direct.UP:
 63                     Step += 10;//很有可能Step的值没有产生变化
 64 
 65                     break;
 66                 case Direct.DOWN:
 67                     Step -= 10;
 68                     break;
 69                 default:
 70                     break;
 71             }
 72         }
 73 
 74         // 第七步2:发射子弹  思考:这个方法写出来后,发现有问题。参数g在time控件中才能起到作用。而Fire方法的调用在 case Keys.Space: 这个地方调用,故不合理
 75         //重新构建
 76         public void Fire(List<Bullet> bullets,Graphics g)
 77         {
 78             foreach (Bullet item in bullets)
 79             {
 80                 item.Draw(g);
 81             }
 82         
 83         }
 84 
 85         //第七步3:发射子弹
 86         public Bullet FireABullet()
 87         {
 88             //第七步7:改良数据
 89             Bullet b = new Bullet();
 90         
 91           
 92             b.Width = 50;
 93             b.Height = 15;
 94             //第八步3: 
 95             b.Speed = 10;
 96 
 97             //第八步1:减去一个speed差值。
 98             b.X = X - b.Width-10-b.Speed;  //离小猪远一点距离 10个像素
 99             b.Y = Y+b.Height/2;
100             return b;
101         }
102         //***----------------------第五阶段完成(发射子弹 )
103         //第八步开始:让子弹动起来,如何让子弹动起来呢?改变子弹的x坐标,如何改变呢?
104 
105     }
106     public enum Direct 
107     {
108         UP,DOWN
109     }
110 }

 

 

原帖:http://ha2ha.com/thread-3355-1-1.html

转载于:https://www.cnblogs.com/kuffy/archive/2012/05/23/2514348.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值