程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#開發WPF/Silverlight動畫及游戲系列教程(Game Tutorial):(四十)

C#開發WPF/Silverlight動畫及游戲系列教程(Game Tutorial):(四十)

編輯:關於C#

C#開發WPF/Silverlight動畫及游戲系列教程(Game Tutorial):(四十)向Silverlight移植②

三、新增功能:

1)新增游戲的音樂及音效對象:

public static MediaElement gameMusic, gameAudio;

2)新增游戲鼠標光標:

//設置游戲鼠標光標
GameCursor.Stretch = Stretch.Fill;
GameCursor.Source = Super.GetImage("/Image/Cursor/0.png");

在鼠標移動事件中根據命中測試進行時時的鼠標光標圖片位置更新:

//鼠標移動(懸停)事件
private void Game_MouseMove(object sender, MouseEventArgs e) {
……
Point p = e.GetPosition(Root);
GameCursor.SetValue(Canvas.LeftProperty, p.X); GameCursor.SetValue(Canvas.TopProperty, p.Y);
……
}

此方法實現了鼠標圖片跟隨光標移動,但是很明顯的影響了程序整體性能(CPU消耗會明顯增加),如果哪位朋友能提供更好的解決方案,望留言給我。

3)新增點擊水滴:

當鼠標在屏幕上左鍵點擊時,只要不點到對象物體上,則在該位置顯示出光標水滴,並播放它自身的動畫。目前我的Silverlight游戲引擎中只用一個光標水滴:

QXDecoration hitCursor;
/// <summary>
/// 加載光標點擊水滴
/// </summary>
private void LoadHitCursor() {
 hitCursor = new QXDecoration() {
  Code = 1,
  EndFrame = 9,
  CenterX = 32,
  CenterY = 32,
 };
 hitCursor.Visibility = Visibility.Collapsed;
 Add(hitCursor);
}
//鼠標左鍵事件
private void Game_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
……
//出現光標水滴
hitCursor.Visibility = Visibility.Visible;
hitCursor.FrameCounter = 0;
hitCursor.Timer.Start();
hitCursor.Coordinate = p;
……
}

如果您想最求更漂亮的點擊效果,那麼只需每次鼠標左鍵點擊時創建新的水滴即可:

private void Game_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
……
//出現光標水滴
QXDecoration hitCursor = new QXDecoration() {
 Code = 1,
 EndFrame = 9,
 CenterX = 32,
 CenterY = 32,
};
Add(hitCursor);
hitCursor.Coordinate = p;
}

四、360度極光類型魔法的制作及使用方法

大家在看Demo演示時,是否會對那個極光魔法充滿興趣與好奇。它不僅僅是動畫的,而且可以360度隨意旋轉,且傷害范圍為一個不規則矩形區域,而這所有的一切的原始素材僅為我制作的一張圖片而已,下面我將為大家演示它的整個制作流程。

首先我們畫出該魔法向X軸正向的圖片:

神奇的動畫效果就要出現啦,接下來每隔5個色相保存一張圖片:

最後保存出8張圖片,並按順序定義好名字:

素材准備工作完成,下面是邏輯上的實現。該極光魔法同樣通過QXMagic來創建實例,當點擊鼠標右鍵時,我們首先獲取鼠標右鍵點擊點的坐標,然後根據方法將之延長到攻擊距離。再根據公式計算出直角坐標系下實際應該旋轉的角度Angle:

/// <summary>
/// 根據兩點商值計算角度
/// </summary>
/// <param name="y">y2-y1值</param>
/// <param name="x">x2-x1值</param>
/// <returns>直角坐標系角度</returns>
public static double GetAngle(double y, double x) {
 return Math.Atan2(y, x) / Math.PI * 180;
}

然後還需要對極光魔法對象進行旋轉處理:

magic.RenderTransform = new RotateTransform() {
 CenterX = 0,
 CenterY = (double)magicData.Attribute("CenterY"),
 Angle = magic.Angle
}

其中CenterY將該魔法發射點及旋轉中心定位到施法者中心,即手的部位;施法時以該中心為旋轉軸進行旋轉。這裡還有個小技巧,即在制作激光魔法圖片時,我特意在激光頭部與圖片左邊邊緣留下一段距離,這樣做可以不需要額外的代碼即可以實現從手的前端發射出魔法處進行旋轉,而不是從身體中心進行旋轉發射:

接著確定傷害區域,該區域為一個時時的不規則矩形區域。處理時我將360二維空間劃分為斜4象限,即45度到135度和-135度到-45度這兩個象限為一個傷害區域、其他角度為另外的傷害區域,那麼最後得到的公式如下:

/// <summary>
/// 根據45度斜四象限獲取矩形四個頂點(直線穿梭魔法用)
/// </summary>
/// <param name="angle">旋轉角度</param>
/// <param name="start">矩形中線起點</param>
/// <param name="end">矩形中線終點</param>
/// <param name="radius">矩形中線與邊距離</param>
/// <returns>四個頂點</returns>
public static Point[] GetRectRange(double angle, Point start, Point end, int radius) {
 if ((angle >= 45 && angle <= 135) || (angle >= -135 && angle <= -45)) {
   return new Point[]{
    new Point(start.X - radius, start.Y),
    new Point(start.X + radius, start.Y),
    new Point(end.X + radius, end.Y),
    new Point(end.X - radius, end.Y),
   };
 } else {
   return new Point[]{
    new Point(start.X, start.Y - radius),
    new Point(start.X, start.Y + radius),
    new Point(end.X, end.Y + radius),
    new Point(end.X, end.Y - radius),
   };
 }
}

這樣做公式簡單,省掉了對每個頂點的獲取及旋轉變換。

最後通過判斷所有在屏幕中的敵對精靈坐標是否處於該矩形區域內進行傷害處理:

/// <summary>
/// 判斷點是否在多邊形內(射線法)
/// </summary>
/// <param name="target">目標點</param>
/// <param name="range">多邊形各頂點</param>
/// <returns></returns>
public static bool InPolygon(Point target, Point[] range) {
 int n = 0, count = 0;
 for (int i = 0; i < range.Length; i++) {
  n = (i == range.Length - 1) ? 0 : n + 1;
                 if ((range[i].Y != range[n].Y) && (((target.Y >= range[i].Y) && (target.Y < range[n].Y)) || ((target.Y >= range[n].Y) && (target.Y < range[i].Y))) && (target.X < (range[n].X - range[i].X) * (target.Y - range[i].Y) / (range[n].Y - range[i].Y) + range[i].X)) {
    count++;
  }
 }
 return (count % 2 > 0) ? true : false;
}

用了兩節的時間進行了本教程示例游戲從WPF向Silverlight平台的移植的關鍵點講解,當然細節的優化還有非常多,源碼發布後大家應該都能理解,因此這裡也不累述了。後面的教程均將在此Silverlight引擎的基礎上進行全新演義,下一節首先講解的是如何制作游戲中的小地圖,敬請關注。

出處:http://alamiye010.cnblogs.com/

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved