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

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

編輯:關於C語言

WillCollide()方法依據精靈的朝向判斷精靈前方是否為障礙物(即判斷障礙物數組Matrix[,]此時是否為0)。

有了它以後,我們同樣還需要像C#開發WPF/Silverlight動畫及游戲系列教程(Game Course):(十二)神奇的副本地圖 一樣建立一個名為NormalMoveTo()的方法用於精靈直線移動,此時我們只需要在第十二節代碼的基礎上增加精靈朝向部分即可:

//直線移動
private void NormalMoveTo(Point p) {
//總的移動花費
int totalcost = (int)Math.Sqrt(Math.Pow(p.X - Spirit.X, 2) + Math.Pow(p.Y - Spirit.Y, 2)) / GridSize * UnitMoveCost;
……
//創建主角朝向屬性動畫
double direction = Super.GetDirectionByTan(p.X, p.Y, Spirit.X, Spirit.Y);
doubleAnimation = new DoubleAnimation(
 direction,
 direction,
 new Duration(TimeSpan.FromMilliseconds(totalcost))
);
Storyboard.SetTarget(doubleAnimation, Spirit);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("Direction"));
storyboard.Children.Add(doubleAnimation);
//動畫播放
storyboard.Begin();
}

這裡要特別注意的是我用黃色背景注明的totalcost這個變量,它的值代表精靈在兩點間移動所需要花費的時間,計算它的目的是因為Storyboard動畫是基於時間軸的動畫(即在一個規定時間內完成指定動畫),第一節中也有相應的說明。因此,為了讓精靈在全角度(不僅僅是8個方向,是360度全方位)的任意兩點間直線移動時均使用統一速度(每移動一個單元格固定花費UnitMoveCost毫秒),這樣不論兩點間是30度、40度、55度、76.3度、87.6度等等隨意多少角度,精靈均能進行平滑的均速移動。

OK,一切就緒,接下來就是在游戲窗口中的鼠標左鍵點擊事件中啟動精靈的直線移動:

private void CarrIEr_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
Point p = e.GetPosition(Map); //點擊的地方在Map中的坐標點
 //假如點擊的地點不是障礙物
 if (Matrix[(int)p.X / GridSize, (int)p.Y / GridSize] != 0) {
  Spirit.Destination = p; //設置主角的最終移動目的地
  Spirit.Action = Actions.Run; //主角動作切換成跑步狀態
  Spirit.IsAStarMoving = false; //非尋路模式
  NormalMoveTo(p); //兩點間建立直線移動
}
}

看完上面代碼有朋友就要問了:IsAStarMoving是什麼東西?簡單講,它是精靈直線移動與A*尋路移動的樞紐。雖然我們實現了NormalMoveTo()和AStarMoveTo()這兩種移動方式,但是如何在邏輯中對其進行很好的銜接,這裡就必須加入IsAStarMoving這個精靈屬性,有了它,我們就可以在窗口刷新事件中這樣寫:

//游戲窗口刷新主線程間隔事件
private void Timer_Tick(object sender, EventArgs e) {
 ……
 //判斷主角是否移動到了目標,如果是則動作切換成停止
 if (ArriveTarget()) {
  Spirit.Action = Actions.Stop;
 } else if (!Spirit.IsAStarMoving && WillCollide()) {
  //在尋路移動模式中,主角100%會饒過障礙物的,
  //因此只有在非尋路模式中才需要時時判斷主角是否將要碰撞障礙物
  AStarMoveTo(Spirit.Destination);
  Spirit.IsAStarMoving = true;
 }
}

通過黃色背景代碼部分的邏輯我們可以輕松實現精靈的直線移動與A*移動的轉換。即精靈首先進行直線移動,在它沒有到達目的地之前(ArriveTarget()==false)我們需要時時判斷它是否將要碰撞到障礙物(判斷WillCollide()是否==True),並且前提是精靈在此移動中還沒啟動過A*尋路(IsAStarMoving==false),因為一旦在直線移動中啟動過A*尋路,結果100%會引導精靈饒過障礙物到達終點,A*尋路過程中不需要額外再判斷是否還會碰撞到障礙物,那是多此一舉(如果出現偶然,不要怪別人,怪自己沒把A*算法寫正確)。如果此兩個條件都符合了,則以精靈的移動目標(Destination)為終點啟動A*尋路模式,這樣就順利的由直線移動轉入到A*尋路移動,完美的銜接與樞紐。

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