开发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(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的路径写法。

展示适配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=\"");
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

官方论坛上有这个解答:https://social.msdn.microsoft.com/Forums/en-US/da89f2ee-03b6-43ed-aa21-97ef091798c9/deploy-error-package-could-not-be-registered?forum=WindowsPhonePreviewSDK

8.1的系列官方blog

http://blogs.msdn.com/b/thunbrynt/archive/2014/03/31/windows-phone-8-1-for-developers-overview.aspx

FQQ

时间: 2024-10-10 17:53:51

开发WP版本的大菠萝英雄榜的相关文章

Linux开发环境必备十大开发工具

原文链接Linux是一个优秀的开发环境,但是如果没有好的开发工具作为武器,这个环境给你带来的好处就会大打折扣.幸运的是,有很多好用的Linux和开源开发工具供你选择,如果你是一个新手,你可能不知道有哪些工具可用.本文将介绍其中十个杰出的开源开发工具,它们将帮助你提升自己的开发效率. 1.Bluefish Bluefish是进行Web开发时最受欢迎的IDE之一.它能够处理编程和标记语言,但是该工具的重点用途在于创建动态和交互式网站.和许多 Linux应用程序一样,Bluefish是一个轻量级工具,

Android开发——web浏览器开发(1) 版本1.0

1,建立一个新的项目 webdemo 2,layout下activity_main设计界面(1)待优化 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layo

android5.0开发必备版本和JDK环境配置

android5.0开发必备版本: JDK-1.8-x64; NDK-10-x64; ADT-5.0&4.0-x64; 谷歌代理: https://wen.lu/?gfe_rd=cr&ei=Ir7YU5XsOK3J8ge_24GgBQ&gws_rd=cr 也可用FQ软件:goagent,或FQ浏览器 goagent: https://github.com/goagent/goagent 配置地址:http://www.woshipm.com/it/13644.html JDK配置(

PHP Extension开发(Zephir版本)

上篇介绍了C语言开发PHP扩展的方法, 现在介绍使用Zephir开发扩展的方法. 关于Zephir需要简单介绍一下: Zephir 是为PHP开发人员提供的能够编写可编译/静态类型的高级语言.是优秀的Phalcon团队为开发第二版本框架所编写的新兴语言,其语法优雅,开发扩展非常方便,执行效率上据说是与C不分上下, 他的编译流程如下:Zephir -> C -> bin. Zephir的目的是创建面向对象库或者框架, 所以它与Clang扩展不同, 不能编写非OOP的模块. 想了解更可以请访问官网

【微信公众平台开发】微信幸运大转盘

需要js插件(下载包地址:http://download.csdn.net/detail/wyz365889/7798255): jquery jQueryRotate.2.2.js jquery.easing.min.js 前端显示代码: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name=

Arduino可穿戴开发入门教程(大学霸内部资料)

Arduino可穿戴开发入门教程(大学霸内部资料) 试读下载地址:链接:http://pan.baidu.com/s/1mg9To28 密码:z5v8 介绍:Arduino可穿戴开发入门教程(大学霸内部资料)为国内第一本可穿戴技术实施教程.本教程以最流行的开源硬件Arduino讲解可穿戴产品的构建方法.全教程覆盖Arduino Lily硬件.软件开发和项目构建等内容.最后,还讲解三个项目:番茄闹钟.二进制时钟.P#OV手*&环. 目  录 第1章  LilyPad Arduino概览 1 1.1

Java软件开发工程师市场需求大不大

Java编程语言是一种简单的,面向对象的,分布式的,解释型的,健壮安全的,结构中立的,可移植的,性能优异.多线程的动态语言.为什么Java开发工程师的待遇一直那么高呢? Java行业市场需求存在巨大的缺口 这几年中国在移动互联网这块发展非常迅猛,各种创业公司.小团队如雨后春笋般冒出来,对Java开发的需要变大.但存在人才发展跟不上市场的需求的现状,相对应的给优秀Java人才开出的薪资待遇随之水涨船高,为此很多大学生看中了这一前景,纷纷加入了动力节点Java培训机构,接受专业的培训,与企业零距离对

HealthKit开发快速入门教程大学霸内部教程

HealthKit开发快速入门教程大学霸内部教程 国内第一本HealthKit专向教程.本教程详细讲解iOS中,如何使用HealthKit框架开发健康应用.最后,本教程结合HealthKit和苹果手表iWatch实现一个健身应用--立卧撑拍拍器. 试读下载地址:http://pan.baidu.com/s/1o6iLO2A 目  录 第1章  HealthKit开发概述- 1 1.1  HealthKit简介- 1 1.1.1  HealthKit特点- 1 1.1.2  HealthKit经典

Swift游戏开发实战教程(大学霸内部资料)

Swift游戏开发实战教程(大学霸内部资料) 试读下载地址:http://pan.baidu.com/s/1sj7DvQH 介绍:本教程是国内第一本Swift游戏开发专向资料. 本教程详细讲解记忆配对.太空侵略者.Simon记忆.迷你高尔夫.银河大战五个游戏的开发.在项目讲解同时,还着详细介绍了图形绘制.游戏引擎.音频引擎.用户交互.传感器等专向技术.最后,教程讲解苹果专用游戏框架Sprit Kit的使用.为了帮助读者充分了解实际开发,教程还详细讲解游戏开发的必备知识,如帐号绑定.发布游戏等内容