C#开发-----坦克大战游戏

 
 

转载请标明是引用于 http://blog.csdn.net/chenyujing1234

 例子代码:

http://www.rayfile.com/zh-cn/files/bad6d707-8dd9-11e1-9c19-0015c55db73d/
 
 
玩家操作一辆坦克,必须消灭所有电脑控制的10辆敌军坦克。本游戏的背景墙砖为金属,不可以被击毁。在游戏中,玩家通过键盘的方向键控制己方坦克的行进方向,并可以按空格键发射子弹,当对方坦克被中,产生爆炸图案和音效。如果玩家的坦克被销毁或敌方坦克全部被击毁,游戏便告终止。游戏运行界面如图11-1所示。
C#开发-----坦克大战游戏_第1张图片
 
程序设计的思路
A、 游戏画面看成10*10的方格,窗体中Map[10, 10]保存游戏砖块位置的地图,其中0代表空地,1代表墙砖。TMap[10, 10]保存坦克位置和砖位置的地图,其中0代表空地,1代表墙砖;2到5为敌方坦克,6为己方坦克。游戏面板重画时,TMap保存的信息传入,便于判断子弹是否击中坦克和墙砖。
B、 游戏画面的刷新采用2个定时器控件timer1和timer2。timer1控件定时控制敌方坦克的移动并刷新游戏面板,timer2控件定时产生新的敌方坦克直到达到敌方坦克最大量。
 
 
1. 坦克类 Tank 设计 —— 重点讲解
 
A、 坦克类Tank:游戏中,主要角色是坦克,设计的坦克类Tank需要实现坦克发射子弹,显示坦克图案,坦克爆炸,改变方向,产生子弹,控制子弹的移动功能。
定义以下描述坦克特征的字段。
    private int width;    //坦克的宽度
    private int height;   //坦克的高度
    private int top;      //坦克位置的纵坐标
    private int left;     //坦克位置的横坐标
    private int type;     //坦克的类型(2---5敌方,6己方)
    private int direct;    //0--上,1--下,2--左,3--右
    public ArrayList bList=new ArrayList();//子弹序列
B、 每辆坦克发射的子弹序列采用 ArrayList 列表数组 bList ,可以动态的增删。
  C#开发-----坦克大战游戏_第2张图片
 
坦克类Tank构造函数
 
坦克类Tank构造函数,随机产生坦克的方向代号以及坐标,类型代号由参数传入。
    public Tank(int tank_type)//构造函数
    {
        Random r = new Random();
        this.direct = r.Next(0, 4);//产生0—3的数
        this.width = 32;
        this.height = 32;
        this.left = r.Next(0, 10);//产生0—9的数
        this.top = r.Next(0, 10);//产生0—9的数
        this.type = tank_type;
    }
 
设计访问坦克的5个私有字段的相应属性
 
           设计访问坦克的宽度,高度,位置坐标,类型,方向5个私有字段的相应属性。用private会使得它们不能被类外访问,于是就设计了有可供外部访问相应属性,以使得那些不能和外界接触的变量有被访问渠道。
    public int Top//Top 属性
    {
        get
        {
            return top;
        }
        set
        {
            if (top >= 0 && top <= 9)
            {
                top = value;
            }
        }
    }
 public int Left//Left属性
 public int Type//坦克的类型属性
 public int Direct//Direct属性(坦克方向)
 
改变坦克移动方向
 
当坦克遇到障碍物时,需要改变方向。newDirect()方法根据随机产生新的坦克移动方向。
    public void newDirect()
    {
        Random r = new Random();
        int new_Direct=r.Next(0, 4);//产生0—3的数
        while(this.direct == new_Direct)
            new_Direct = r.Next(0, 4);//产生0—3的数
        this.direct = new_Direct;
    }
   //0-- ,1-- ,2-- ,3--
 
绘制坦克在游戏面板中
 
public void Draw(Graphics g,int type)//根据坦克类型选择不同图片
    {
        Image tankImage = Image.FromFile("BMP/ETANK1.BMP");
        if (type == 2) tankImage = Image.FromFile("BMP/ETANK2.BMP");
        if (type == 3) tankImage = Image.FromFile("BMP/ETANK3.BMP");
        if (type == 4) tankImage = Image.FromFile("BMP/ETANK4.BMP");
        if (type == 5) tankImage = Image.FromFile("BMP/ETANK1.BMP");
        if (type == 6) tankImage = Image.FromFile("BMP/MYTANK.BMP");
      //得到绘制这个坦克图形的在游戏面板中的矩形区域
        Rectangle destRect = new Rectangle(this.left * width, this.top  * height, width,height);
        Rectangle srcRect = new Rectangle(direct * width, 0, width, height);
        g. DrawImage ( tankImage , destRect,srcRect,GraphicsUnit.Pixel  );
    }
 
