private void AStarMoveTo(Point p) {
int start_x = GameSystemX;
int start_y = GameSystemY;
Start = new System.Drawing.Point(start_x, start_y);
int end_x = (int)p.X / GridSize;
int end_y = (int)p.Y / GridSize;
End = new System.Drawing.Point(end_x, end_y);
if (path == null) { /* 路徑不存在 */ }
else {
......
DoubleAnimationUsingKeyFrames keyFramesAnimationX = new DoubleAnimationUsingKeyFrames();
keyFramesAnimationX.Duration = new Duration(TimeSpan.FromMilliseconds(path.Count * cost));
Storyboard.SetTarget(keyFramesAnimationX, Spirit);
Storyboard.SetTargetProperty(keyFramesAnimationX, new PropertyPath("X"));
DoubleAnimationUsingKeyFrames keyFramesAnimationY = new DoubleAnimationUsingKeyFrames();
keyFramesAnimationY.Duration = new Duration(TimeSpan.FromMilliseconds(path.Count * cost));
Storyboard.SetTarget(keyFramesAnimationY, Spirit);
Storyboard.SetTargetProperty(keyFramesAnimationY, new PropertyPath("Y"));
for (int i = 0; i < framePosition.Count(); i++) {
LinearDoubleKeyFrame keyFrame = new LinearDoubleKeyFrame();
keyFrame.Value = i == 0 ? Spirit.X : (framePosition[i].X - SpiritCenterX) * GridSize;
keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(cost * i));
keyFramesAnimationX.KeyFrames.Add(keyFrame);
keyFrame = new LinearDoubleKeyFrame();
keyFrame.Value = i == 0 ? Spirit.Y : (framePosition[i].Y - SpiritCenterY) * GridSize;
keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(cost * i));
keyFramesAnimationY.KeyFrames.Add(keyFrame);
}
......
}
}
關鍵修改(黃底):
1. Storyboard.SetTargetProperty(..., new PropertyPath("X")) 目標改為精靈控件的 X 依賴屬性(而非 Canvas.Left)。
2. 首幀用 Spirit.X/Y 平滑銜接,後續幀按 cost 遞增時間。忽略此處理會導致重新點擊時角色跳動(起始座標定位錯誤 Bug)。
關鍵幀平滑銜接示意圖(GridSize=20)。
private void Carrier_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
Point p1 = e.GetPosition(Map);
AStarMoveTo(p1);
}
e.GetPosition(Map) 直接獲取地圖圖片上的點擊座標。TranslatePoint 亦可達同樣效果,適用於邊緣判斷、碰撞檢測、射程計算。
Ctrl+F5:任意點擊地圖移動,隨時牽引地圖,主角與障礙物平滑顯示正確位置。This is Perfect!
匯總前章知識,構建 GridSize=30、斜度 60° 回合制戰棋戰鬥場景。先解決懸念已久的大問題:精靈八方向實現。兩枚重磅炸彈即將登場!