主角始終處於游戲窗口的正中,那麼它距離左邊400像素,距離頂端300像素,因此,我們通過邊緣法可以得出,只需要根據主角的x,y坐標計算出主角當前所處的地圖切片代號。以上圖為例,此時主角所處的切片為2_3.jpg,那麼我們只需加載2_3以及它周邊的9張切片:1_2.jpg、2_2.jpg、3_2.jpg、1_3.jpg、2_3.jpg、3_3.jpg、1_4.jpg、2_4.jpg、3_4.jpg即可完美填充整個游戲窗口。當然,填充用地圖切片必須是自適應的,即時時根據主角所處位置來更換所需要切片。
理解原理後,代碼實現起來就簡單多了,首先我們需要修改地圖Surface初始化代碼:
Canvas MapSurface;
int mapSectionWidth, mapSectionHeight, mapSectionXNum, mapSectionYNum;
/// <summary>
/// 初始化地圖地表層
/// </summary>
private void InitMapSurface(XElement args) {
MapSurface = new Canvas() {
Width = Convert.ToDouble(args.Attribute("Width").Value),
Height = Convert.ToDouble(args.Attribute("Height").Value),
};
Add(MapSurface);
mapSectionWidth = Convert.ToInt32(args.Attribute("SectionWidth").Value);
mapSectionHeight = Convert.ToInt32(args.Attribute("SectionHeight").Value);
mapSectionXNum = (int)(MapSurface.Width / mapSectionWidth);
mapSectionYNum = (int)(MapSurface.Height / mapSectionHeight);
}
然後我們定義兩個非常重要的切片定位用變量:
int _leaderSectionX;
/// <summary>
/// 主角所處的切片X值
/// </summary>
public int leaderSectionX {
get { return _leaderSectionX; }
set { if (_leaderSectionX != value) { _leaderSectionX = value; ChangeMapSection(); } }
}
int _leaderSectionY;
/// <summary>
/// 主角所處的切片Y值
/// </summary>
public int leaderSectionY {
get { return _leaderSectionY; }
set { if (_leaderSectionY != value) { _leaderSectionY = value; ChangeMapSection(); } }
}
leaderSectionX和leaderSectionY分別為主角所處的切片X,Y值(對應切片命名中下劃線“_”兩端的值),其中任意一個更改後都將激發ChangeMapSection方法:
Image mapSection;
int startSectionX, startSectionY,endSectionX,endSectionY;
/// <summary>
/// 更新呈現的地圖切片
/// </summary>
private void ChangeMapSection() {
MapSurface.Children.Clear();
if (leaderSectionX == 0) {
startSectionX = 0; endSectionX = 2;
} else if (leaderSectionX == mapSectionXNum - 1) {
startSectionX = leaderSectionX - 2; endSectionX = leaderSectionX;
} else {
startSectionX = leaderSectionX - 1; endSectionX = leaderSectionX + 1;
}
if (leaderSectionY == 0) {
startSectionY = 0; endSectionY = 2;
} else if (leaderSectionY == mapSectionYNum - 1) {
startSectionY = leaderSectionY - 2; endSectionY = leaderSectionY;
} else {
startSectionY = leaderSectionY - 1; endSectionY = leaderSectionY + 1;
}
for (int x = startSectionX; x <= endSectionX; x++) {
for (int y = startSectionY; y <= endSectionY; y++) {
mapSection = new Image() {
Source = Super.getImage(string.Format("Map/{0}/Surface/{1}_{2}.jpg", mapCode.ToString(), x, y)),
Width = mapSectionWidth,
Height = mapSectionHeight,
Stretch = Stretch.Fill,
};
MapSurface.Children.Add(mapSection);
Canvas.SetLeft(mapSection, x * mapSectionWidth);
Canvas.SetTop(mapSection, y * mapSectionHeight);
}
}
}