學習了楊中科版的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);
}
}
}