x01.Game.Dragon.2: 箭术表演
只要想射中,就能射中,所以叫箭术表演。
1.给 Sprite 类添加一属性:
public bool Alive { get; set; }
因为要射中恐龙,所以还需一碰撞检测函数 HasCollision(),代码如下:
public bool HasCollision(ref Sprite other) { return Bound.IntersectsWith(other.Bound); }
2.现在要修改 MainForm 类了。主要是添加了 arrow,archer 字段。变化的地方,即注释的地方。完整代码如下:
public partial class MainForm : Form { const string ImgDir = @"F:\Resource\Image\game\"; GameBox gameBox; Sprite dragon; Sprite archer; Sprite arrow; //Bitmap dragonImage; //Bitmap grass; //PointF offset; bool isOver = false; //int direction = 2; int score = 0; public MainForm() { InitializeComponent(); Init(); } protected override void OnClosed(EventArgs e) { GameOver(); } protected override void OnKeyDown(KeyEventArgs e) { switch (e.KeyCode) { case Keys.Enter: Run(); break; case Keys.Escape: GameOver(); break; case Keys.Space: if (!arrow.Alive) { archer.FrameDirection = Sprite.FrameDirectionE.Forward; archer.CurrentFrame = 10; } break; //case Keys.Up: // direction = 0; // break; //case Keys.Right: // direction = 2; // break; //case Keys.Down: // direction = 4; // break; //case Keys.Left: // direction = 6; // break; } } void Run() { int currentTime = 0, startTime = 0; while (!isOver) { ArrowUpdate(); currentTime = Environment.TickCount; if (currentTime > startTime + 16) { startTime = currentTime; Draw(); Application.DoEvents(); gameBox.Refresh(); } } Application.Exit(); } private void GameOver() { isOver = true; } private void Init() { Text = "Dragon Game"; Size = new Size(800, 600); gameBox = new GameBox(800, 600); gameBox.Parent = this; gameBox.Dock = DockStyle.Fill; gameBox.Print(10, 10, "Enter: 开始"); //dragonImage = new Bitmap(ImgDir + "dragon.png"); //grass = new Bitmap(ImgDir + "grass.bmp"); dragon = new Sprite(ref gameBox); dragon.Image = new Bitmap(ImgDir + "dragon.png"); dragon.Size = new Size(256, 256); dragon.Columes = 8; dragon.Frames = 64; dragon.Position = new PointF(250, 50); dragon.Offset = new PointF(-4, 0); arrow = new Sprite(ref gameBox); arrow.Image = new Bitmap(ImgDir + "arrow.png"); arrow.Size = new Size(32, 32); arrow.Columes = 1; arrow.Frames = 1; arrow.Alive = false; arrow.Offset = new PointF(0, -12); archer = new Sprite(ref gameBox); archer.Image = new Bitmap(ImgDir + "archer_attack.png"); archer.Size = new Size(96, 96); archer.Columes = 10; archer.Frames = 80; archer.Position = new PointF(360, 500); archer.FrameDirection = Sprite.FrameDirectionE.None; } void Draw() { Bitmap grass = new Bitmap(ImgDir + "grass.bmp"); gameBox.Device.DrawImageUnscaled(grass, 0, 0, 800, 600); if (arrow.Alive) { arrow.Position = new PointF(arrow.Position.X, arrow.Position.Y + arrow.Offset.Y); if (arrow.Position.Y < -32) { arrow.Alive = false; } arrow.Draw(); } archer.Animation(10, 19); if (archer.CurrentFrame == 19) { archer.FrameDirection = Sprite.FrameDirectionE.None; archer.CurrentFrame = 10; arrow.Alive = true; arrow.Position = new PointF(archer.Position.X + 32, archer.Position.Y); } archer.Draw(); dragon.Position = new PointF(dragon.Position.X + dragon.Offset.X, dragon.Position.Y); if (dragon.Position.X < -128) { dragon.Position = new PointF(800, dragon.Position.Y); } dragon.Animation(6 * 8 + 1, 6 * 8 + 8); dragon.Draw(); gameBox.Print(0, 0, "\nScore: " + score.ToString()); //Bitmap grass = new Bitmap(ImgDir + "grass.bmp"); //gameBox.Device.DrawImageUnscaled(grass, 0, 0, 800, 600); //switch (direction) //{ // case 0: // up // offset = new PointF(0, -1); // break; // case 2: // right // offset = new PointF(1, 0); // break; // case 4: // down // offset = new PointF(0, 1); // break; // case 6: // left // offset = new PointF(-1, 0); // break; // default: // break; //} //dragon.Position = new PointF(dragon.Position.X + offset.X, dragon.Position.Y + offset.Y); //dragon.Animation(direction * 8 + 1, direction * 8 + 8); //dragon.Draw(); gameBox.Print(0, 0, "Esc: 结束 Space: 射箭"); } void ArrowUpdate() { if (arrow.Alive) { if (arrow.HasCollision(ref dragon)) { arrow.Alive = false; score++; dragon.Position = new PointF(800, dragon.Position.Y); } } } }
虽然能射击,但没有声音,未免美中不足。
3.声音分两种,一种为即时音效,如射中恐龙时听到的电击声: foom.wav 文件;一种为背景音乐: song.mid 文件。
要实现即时音效,首先在 MainForm 中添加字段
SoundPlayer soundPlayer;
然后添加一个设置该字段的方法 SetSoundPlayer(),代码如下:
public SoundPlayer SetSoundPlayer(string path) { SoundPlayer player = null; try { player = new SoundPlayer(); player.SoundLocation = path; player.Load(); } catch (Exception ex) { MessageBox.Show(ex.Message); } return player; }
在 Init() 中使用此方法初始化 soundPlayer 字段:
soundPlayer = SetSoundPlayer(ImgDir + "foom.wav");
在 ArrowUpdate() 中如检测碰撞恐龙为真,则添加语句:
soundPlayer.Play();
如此,即时音效完成。
要实现背景音乐,需要 interop.WMPLib.dll, 或 COM 中的 Window Media Player 组件,注意是 wmp.dll 。添加该库引用后,在 MainForm 中添加字段:
WindowsMediaPlayer wmPlayer;
在 Init() 中初始化该字段:
wmPlayer = new WindowsMediaPlayer();
wmPlayer.URL = ImgDir + "song.mid";
按 F5,即可听到背景音乐。如射中恐龙,即时音效也能听到。所有相关资源,可到 x01.download 下载。