杨中科版C#射击游戏

学习了杨中科版的C#射击游戏视频,大家可参考http://player.youku.com/player.php/sid/XMTUyNjQ3NjQ0/v.swf

准备素材,一张飞机图片,一个WAV的飞机遇到子弹爆炸音效。
1.创建一个WinForm应用程序
Form窗体,拖一个panel控件,相当于战场。拖一个Timer控件,操纵飞机与子弹运行。
panel控件中用到会三个事件,一个是Paint事件,用来触发调用画飞机和子弹。第一个是MouseClick事件,主要用来任意点击panel区域时,发射子弹。还有一个是Timer的Tick事件,用来控制飞机与子弹的移动。
2.创建抽象类GameObject,用于子弹类,飞机类继承。子弹和飞机,共同拥有的属性,在panel上的X,Y的坐标,以及Draw()画子弹/飞机和Move()移动的方法。
3.创建子弹Bullut与飞机Plane的类继承于抽象类GameObject;同时添加子弹自己的特有的属性和方法,例如,Bullet类自己的属性有bool isFired,判断是否发射子弹(子弹是当鼠标点击时才需要发射),Bullet类自己的方法有判断子弹是否击中飞机bool IsHit();
Panel类自己有属性有HitTime子弹击中的次数,本游戏中子弹需击中两次方可爆炸,并发出爆炸音。
bool IsVisble属性用于当子弹第一次击中飞机时,飞机开始闪烁,(闪烁实现的效果就是一会让飞机画在panel上,一会又把它隐藏掉),Panel类中自己的方法有Resart,当飞机飞到边界时或击碎时,飞机需从左边重新出现。
4.新建一个GamePanel类,让它继承于Panel控件,解决游戏中在运行中飞机不停闪烁的问题(不是击中第一次后飞机闪烁)。应用了双缓冲。
具体代码如下:

Form1.cs
using System;
using System.Windows.Forms;
using System.Drawing;
using Game.Properties;
using System.Media;

namespace Game
{
    public partial class Form1 : Form
    {
        Plane plane;
        Bullet bullet;
        public Form1()
        {
            InitializeComponent();
            NewBullet();
            NewPlane();
        }

       //实例化一个子弹

        private void NewBullet()
        {
            bullet = new Bullet();
            bullet.isFired = false;
            bullet.rect = panelFiled.ClientRectangle;
            bullet.Y = panelFiled.ClientRectangle.Height;
        }
       //实例化一个飞机
        private void NewPlane()
        {
            plane = new Plane();
            plane.Restart();
            plane.rect= panelFiled.ClientRectangle;
            Random rad = new Random();
            plane.Y = rad.Next(0, 100)//飞机随机在左侧Y轴方向出现

        }

        private void panelFiled_Paint(object sender, PaintEventArgs e)
        {
           
            plane.Draw(e.Graphics);
            bullet.Draw(e.Graphics);
                  
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            bullet.Move();
            plane.Move();
            if (bullet.Ishit(plane) == true)//判断当子弹击中飞机时的情况
            {
                NewBullet();
                plane.HitTime++;
                if (plane.HitTime == 2)//当两次击中时,发出爆炸声音
                {
                    NewPlane();
                    SoundPlayer player = new SoundPlayer(Resources.BOMB);
                    player.Play();
                                
                }
            }
            panelFiled.Invalidate();
        }

        private void panelFiled_MouseClick(object sender, MouseEventArgs e)
        {
            bullet.isFired = true; //当鼠标开始点击中,发射子弹
            bullet.X = e.X;
            bullet.Y = panelFiled.ClientRectangle.Height;
            panelFiled.Invalidate();

        }

     
    }
 
}
//抽象类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Game
{
   
   
   abstract class GameObject
    {
        public int X { get; set; }
        public int Y { get; set; }
        public Rectangle rect { get; set; }
        public abstract void Draw(Graphics e);
        public abstract void Move();
    }
 

}


//子弹类
using System.Drawing;
using System;


namespace Game
{

    class Bullet:GameObject
    {
        public const int R = 5;//子弹的半径
        public bool isFired { get; set; }
        //画子弹
        public override void Draw(Graphics e)
        {
            if (isFired == false) //用来判断是否开始点击,没有点击不可自动发射子弹
            {
                return;
            }
            e.FillEllipse(new SolidBrush(Color.Black), X, Y, R * 2, R * 2);
          
        }
        public override void Move()
        {
            if (isFired == false)
            {
                return;
            }
            Y=Y-3;//向上移动
        }
        //判断子弹是否击中飞机,求出两物体之间的距离,如果小于小物体的半径之各则判断其相撞
        public bool Ishit(Plane plane)
        {
            int detalX = plane.X - X;
            int detalY = plane.Y - Y;
            double dist = Math.Sqrt(detalX * detalX + detalY * detalY);
            if (dist > Bullet.R + Plane.R)
            {
                return false;

            }
            else
                return true;
        }    
    }
}

//飞机类

namespace Game
{
    class Plane:GameObject
    {
        public const int R = 25;
        public int HitTime { get; set; }
        private bool isVisble;
        public int speed { get; set; }
        Random rad = new Random();
        public override void Draw(Graphics e)
        {
            if (HitTime == 1) //判断击中一次时,飞机开始闪烁,让其时而可见,时而消失
            {
                isVisble = !isVisble;
                if(!isVisble)
                {
                    return;
                }

            }
            e.DrawImage(Resources.plane, X, Y, R*2, R*2);
        }
       //飞机爆炸或都撞到右侧panel时,重新出现
        public void Restart()
        {
            speed = rad.Next(1, 3);
            Y = rad.Next(0, rect.Height);//重现出现的位置Y轴随机
            X = 0;
            HitTime = 0;//重现出现时击中次数为0
        }
        public override void Move()
        {
           //移动的速度
            X = X + speed;//向右移动
            if (X > rect.Width)
            {
                Restart();
            }
        }
    }
}

//解决双缓冲的类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Game
{
    class GamePanel:Panel
    {
        public GamePanel()
        {
            SetStyle(ControlStyles.UserPaint |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.ResizeRedraw |
                ControlStyles.SupportsTransparentBackColor, true);
       }
    }
}

原文地址:https://www.cnblogs.com/agile2011/p/2055517.html