想當年Team有無數人在玩大菠蘿,我被忽悠進來作肉盾,選了蠻子,從1.0開始,經歷了10三、10五、10八、2.0、2.1。這個遊戲對我最大的幫助是學習了不一樣的技術,好比XAML、好比xcode開發、好比WP的開發。html
這篇文章不會step by step的介紹如何從0開始作WP開發,我會重點記錄開發過程當中要注意的坑,以及一些發佈上架時的注意事項。git
文中大部份內容對於熟悉XAML的人來說,可能過於簡單。放在這裏,但願對初學者有個幫助,尤爲是如我這樣作winform開發的人。github
先上幾張圖,chrome
玻璃渣如今有兩套API在並行運行,官方文檔老版本的地址:https://github.com/blizzard/d3-api-docs,新版本的地址:https://dev.battle.net/io-docs。shell
二者的區別是,前者不包含諸如堅韌、聖教軍等資料片中出現的內容,固然也不包括天梯、附魔等內容。後者不包含每一個裝備的item tooltip html。同時,後者必需要註冊一個開發者帳號(免費的)。windows
<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar BackgroundColor="Black" ForegroundColor="White" Mode="Default" Opacity="1.0" IsMenuEnabled="True" IsVisible="True"> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="Feedback" Click="Email_Click"/> <shell:ApplicationBarMenuItem Text="Share" Click="Share_Click"/> <shell:ApplicationBarMenuItem Text="Score" Click="Score_Click"/> <shell:ApplicationBarMenuItem Text="Clear Cache" Click="ClearCache_Click"/> <!--<shell:ApplicationBarMenuItem Text="Server Status" Click="ServerStatus_Click"/>--> </shell:ApplicationBar.MenuItems> <shell:ApplicationBarIconButton IconUri="/assets/appbar/search.png" Text="Search Friend" Click="AppbarAddFriend_Click"/> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>
這裏分爲兩部分,MenuItems是右下角三個點對應的菜單項,IconButton對應的是圖標按鈕。前者無對應圖標,若是是英文,則所有小寫字母;後者能夠指定是否只顯示圖標,或者同時顯示圖標與文字。api
<Line X2="300" Stroke="White" Height="1" StrokeThickness="3"></Line>
這段XAML畫一條白色的線,注意顏色及線寬都是用Stroke***屬性指定的。xcode
<TextBlock HorizontalAlignment="Right" Text="{Binding Toughness, Converter={StaticResource IntConverter}}">Toughness</TextBlock>
這個文本框綁定資料片中英雄的堅韌屬性,若是想按照千分位(或者你本身別的格式顯示),則再指定Converter的class信息。緩存
如,千分位的Convert代碼以下:app
public class IntConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return String.Format("{0:N0}", value); }
而若是顯示小數點後兩位的浮點數,則對應代碼爲:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return String.Format("{0:f2}", value); }
<Border BorderThickness="1" Height="130" Canvas.Left="72" Canvas.Top="515" Width="68" BorderBrush="{Binding ItemList[mainhand].BorderBrush]}" Tap="MainHand_Tap"> <Border.Background> <ImageBrush ImageSource="{Binding ItemList[mainhand].BorderBackGround}"/> </Border.Background> <Image Source="{Binding ItemList[mainhand].ItemImage}" Stretch="None" Height="128" Width="64" Margin="0,0,0,0"/> </Border>
這個page的DataContext是Hero hero,而Hero的部分結構以下:
public class Hero { private int id; private string name; //。。。 private Dictionary<string, Item> itemList = new Dictionary<string, Item>();
主手武器的圖片,若是用code behind方式寫,對應代碼中的hero.ItemList[「mainhand」].ItemImage。XAML方式則對應爲:"{Binding ItemList[mainhand].ItemImage}" 。注意mainhand屬性在xaml中沒有了雙引號。
<Image Canvas.Left="254" Canvas.Top="38" Source="{Binding SkillList[1].SkillImage}" Stretch="None" Tap="Skill1_Tap"></Image>
這是Skill中的鼠標右鍵技能,大菠蘿目前一共有2個鼠標技能,4個Action技能,4個被動技能(資料片以前是3個),代碼中簡單的用SkillList包含了這10個技能。因此對於鼠標右鍵技能,綁定的Xaml就變成了"{Binding SkillList[1].SkillImage}" ,同理,對於第一個被動技能,則對應的是="{Binding SkillList[6].SkillImage}"
D3中的last updated是Unix時間,是一個ulong類型的值,轉換爲DateTime的代碼以下:
DateTime unix = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); DateTime last = unix.AddSeconds(lastUpdated);
爲了提升效率,對於裝備的圖片,代碼中進行了緩存,保存在該應用的IsolatedStorage目錄下。D3中的tooltip名字都很長,Windows系統中,路徑+文件名長度不能超過260個字節。因此簡單的作法,是對文件名作了一個Hash,來做爲緩存文件名稱。(固然,會有偶爾的衝突,這個代碼沒有作處理)
localfile = Math.Abs(localfile.GetHashCode()).ToString();//localfile就是本地緩存的文件名。
string free = String.Empty; long freeSize=IsolatedStorageFile.GetUserStoreForApplication().AvailableFreeSpace; if (freeSize >> 30 >= 1) free = String.Format("{0:N0}GB", (freeSize >> 30)); else if (freeSize >> 20 >= 1) free = String.Format("{0:N0}MB", (freeSize >> 20)); else if (freeSize >> 10 >= 1) free = String.Format("{0:N0}KB", (freeSize >> 10)); else free = String.Format("{0:N0}", freeSize);
public BitmapImage BackGround { get { return new BitmapImage(new Uri("/assets/background/" + this._class.Replace("-", "").ToLower() + this.male + "_background.jpg", UriKind.Relative)); } }
注意Uri的路徑寫法。
這是優化過的利用內置WebBrowser展現的我左手華戒的tooltip信息。若是直接用WebBrowser展現,該html會很是小,基本不可讀。
對於這個問題,能夠經過設置viewport來解決。官方頗有價值的一篇文章,請戳這裏:http://blogs.msdn.com/b/iemobile/archive/2011/01/21/managing-the-browser-viewport-in-windows-phone-7.aspx
放代碼以下:
StringBuilder sb = new StringBuilder(); sb.AppendLine("<html>"); sb.AppendLine("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en-us\">"); sb.AppendLine("<head xmlns:og=\"http://ogp.me/ns#\" xmlns:fb=\"http://ogp.me/ns/fb#\">"); sb.AppendLine("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\" />");//這行很重要 sb.AppendLine("<meta name=\"viewport\" content=\"width=370,minimum-scale=1\" />");//這行也很重要 sb.AppendLine("</head>"); sb.AppendLine("<body style=\"background-color:black\">"); sb.AppendLine(lines); //這就是D3返回給個人華戒的html描述信息 sb.AppendLine("</body>"); sb.AppendLine("</html>");
每一個英雄有14個裝備,每一個裝備的信息都要單獨獲取對應的圖片及tooltip。若是採用await GetItemByKey的方式,則14個裝備的圖片所有讀完,讀取時間至少在8秒之上。
利用Task的並行處理方式,咱們的處理效率則大大提升了。
list.Add("head", await GetItemByKey(person, "head")); list.Add("torso", await GetItemByKey(person, "torso")); list.Add("feet", await GetItemByKey(person, "feet")); list.Add("hands", await GetItemByKey(person, "hands")); list.Add("shoulders", await GetItemByKey(person, "shoulders")); list.Add("legs", await GetItemByKey(person, "legs")); list.Add("bracers", await GetItemByKey(person, "bracers")); list.Add("mainhand", await GetItemByKey(person, "mainHand")); list.Add("offhand", await GetItemByKey(person, "offHand")); list.Add("waist", await GetItemByKey(person, "waist")); list.Add("rightfinger", await GetItemByKey(person, "rightFinger")); list.Add("leftfinger", await GetItemByKey(person, "leftFinger")); list.Add("neck", await GetItemByKey(person, "neck")); list.Add("special", await GetItemByKey(person, "special"));
Task<Item> head = GetItemByKey(person, "head"); Task<Item> torso = GetItemByKey(person, "torso"); Task<Item> feet = GetItemByKey(person, "feet"); Task<Item> hands = GetItemByKey(person, "hands"); Task<Item> shoulders = GetItemByKey(person, "shoulders"); Task<Item> legs = GetItemByKey(person, "legs"); Task<Item> bracers = GetItemByKey(person, "bracers"); Task<Item> mainhand = GetItemByKey(person, "mainHand"); Task<Item> offhand = GetItemByKey(person, "offHand"); Task<Item> waist = GetItemByKey(person, "waist"); Task<Item> rightfinger = GetItemByKey(person, "rightFinger"); Task<Item> leftfinger = GetItemByKey(person, "leftFinger"); Task<Item> neck = GetItemByKey(person, "neck"); Task<Item> special = GetItemByKey(person, "special");
//上面代碼會馬上返回,只是定義了task而已。
await Task.WhenAll(head, torso, feet, hands, shoulders, legs, bracers, mainhand, offhand, waist, rightfinger, leftfinger, neck, special);
//這行代碼會並行執行這14個任務,等待全部信息完成。
list.Add("head", head.Result); list.Add("torso", torso.Result); list.Add("feet", feet.Result); list.Add("hands", hands.Result); list.Add("shoulders", shoulders.Result); list.Add("legs", legs.Result); list.Add("bracers", bracers.Result); list.Add("mainhand", mainhand.Result); list.Add("offhand", offhand.Result); list.Add("waist", waist.Result); list.Add("rightfinger", rightfinger.Result); list.Add("leftfinger", leftfinger.Result); list.Add("neck", neck.Result); list.Add("special", special.Result);
//14個任務的結果加入到list中。
private async Task<List<Skill>> GetSkillList(dynamic skills) { List<Skill> skillList = new List<Skill>(); foreach (var skill in skills) { if (skill.ToString()!="{}")//skill不是null,若是不存在,則對應{}
若是應用中用了WebBrowser,則須要指定相關權限。具體位置在:project-Properties-WMAppManifest.xml-Capabilities中,要check上ID_CAP_WEBBROWSERCOMPONENT
對於SL8.1版本的WP應用,Package.appxmanifest文件的內容,要作修改。我這個程序是從8.0升級上來的,因此仍是SL內核的版本,若是是一個新建的8.1WP應用,則無需作下面的修改。
http://blogs.msdn.com/b/thunbrynt/archive/2014/03/31/windows-phone-8-1-for-developers-overview.aspx