一切就緒,現在讓我們著手構建動態障礙物數組VaryObstruction。
同樣的,從實現原理切入。我們首先需要拷貝一份固定障礙物數組(FixedObstruction)的淺表副本賦給動態障礙物數組(VaryObstruction);然後循環遍歷索敵區域內的所有精靈對象,將它們占據區域全部示為障礙物區域並更新VaryObstruction;最後間隔一定時間重復以上過程繼續更新動態障礙物數組。
原理總是比較簡單的,做起來往往並非一帆風順。大家可以從原理中看出兩個重點:1、此過程是一個重復無限循環過程,因此我們可以將此之放在一個計時器中,讓Tick事件去處理;2、此過程是絕對的性能消耗,如果將之放在界面線程中,很肯定的將導致游戲刷新率大副下降,這將極其影響游戲的流暢性。聰明的朋友此時一定想到了後台處理;沒錯,這裡必須使用後台處理,而且必須是異步跨線程的(即不占用界面線程,同時又能讓結果直接影響到界面)。幸運的是,在WPF/Silverlight中,我們可以輕松的使用BackgroundWorker;在Winform時代用過它的朋友都很清楚,它是一個爽歪歪的東西。呵呵,那麼接下來的過程就再簡單不過了,且看功能實現的關鍵步驟及代碼:
第一步,創建這兩個重要對象:
//設置游戲窗體輔助線程
AuxiliaryThread = new DispatcherTimer(DispatcherPriority.Normal);
AuxiliaryThread.Tick += new EventHandler(AuxiliaryThread_Tick);
AuxiliaryThread.Interval = TimeSpan.FromMilliseconds(1000);
AuxiliaryThread.Start();
//設置後台工作者
BackWorker = new BackgroundWorker();
BackWorker.DoWork += new DoWorkEventHandler(BackWorker_DoWork);
BackWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackWorker_RunWorkerCompleted);
第二步,在輔助線程(AuxiliaryThread)計時器中啟動異步後台處理:
private void AuxiliaryThread_Tick(object sender, EventArgs e) {
//異步刷新面板及障礙物
if (!BackWorker.IsBusy) { BackWorker.RunWorkerAsync(); }
}
第三步,定義工作委托:delegate void WorkDelegate();
然後在已經注冊的後台處理事件(BackWorker_DoWork)中執行異步委托(RefreshFace),從而實現刷新動態障礙物數組:
private void RefreshFace() {
//將當前動態障礙物重置為原始固定值
VaryObstruction = (byte[,])FixedObstruction.Clone();
//重新填充動態障礙物
for (int i = 0; i < CarrIEr.Children.Count; i++) {
if (CarrIEr.Children[i] is QXSpirit) {
QXSpirit spirit = CarrIEr.Children[i] as QXSpirit;
if (spirit != Leader) {
int x = (int)(spirit.X / GridSizeX);
int y = (int)(spirit.Y / GridSizeY);
for (int m = x - spirit.HoldWidth; m <= x + spirit.HoldWidth; m++) {
for (int n = y - spirit.HoldHeight; n <= y + spirit.HoldHeight; n++) {
VaryObstruction[m, n] = 0;
}
}
}
}
}
}
private void BackWorker_DoWork(object sender, DoWorkEventArgs e) {
//跨線程異步刷新障礙物
this.Dispatcher.BeginInvoke(new WorkDelegate(RefreshFace), DispatcherPriority.Normal, null);
}