开发WP版本的大菠萝英雄榜
前言
想当年Team有无数人在玩大菠萝,我被忽悠进来做肉盾,选了蛮子,从1.0开始,经历了103、105、108、2.0、2.1。这个游戏对我最大的帮助是学习了不同的技术,比如XAML、比如xcode开发、比如WP的开发。
这篇文章不会step by step的介绍如何从0开始做WP开发,我会重点记录开发过程中要注意的坑,以及一些发布上架时的注意事项。
文中大部分内容对于熟悉XAML的人来讲,可能过于简单。放在这里,希望对初学者有个帮助,尤其是如我这样做winform开发的人。
先上几张图,






官方API
玻璃渣现在有两套API在并行运行,官方文档老版本的地址:https://github.com/blizzard/d3-api-docs,新版本的地址:https://dev.battle.net/io-docs。
两者的区别是,前者不包含诸如坚韧、圣教军等资料片中出现的内容,当然也不包括天梯、附魔等内容。后者不包含每个装备的item tooltip html。同时,后者必须要注册一个开发者账号(免费的)。
XAML绑定
Appbar的写法
<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对应的是图标按钮。前者无对应图标,如果是英文,则全部小写字母;后者可以指定是否只显示图标,或者同时显示图标与文字。
画线
<Line X2="300" Stroke="White" Height="1" StrokeThickness="3"></Line>
这段XAML画一条白色的线,注意颜色及线宽都是用Stroke***属性指定的。
指定格式绑定数字
<TextBlock HorizontalAlignment="Right" Text="{Binding Toughness, Converter={StaticResource IntConverter}}">Toughness</TextBlock>
这个文本框绑定资料片中英雄的坚韧属性,如果想按照千分位(或者你自己别的格式显示),则再指定Converter的class信息。
如,千分位的Convert代码如下:
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中没有了双引号。
属性的嵌套绑定2
<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}"
代码相关
Unix时间的转换
D3中的last updated是Unix时间,是一个ulong类型的值,转换为DateTime的代码如下:
DateTime unix = new DateTime(, , , , , , 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 >> >= ) free = String.Format("{0:N0}GB", (freeSize >> ));
else if (freeSize >> >= ) free = String.Format("{0:N0}MB", (freeSize >> ));
else if (freeSize >> >= ) free = String.Format("{0:N0}KB", (freeSize >> ));
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的路径写法。
展示适配WP屏幕的HTML信息