Explore(Graphics g)在屏幕上画出坦克爆炸动画
 
坦克被击中,Explore(Graphics g)在屏幕上画出坦克爆炸动画。
    public void Explore(Graphics g)//坦克爆炸动画
    {
        //得到绘制这个坦克图形的在游戏面板中的矩形区域
        Rectangle destRect = new Rectangle(this.left * width, this.top * height, width, height);
        Rectangle srcRect = new Rectangle(0, 0, width, height);
        Image tankImage = Image.FromFile("BMP/explode1.bmp");
        g.DrawImage(tankImage, destRect, srcRect, GraphicsUnit.Pixel);
        tankImage = Image.FromFile("BMP/explode2.bmp");
        g.DrawImage(tankImage, destRect, srcRect, GraphicsUnit.Pixel);
        PlaySound.Play("Sound/Explode.wav");
    }
 
 
发射子弹
 
敌我不同坦克,发射不同样式的子弹,发射的子弹加入每辆坦克的子弹序列bList中,如果己方发射子弹并产生发射子弹声音效果。Fire方法实现此功能。
    public void fire()
    {
        bullet b = new bullet(this.type);//根据坦克产生不同子弹
        b.Direct = this.Direct;//坦克的朝向
        b.Top = this.Top;
        b.Left = this.Left;
        bList.Add(b);
        if(this.type==6) PlaySound.Play("Sound/Shoot.wav");//己方发射声音效果
    }
 
移动子弹
 
  public void MoveBullet(ref int [,]Map)
    {
        for (int i = bList.Count-1; i>=0; i--)//遍历子弹序列
        {
            bullet t = ((bullet)bList[i]);
            t.move();//移动子弹
            if (t.Left < 0 || t.Left > 9 || t.Top < 0 ||t.Top > 9)
            //超出边界
            {
                bList.RemoveAt(i);continue;//删除此颗子弹
            }
            if (Map[t.Left, t.Top] != 0)//已遇到物体
            {
                    bList.RemoveAt(i); //删除此颗子弹
                    if (t.hitE(Map[t.Left, t.Top]))//击中对方坦克
                        Map[t.Left, t.Top] = -1;//此处坦克被打中
                    continue;
            }               
        }           
    }
 
画子弹DrawBullet( )方法
public void MoveBullet(ref int [,]Map)
    {
        for (int i = bList.Count-1; i>=0; i--)//遍历子弹序列
        {
            bullet t = ((bullet)bList[i]);
            t.move();//移动子弹
            if (t.Left < 0 || t.Left > 9 || t.Top < 0 ||t.Top > 9)
            //超出边界
            {
                bList.RemoveAt(i);continue;//删除此颗子弹
            }
            if (Map[t.Left, t.Top] != 0)//已遇到物体
            {
                    bList.RemoveAt(i); //删除此颗子弹
                    if (t.hitE(Map[t.Left, t.Top]))//击中对方坦克
                        Map[t.Left, t.Top] = -1;//此处坦克被打中
                    continue;
            }               
        }           
    }
 
画子弹DrawBullet( )方法
      DrawBullet方法中遍历子弹序列,并调用子弹的Draw方法将子弹显示在屏幕上。
    public void DrawBullet(Graphics g, int[,] Map)//画子弹
    {
        MoveBullet(ref Map);
        foreach (bullet t in bList)//遍历子弹序列
            t.Draw(g);
    }
 
2.子弹(bullet)类设计
     子弹类比较简单,主要完成子弹的移动和在屏幕上的显示。子弹类型type有两种:敌方子弹和己方子弹,从而使用bool类型。 己方子弹值为 true 敌方子弹值为 false
    定义以下描述子弹特征的字段。
    private int top;   // 子弹坐标( Top,Left)
    private int left;
    private int direct;// 子弹行进方向
    private int width = 32;
    private int height = 32;
    private bool type; // 己方子弹 true, 敌方子弹 false
    public bullet(int type) // 子弹类构造函数
    {
        if (type == 6)//己方
            this.type = true;
        else
            this.type = false;
    }
 
 
子弹的显示
n子弹类的Draw方法根据传入的游戏面板图形对象g,在游戏面板根据子弹坐标显示子弹图案。
    public void Draw(Graphics g)
    {
        Image bulletImage;
        if (type == true)//己方
            bulletImage = Image.FromFile("BMP/missile1.bmp");
        else
            bulletImage = Image.FromFile("BMP/missile2.bmp");
        //得到绘制这个子弹图形的在游戏面板中的矩形区域
        Rectangle destRect = new Rectangle(left * width, top * height, width, height);
        Rectangle srcRect = new Rectangle(0, 0, width, height);
        g.DrawImage(bulletImage, destRect, srcRect, GraphicsUnit.Pixel);
    }
 
 
