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

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

編輯:關於C語言

C#開發WPF/Silverlight動畫及游戲系列教程(Game Course):(二十) 第一部分拓展小結篇

寫了20節,一路向追著鬼子打一樣都沒停過,索性也想暫時休息一下整理整理思緒好完成後面的第二部分更為精彩的內容:諸如跟隨式地圖移動模式、NPC & 怪物 與主角的互動、對象AI、攻擊與魔法、各種類型傷害計算、完美的RPG游戲界面……等等等等,激動嗎?講實話:我很激動!

讀者聲音:還沒寫就開始激動了,典型的傻子。

^_^||言歸正傳,本節就先來個承上啟下的的小結吧,我打算分4個部分對前20節內容進行補充拓展:

一、完美的改進型A*尋路移動模式

在C#開發WPF/Silverlight動畫及游戲系列教程(Game Course):(十九) 完美精靈之八面玲珑(WPF Only)③中,我們雖然實現了精靈的全方向與動作,但是細心的朋友就會發現,精靈在走路的時候一直使用著A*;這將導致兩個問題:1、性能上的損失,每次移動不管中間是否有障礙物都啟動尋路算法,造成資源的白白浪費;2、在C#開發WPF/Silverlight動畫及游戲系列教程(Game Course):(十二)神奇的副本地圖 的結尾我曾輕描淡寫的敘述了如何實現改進型A*,雖然通過副本地圖簡單實現了,但是暫時並不完美。那麼,下面我將向大家講解通過地地道道的方法實現改進型完美A*移動模式。

何謂改進型完美A*移動模式?即主角每次移動時,首先並不啟動A*尋路而是直接建立兩點間的直線移動;接下來即進行時時的障礙物判斷,如果沒有碰撞到任何障礙物或對象則將該直線移動保持到終點;但是中途一旦碰到障礙物,則以目的地為終點即時啟動A*尋路。

原理很簡單,關鍵技術就是如何對碰撞進行檢測?

傳統的方法有兩種:

第一種我且稱之為坐標還原法:即時時記錄精靈未碰撞障礙物時的坐標(Old_X,Old_Y),在精靈移動時一旦檢測到精靈此時站到了障礙物上,則將精靈此時的坐標進行還原(X=Old_X,Y= Old_Y),然後啟動A*尋路。此方法的優點是使用簡單,不需要復雜的判斷邏輯;缺點是效果不好,在畫面上將造成精靈一瞬間被彈開的情況,雖然那一刻非常的短暫且距離微小,但是對於精靈移動動畫平滑性的影響是嚴重的,因此我們最好不要采用此方法。

第二種為啟發式預測法:該方法的原理為時時對精靈前方的區域進行預測,一旦發現前方有障礙物,則即時啟動A*尋路直到目的地。該方法可謂絕對皇室血統,一個字“正”,集所有優點之大成者;優點多相對的實現起來難度就大些。在WPF/Silverlight中如何實現之?先來看下圖:

上圖中已經給了很詳細的說明,即在直線移動過程中,精靈時時判斷此時朝向前方的單元格是否為障礙物,如果是則啟動A*尋路饒過它。充分理解了原理後,我們可以通過如下方法來返回精靈是否將要遇到障礙物了:

//判斷是否將要碰撞到障礙物(障礙物預測法)
private bool WillCollide() {
switch ((int)Spirit.Direction) {
 case 0:
  return Matrix[(int)(Spirit.X / GridSize), (int)(Spirit.Y / GridSize) - 1] == 0 ? true : false;
 case 1:
  return Matrix[(int)(Spirit.X / GridSize) + 1, (int)(Spirit.Y / GridSize) - 1] == 0 ? true : false;
 case 2:
  return Matrix[(int)(Spirit.X / GridSize) + 1, (int)(Spirit.Y / GridSize)] == 0 ? true : false;
 case 3:
  return Matrix[(int)(Spirit.X / GridSize) + 1, (int)(Spirit.Y / GridSize) + 1] == 0 ? true : false;
 case 4:
  return Matrix[(int)(Spirit.X / GridSize), (int)(Spirit.Y / GridSize) + 1] == 0 ? true : false;
 case 5:
  return Matrix[(int)(Spirit.X / GridSize) - 1, (int)(Spirit.Y / GridSize) + 1] == 0 ? true : false;
 case 6:
  return Matrix[(int)(Spirit.X / GridSize) - 1, (int)(Spirit.Y / GridSize)] == 0 ? true : false;
 case 7:
  return Matrix[(int)(Spirit.X / GridSize) - 1, (int)(Spirit.Y / GridSize) - 1] == 0 ? true : false;
 default:
  return true;
}
}

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