这是优化过的利用内置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中。
判断Json片段是否为空
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的权限
如果应用中用了WebBrowser,则需要指定相关权限。具体位置在:project-Properties-WMAppManifest.xml-Capabilities中,要check上ID_CAP_WEBBROWSERCOMPONENT
SL8.1版本的发布
对于SL8.1版本的WP应用,Package.appxmanifest文件的内容,要做修改。我这个程序是从8.0升级上来的,所以还是SL内核的版本,如果是一个新建的8.1WP应用,则无需做下面的修改。
- <publisherDiaplsyName>与开发商名字一致
- <Identity>下面的Name要与你在dev center中预留的名字一致
- <Publisher>与dev center中的开发商GUID一致
Deploy error: Package could not be registered
8.1的系列官方blog
http://blogs.msdn.com/b/thunbrynt/archive/2014/03/31/windows-phone-8-1-for-developers-overview.aspx
开发WP版本的大菠萝英雄榜的更多相关文章
- 干货100+ 最超全的web开发工具和资源大集合
干货100+ 最超全的web开发工具和资源大集合 作为Web开发者,这是好的时代,也是坏的时代.Web开发技术也在不断变化.虽然很令人兴奋,但是这也意味着Web开发人员需要要积极主动的学习新技术和 ...
- 人们对Python在企业级开发中的10大误解
From : 人们对Python在企业级开发中的10大误解 在PayPal的编程文化中存在着大量的语言多元化.除了长期流行的C++和Java,越来越多的团队选择JavaScript和Scala,Bra ...
- 崔用志-微信开发-java版本
崔用志-微信开发-java版本 今天看到一些关于微信开发的知识蛮好的博客,分享给大家,希望对大家有帮助. 微信开发准备(一)--Maven仓库管理新建WEB项目 微信开发准备(二)--springmv ...
- Arduino可穿戴开发入门教程(大学霸内部资料)
Arduino可穿戴开发入门教程(大学霸内部资料) 试读下载地址:链接:http://pan.baidu.com/s/1mg9To28 密码:z5v8 介绍:Arduino可穿戴开发入门教程(大学霸内 ...
- PHP Extension开发(Zephir版本)
上篇介绍了C语言开发PHP扩展的方法, 现在介绍使用Zephir开发扩展的方法. 关于Zephir需要简单介绍一下: Zephir 是为PHP开发人员提供的能够编写可编译/静态类型的高级语言.是优秀的 ...
- ios开发数据库版本迁移手动更新迭代和自动更新迭代艺术(二)
由于大家都热衷于对ios开发数据库版本迁移手动更新迭代和自动更新迭代艺术(一)的浏览下面我分享下我的源文件git仓库: 用法(这边我是对缓存的一些操作不需要可以省去):https://github.c ...
- 聚焦“云开发圆桌论坛”,大前端Serverless大佬们释放了这些讯号!
4月14日,由云加社区举办的TVP&腾讯云技术交流日云开发专场,暨"腾讯云-云开发圆桌论坛"在北京.深圳两地同步举行. 当天下午,一场主题为"基于大前端和node ...
- DDD实战进阶第一波(一):开发一般业务的大健康行业直销系统(概述)
本系列文章 DDD实战进阶第一波(一):开发一般业务的大健康行业直销系统(概述) DDD实战进阶第一波(二):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架一) 近年来,关于如何开发基于 ...
- iOS 开发之版本上线更新流程
iOS 开发之版本上线更新流程 把自己app上线的流程记录下来,希望能够让自己加深印象,也能帮助到一些人便是极好的! 证书和描述文件的配置就不写了,直接配置工程吧. 大致把我自己上线的流程写一下: ...
随机推荐
- Java 文档注释
Java只是三种注释方式.前两种分别是// 和/* */,第三种被称作说明注释,它以/** 开始,以 */结束. 说明注释允许你在程序中嵌入关于程序的信息.你可以使用javadoc工具软件来生成信息, ...
- 今天说一下where 中 exists 和 in 里面的一些区别
in 和 exists 已经成为我们日常查询时候的常客了.很多时候他们2个都是可以互通实现的,但是,无论兄弟怎么亲,还是会有那么一些差别的. 先搞个测试表 )) ),Col2 )) INSERT IN ...
- msysGit管理GitHub代码
msysGit管理GitHub代码 代码的管理,在日常开发中是很重要的环节,程序员的修炼三部曲——版本控制,单元测试,项目自动化. 本篇就简单的说说通过msysGit来管理GitHub中的代码,实 ...
- 不要轻易使用linq代替sql
使用Entityframework+Reposity模式 写出的代码执行效率极低. Linq代码: var querySql = rel_project_personservice.GetItems( ...
- MAC中设置java环境变量和MAVEN
借助于/usr/libexec/java_home进行配置 在~/.bash_profile 或者/.bash中添加(这里添加1.7版本) #JAVA_HOME export JAVA_HOME=$( ...
- 周一干不干活-PHP+MySQLi
hi 本来是雄心壮志的要干活的,哪知天有不测,早上大阴天起不来,中午又回寝室折腾衣服(做女工啊,牛不牛)没睡午觉,这样的迷糊状态,怎么科研,写这个好了. 1.PHP的OOP编程 4.7 多态 --定义 ...
- 给深度学习入门者的Python快速教程 - 基础篇
实在搞不定博客园的排版,排版更佳的版本在: https://zhuanlan.zhihu.com/p/24162430 Life is short, you need Python 人生苦短,我用Py ...
- NOIP水题合集[3/未完待续]
NOIP2008pj传球游戏 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球, ...
- AC日记——删除单词后缀 openjudge 1.7 20
20:删除单词后缀 总时间限制: 1000ms 内存限制: 65536kB 描述 给定一个单词,如果该单词以er.ly或者ing后缀结尾, 则删除该后缀(题目保证删除后缀后的单词长度不为0), 否 ...
- Permutation test 置换检验
来源:Public Library of Bioinformatics 显著性检验通常可以告诉我们一个观测值是否是有效的,例如检测两组样本均值差异的假设检验可以告诉我们这两组样本的均值是否相等(或者那 ...