子弹移动
 
n 判断子弹行进方向Direct,修改坐标值。子弹行进方向是坦克在发射子弹时设置的,和坦克的行进方向一致。坦克的方向上下左右分别用数字0,1,2,3表示,子弹的方向同样表示。例如Direct属性值为0,表示向上行进,所以Top值减1。
    public void move()
    {
        switch (Direct)
        {
            case 0:  //向上
                Top--; break;
            case 1:
                Top++; break;
            case 2:
                Left--; break;
            case 3:
                Left++; break;
        }
    }
 
判断是否击中对方坦克
 
public bool hitE(int tanktype)//是否击中对方坦克
    {
        if (type == false)// 敌方子弹
            if (tanktype >= 2 && tanktype <= 5)// 敌方 坦克
                //坦克的类型(2---5敌方,6己方)
                return false;
            else
                return true;
        if (type == true)// 己方子弹
            if (tanktype == 6)//坦克的类型(2---5敌方,6己方)
                return false;
            else
                return true;
        return false;
    }
 
4.游戏窗体类设计
C#开发-----坦克大战游戏_第3张图片
下面讲解游戏窗体代码
 
窗体Load的事件
窗体Load的事件中随机产生背景墙砖图案,保存Map[10, 10]中。同时将己方坦克定位到(4,9)坐标处,行进方向初始化为向上。
    private void Form1_Load(object sender, System.EventArgs e)
    {
        pictureBox1.Width = 10 * width;
        pictureBox1.Height  = 10 * width;
        path = Application.StartupPath;
        Random r = new Random();
        for(int x=0;x<10;x+=2)
            for (int y = 0; y < 10; y+=2)
            {
                //产生0,1数其中0代表空地,1代表墙砖 
                Map[x, y] = r.Next(0, 2);
            }
        Map[4, 9] = 0;
        MyTank.Top = 9;
        MyTank.Left = 4 ;
        MyTank.Direct = 0;
        lblX.Text = "X坐标:" + MyTank.Left+"  Y坐标:" + MyTank.Top;
    }
 
画游戏墙砖
 
 
 private void DragWall(Graphics g)//画游戏地图墙砖
    {
        Image WallImage = Image.FromFile("BMP/TQ.BMP");
        for(int x=0;x<10;x++)
             for (int y = 0; y < 10; y++)
             {
                if (Map[x, y] == 1)
                {
                     //得到绘制这个墙砖块的在游戏面板中的矩形区域
                Rectangle Rect = new Rectangle(x * width, y * width, width, width);
                g.DrawImage(WallImage, Rect);
                }
             }        
    }
 
定时产生新敌方坦克
 private void timer2_Tick(object sender, EventArgs e)//定时产生新敌方坦克
    {
        if (eCount < eMaxCount)//eMaxCount敌方坦克最大量
        {
            //敌方坦克类型为3,改变此数可以产生不同图案的地方坦克
            eTank = new Tank(3);
            eTanks.Add(eTank);// eTanks[eCount] = eTank;
            eCount++;
        }
        else
            timer2.Enabled = false;//不再产生新的敌方坦克
    }
 
 
timer1 控件定时控制敌方坦克的移动
 
timer1控件定时控制敌方坦克的移动并刷新游戏面板。
 private void timer1_Tick(object sender, EventArgs e)
    {
        foreach (Tank t in eTanks)
        {
            switch (t.Direct)//0--上,1--下,2--左,3--右
            {
                case 0:  //向上……
                case 1: //向下    ……
                  case 2:  //向左  …..
                case 3:   // 向右
                    if (t.Left == 9 || Map[t.Left+1, t.Top ] == 1
                        || Meet_Tank(t.Left+1, t.Top))//遇到墙砖或坦克
                        t.newDirect();//坦克转向
                    else
                        t.Left++;
                    break;
            }
            Random r = new Random();
            int fire_bool = r.Next(0, 8);//产生0—7的数
            if (fire_bool == t.Direct)  t.fire();
        }
        pictureBox1.Invalidate();//重画游戏面板区域           
    }
 
游戏面板 pictureBox1 Paint 事件
n游戏面板pictureBox1的Paint事件最复杂。
nPaint事件中完成以下任务:
1.完成修改TMap[10, 10] ,保存墙砖位置
2.完成重画墙砖,
3.画敌方坦克及子弹,
4.画己方坦克和己方子弹。
5.最后根据Tmap数组中某处的值是否为-1,处理坦克爆破。
6.当玩家自己的坦克被击中,timer1控件定时器无效,游戏结束。
7.调用CheckWin()检查是否敌方所有坦克被击毁,如果是则玩家胜利,游戏结束。
 

你可能感兴趣的:(游戏,timer,image,object,C#,Random)