怎么使三国策8官网战斗画面的上面菜单消失

《三国策》物品锁功能 让背包更安全_网络游戏_新浪游戏_新浪网
《三国策》物品锁功能 让背包更安全
  账号被盗一直是网络游戏运营商和玩家最深恶痛绝的问题之一,我们为解决账号被盗问题绞尽脑汁,竭尽全力!作为《三国策》运营商的我们,为了能够更好的使玩家的账号得到保护,我们已为大家推出物品上锁保护功能。具体介绍如下:
三国策画面
  第一次设置密码:
  1. 游戏中点击【个人】按钮中会有【物品密码锁】按钮
  2. 点击【物品密码锁】界面,进行设置密码、密码的提示问题及答案
  3. 密码的提示问题可用下拉菜单选择;请详细记录好密码的提示问题以及答案避免忘记。
  4. 物品锁功能上线后账号首次登录游戏,初始设置的物品锁密码为系统默认密码000000,没有提示问题及答案。建议玩家立即去设置物品锁密码及提示问题答案。
物品栏密码重置
  如果您需要更改密码:
  1. 点击游戏界面下方【个人】-【物品密码锁】界面下输入新的密码以及正确的密码提示答案点击确定方能正确设置成功新的物品锁密码。
  2. 为了保证账户的安全性,当您退出跨服的时候需要进行其它操作也必须要再次输入账户保护密码才能进行其它的操作。
  3. 如果物品栏密码锁设定为系统默认密码000000,在玩家登入游戏,退出游戏以及从跨服中返回社区都不会弹出输入物品锁密码提示。
  声明:新浪网游戏频道登载此文出于传递信息之目的,绝不意味着新浪公司赞同其观点或证实其描述。
关于CGWR:  (China Game Weight Rank)是由新浪游戏推出的目前国内最全面、最专业、最公正的网络游戏评测排行榜,力图为中国游戏玩家打造最值得信赖的新网游推荐平台。
  新浪中国网络游戏排行榜是以由新浪游戏专业评测员组成的评测团队为核心,以游戏的画质、类型、风格、题材等游戏特性为依据,对中国(大陆港澳台)、欧美、日韩等地区正在进行测试或正式运营的新网游产品进行评测并打分后产生的权威游戏排行榜。新浪中国网络游戏排行榜将网络游戏从六大项、二十八个小分项与同类游戏进行横向比较,再将该游戏与自身的不同版本进行纵向对比后,由评测中心根据加权平均数得出最后的游戏分数,并以游戏测试及上线时间点为分组,根据每款游戏的CGWS分数在每个季度发布排行榜榜单,实现了排行榜的透明化和实时化,帮助玩家准确、迅速地找到心目中的理想游戏。  评天下游戏、测产品深浅―新浪中国网络游戏排行榜CGWR! 
电话:010-当前访客身份:游客 [
:用系统的mediarecorder是比较好的方法来进行编程...
:引用来自“DDPush”的评论试试开源的DDPush任意门...
:谢谢你的文章。
:写的非常好,虽然我是初学者还不能完全理解您所说...
:如果是对语音识别率有较高要求(尤其是中文语音)...
:/kbengine/kbengine_unity3d_...
:引用来自“hokim”的评论 引用来自“sunlimiter”...
:我的遇到了一些问题 Error inflating class andr...
:不错,找这个内容找了挺久的
今日访问:229
昨日访问:246
本周访问:683
本月访问:683
所有访问:503883
列表模式: |
WPF 基础到企业应用系列索引
WPF 基础到企业应用系列从WPF的起源、背景、历史、现状讲起,然后逐渐过渡到基础、企业应用以及经验总结等。整个系列计划三十篇左右,每一篇都会认真完成,怀着宁缺毋滥的精神,争取能给读者带来帮助的同时也能提高自己,更进一步希望能以文会友,共同提高!诚然,由于WPF整个系列是自己的一些粗浅心得和微薄经验,所以不会像写书那么面面俱到,如果有不足或者错误之处也请大家见谅。
&&&&&&&&&&&&
& 9. WPF 基础到企业应用系列9——深入剖析WPF事件机制 (核心篇)&&&&&
&10. WPF 基础到企业应用系列10——WPF事件机制之“刨根问底”
&11. WPF 基础到企业应用系列11——深入剖析WPF命令机制 (核心篇)&&
&12. WPF 基础到企业应用系列12——WPF命令之“庖丁解牛”
&13. WPF 基础到企业应用系列13——WPF Binding全接触 (核心篇)&&&
&14. WPF 基础到企业应用系列14——WPF Binding之“面面俱到”
& 1. 资源、样式、模板
& 2. 尺寸缩放、定位与变换元素
& 3. WPF控件分类介绍与使用技巧
& 4. 用户控件和自定义控件开发
& 5. 多语言、皮肤和主题
& 6. 2D图形
& 7. 3D图形
& 8. 动画(几种动画的应用)
& 9. 音频、视频、语音
& 10. 文档、打印、报表
& 1. Win32、Windows Form以及ActiveX之间的互用性
& 2. 构建并部署应用程序(ClickOnce部署、微软setup /InstallShield+自动更新组件)
& 3. MVC、MVP、MVVM全解析
& 4. WPF的模式讲解及实例(MVC Demo)
& 5. WPF的模式讲解及实例(MVP Demo)
& 6. WPF的模式讲解及实例(MVVM Demo)
& 7. 性能优化(WPF项目的瓶颈)
& 8.一个完整WPF项目(普通架构版)
& 9. 一个完整WPF项目(MVVM架构版)
& 10. WPF 4.0新功能
最后 会尽心尽力写好这个系列,同时由于是自己对这些技术的使用总结和心得体会,错误之处在所难免,怀着技术交流的心态,在和发表出来,所以希望大家能够多多指点,这样在使一部分人受益的同时也能纠正我的错误观点,以便和各位共同提高,后续文章敬请关注!原文链接:
发布于 3年前,
阅读(22) | 评论(0) |
投票(0) | 收藏(0)
WPF企业内训全程实录由于文章比较长,所以一共拆分成了三篇,上篇主要讲了基础,中篇主要讲解开发模式、团队协作及应用框架,起着承上启下的作用,主要讲解开发模式、团队协作及应用框架。这篇作为该实录的下篇——终结篇,起着总结的作用,主要讲解其他技术的引用、WPF项目及性能优化、部署与更新等议题。
其实如果大家仔细看目录,可以发现我安排的顺序是首先讲解最基本的概念和基础内容、然后过渡到开发模式及框架、最后结合其他技术和项目实际运用,这也是学习并应用一门技术最好的流程。上篇实际上主要有两个侧重点:一则就是理清脉络——历史渊源、概念引入及基本阐述;二则是讲解WPFBasic——主要细究WPF的每个知识点,基本涵盖了WPF的方方面面;如果大家感兴趣,可以下载代码并进行仔细研究,如果有不懂的地方也可以参考我写的,这里受篇幅限制,就不详细重复论述。中篇主要围绕WPF开发模式、WPF团队协作和MVVM框架三个议题进行阐述,侧重于为什么要引入MVC/MVP/MVVM模式、从根本上说这些模式是为了解决什么问题、针对不同的开发模式,团队协作会有哪些具体的改变、了解并使用常用的开发框架以及追根索源探究并实现自己的开发框架。下篇则主要总结前面所讲的内容,同时介绍其他技术引入、WPF项目及性能优化与部署与自动更新等概念,其目的在于项目具体应用层次的归纳和总结。
& 2.本文提纲
& 3.简要介绍
& 4.WPF介绍
& 5.WPF基础
& 6.WPF工具
& 7.WPF开发模式
& 8.WPF团队协作
& 9.了解并使用MVVM框架
& 10.自己开发MVVM框架
& 11.其他技术引入
& 12.WPF项目及性能优化
& 13.部署与自动更新
& 15.详细技术索引
十一. 其他技术引入
通过WPF 基础到企业应用和前面两篇文章,我们基本讲解了WPF的基础知识和框架相关细节,可以用以下这幅图进行简要概括:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 图1
那么下面我们就来探讨一下WPF和其他技术之间的衔接问题。我们之前做项目都有一个基本流程,大致包括以下几个方面:
1. 基础开发平台与工具:在开发一个中、大型项目之前,我们一般都会有技术选型的过程,比如选择Linux + Apache + PHP + MySQL或者Linux + Apache + Java (WebSphere) + Oracle再或者我们最熟悉的Windows Server
+ IIS + C#/ASP.NET + SQL Server,当然这些操作系统、WEB服务器、开发语言和数据库在一定条件下可以任意搭配,比如你想用FreeBSD操作系统,你想用Ruby或者Python语言,你想用DB2或者其他数据库等。决定了开发平台和语言之后,就需要有定制的开发工具,比如Java你可能需要Eclipse或者MyEclipse插件,Net你需要强大的Visual Studio或者MONO环境下使用SharpDevelop,PHP你可能需要强大的Zend。简而言之,不管使用什么开发平台,都需要对应的开发套件与开发工具作为辅助。当然我们今天谈的是WPF项目的开发,所以必然我们会首先选择Windows Server
+ IIS + C#/ASP.NET + SQL Server这种搭配,也有人会说可以考虑MONO下的WPF开发和部署,不过很遗憾,MONO下针对WPF并没有完全进行实现。
2. 基础框架及资源:这里的基础框架是指有没有现成的数据访问框架、通用权限框架、异常和日志处理框架、IOC框架、AOP框架、简单的CMS管理框架、Office文档及PDF交互、报表及打印功能等,因为有了这些以后,开发项目就简单了许多,我们只需要关注具体的业务处理就行,这样可以使项目更加高效且稳定的完成。
3. 逻辑架构:逻辑架构往往决定了你如何划分模块以及如何来分层,这个要根据项目的具体情况而定,比如项目的大小、项目模块的多少以及开发方式、开发团队等。往往在这一阶段决定项目的整体架构(三层及多层架构、是否有必要搭建ESB与SOA等)。
4. 物理搭建:之前在做WEB应用的时候,会非常重视物理结构及环境的搭建,因为往往它在项目伸缩性、灵活性以及负载方面起着至关重要的作用,其实在决定逻辑架构的时候也必须要考虑到物理架构,我们这里所说的物理架构就是指整个系统或者多个系统在物理环境上的一个部署情况,比如Web Server集群、App Server集群、文件服务器集群、图片服务器集群、流媒体服务器集群、全文检索服务器集群、缓存服务器集群、负载均衡服务器、数据库主从、读写服务器集群等的部署情况。做简单的WPF管理系统也许并不用考虑这么多,如果要做大型的WPF播放器以及大型的WPF应用,这些都得经过仔细的斟酌才行。
5. 框架的选择:这个地方是选择整个应用程序的框架,当然选择的前提还必须参考前面的逻辑与物理结构。具体框架包括数据底层处理框架、公共基础框架以及我们前面所提及的诸如MVC/MVP/MVVM模式等。
6. 其他处理:面向对象设计与实现、面向方面思想、权限系统设计、缓存体系设计、异常及日志框架设计、分布式及负载均衡等都是我们需要考虑的重点和要点。最后要特别注意团队及项目规范、项目整体开发流程、版本与配置管理、项目开发注意细节等问题。
十二. WPF项目及性能优化
一,WPF项目
1)之前的项目架构
在讲WPF项目架构与基础结构之前,我们先来看一下之前搭建的WEB应用程序:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 图2及图3&
上面的两幅图具体概念如下:
01,User Interface即UI层:该层作为数据输入和展示的界面,是与用户交互的有效途径,所以它起着至关重要的作用。往往给人第一印象的就是UI层,在设计的时候也要根据不同的技术或者不同的要求进行斟酌。通常可以把UI分为B/S UI、C/S UI以及WEB服务。在这里就是我们的ASP.NET项目。
02,WebModelCommon:这层作为UI与领域逻辑的中间层,它的充当了桥梁、筛选、过滤和验证的作用。它主要包括两个工程,WebHelper主要提供给UI一些常用操作。WebLogic主要对UI与领域逻辑的数据进行转换、筛选、验证及过滤操作。
03,Business Logic:Domain Model (Data Model Layer)始终是应用程序的核心,必须投入大量精力,按照面向对象的分析和设计 (OOAD) 最佳做法进行设计同时按照OOP进行开发。
04,FrameWork:主要包括数据访问框架、通用权限框架、异常和日志处理框架、IOC框架、AOP框架等基础或常用功能。
05,SOA:这一层不是必须的,根据项目的具体情况进行取舍,如果业务比较复杂且交互项目繁多,那么SOA可以减轻我们的负担;如果业务比较单一且相对简单,就可以直接调用或者使用Web Service/Remoting/WCF作为通信框架即可。在实施SOA的过程中,可以自己使用WCF+WF搭建一个小型轻量级的SOA框架,也可以使用诸如Biztalk等软件。
06,Reference:这里主要包括第三方的框架和组件项目,把这些文件分门别类地集中放在此目录下。
07,Solution Items:项目的规范、流程、重要文件等。
08,Test:这里主要放置测试需要的一些信息,如测试版本、测试文档等。
09,Publish:这个文件夹主要放置发布的版本。
这个框架能解决大多数问题,但仍有不完善之处。
1)WPF或Silverlight架构
在MVVM模式中,你需要一个为View量身定制的model,那么这个model实际上就是上图ViewModel。ViewModel包含所有UI所需要的接口、属性和命令,这样只需要通过Binding使他们进行关联,就可以使二者之间达到松散耦合,所以这样一来,UI就可以由UI专业人员用 Design和Blend来实现(当然很多效果还是需要用传统的制图软件,所以我们都称这种想法叫理想状态),代码人员也可以专心写他的逻辑和业务代码,所以这样分工和协作变得更轻松、更愉快了。更漂亮的是View完全可以由(Unit/Automatic Test)所取代,所以单元测试也变得相对简单。这对于我们的开发人员和测试人员无疑是一个很好的解脱,同时也提高了系统的可测性、稳定性和维护性。数据绑定系统同时也提供了标准化的方式传输到视图的错误验证和输入验证(但是个人觉得不是很好用,所以我们在实际的项目当中会写一套自己的验证框架)。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 图4
那么根据上面这幅图,我们具体可以得出如下结论:
1,首先介绍的是UI层,该层作为数据输入和展示的界面,是与用户交互的有效途径,所以它起着至关重要的作用。往往给人第一印象的就是UI层,在设计的时候也要根据不同的技术或者不同的要求进行斟酌。通常可以把UI分为B/S UI、C/S UI以及WEB服务。
2,ViewModel作为用户界面和业务领域模型的中间层,它往往起着类似于桥梁的作用(UI和领域业务逻辑层之间的桥梁以及耦合的隔离者)。
3,Domain Model (Data Model Layer)始终是应用程序的核心,必须投入大量精力,按照面向对象的分析和设计 (OOAD) 最佳做法进行设计同时按照OOP进行开发。
4,Model、View 和 ViewModel 层之间实施严格的分离,也强调了它们之间是一种松散耦合的关系。
5,每一层或者每一个模块都有自己完整的单元测试,这样即提高了代码质量,同时也增强了稳定性和可维护性。
6,不要为了MVVM而MVVM,不要强调UI端不产生一句后台代码而把所有代码都扔进ViewModel,因为有的操作如果不参与逻辑流程,放在UI端处理会更好,这也符合UI和逻辑隔离的最终原则。
7,数据底层操作层可以随意的搭配,既可以使用传统的方式也可以用ORM的方式,这个根据团队或项目的具体情况作抉择。如传统的存储过程或者脚本、借助于企业库、IBATIS.NET、Nhibernate,Active Record,Entity framework,Linq To Sql,entity framework或者Custom ORM等。
8,Database做为最底层,它对应用程序起着最为关键的作用,项目没有数据就等于失去了最本质的东西,除非这个项目和数据没有太多关联,所以必须投入大量的时间和精力在这一层,这也是数据库库团队存在的必要。最典型的问题包括数据库优化、数据库拆分、分离、同步、数据挖掘以及数据库的备份与复原等。
前段时间本来要重构一个项目,但由于诸多原因,这个项目没有能够在整体架构上进行调整,这里也把项目整体结构图贴出来,供大家参考
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 图5及图6&
上面的两幅图具体概念如下:
01,UI:该层作为数据输入和展示的界面,是与用户交互的有效途径,所以它起着至关重要的作用。往往给人第一印象的就是UI层,在设计的时候也要根据不同的技术或者不同的要求进行斟酌。通常可以把UI分为B/S UI、C/S UI以及WEB服务。在这里就是我们的WPF项目。
02,ViewModel作为用户界面和业务领域模型的中间层,它往往起着类似于桥梁的作用(UI和领域业务逻辑层之间的桥梁以及耦合的隔离者),这里没有把它从UI里面独立出来,所以它放在UI或者独立出来均可。
03,LogicBusiness:Domain Model (Data Model Layer)始终是应用程序的核心,必须投入大量精力,按照面向对象的分析和设计 (OOAD) 最佳做法进行设计同时按照OOP进行开发。
04,Common:主要包括数据访问框架、通用权限框架、异常和日志处理框架、IOC框架、AOP框架等基础或常用功能。
05,SOA Service:这一层不是必须的,根据项目的具体情况进行取舍,如果业务比较复杂且繁多,那么SOA可以减轻我们的负担;如果业务比较单一且相对简单,就可以直接调用或者使用Web Service/Remoting/WCF作为通信框架即可。在实施SOA的过程中,可以自己使用WCF+WF搭建一个小型轻量级的SOA框架,也可以使用诸如Biztalk等软件。
06,DataAccess:数据库访问组件。
07,AddedDll:这里主要包括第三方的框架和组件项目,把这些文件分门别类地集中放在此目录下。
08,UnitTest:对每层及每个模块进行单元测试。
从上面WEB与WPF两个项目中可以看到具体的差别与联系:联系在于公共的东西都是不会变的;差别在于WEB与WPF都有各自的特点,所以在处理上也有一些细微的区别!
二,性能优化
关于性能优化,在任何项目都会有所涉及,使用WPF的项目也不例外(或者更甚)。那么针对WPF项目,我们如何来做好性能优化呢?其实这个问题比较大,因为往往某个细节的操作会影响到整个WPF应用程序的性能,所以在做项目的时候一般都会针对这些性能优化操作列一个表(详细说明性能优化点及注意事项)。WPF性能优化就像之前做WEB优化一样,都有一些“银弹”可供参考,WEB项目有Yahoo团队实践分享——网站性能优化的条黄金守则和业界的一些经验;WPF作为出道不久的技术,主要参考微软提供的性能优化注意事项以及自己的实践经验。本来是想罗列一些性能优化点,无奈由于时间仓促且怕罗列不全面或不正确,所以把它留在以后心情好的时候再续,不然就会起到不能帮助读者反而误导读者的效果。
十三. 部署与自动更新
一个优良的软件都会有自己完整的部署与自动更新流程,C/S应用程序尤其如此,所以如何解决客户端的部署与自动升级问题便是一个非常重要的问题。大家都知道ClickOnce 无疑是微软对Client/Server模式部署的最佳解决方案,但正是因为它的功能特别强大而且又要使用相当简单,所以在产品的封装上就特别严实,基本上就暴露了一些简单的操作接口,这样用户就无法做定制化的操作,所以我们下面主要探讨不使用ClickOnce的操作流程。
一,打包操作
关于打包操作,现在市面上有很多的打包工具与代码,但最为常用的要数Installshield和微软自带的打包工具软件,两者在这方面都有不俗的表现,前者强调打包的定制化以及多样性,后者强调易操作及快速性。如果你想要更多漂亮及定制化的操作,可以选择Installshield+脚本的方式;如果你想做一般的效果,那么微软自带的打包工具软件就特别适合;当然这也不是绝对的定律,只是一般情况下的选择,下面我们就主要来讲解微软自带的打包工具软件。
1) 创建安装和部署项目:
1,右键点击当前解决方案—&Add—&New Project,在弹出的窗口中选择Other Project Types—&Setup and Deployment—&Setup Project;然后输入项目的名字,点击“OK”按钮。新添加的安装和部署项目就会出现在解决方案列表中。
2) 添加项目输出及制作安装界面:
1,首先把你要安装的项目加进来,也就是加入到应用程序文件夹,由于VS SetUp设置比较简单,你只需要按照操作步骤一步一步设置即可。在完成应用程序文件夹之后设置开始菜单和用户桌面的快捷方式。
2,右键点击安装项目,选择View—&User Interface可以看到VS SetUp为我们提供的一些默认安装界面,当然你也可以创建、修改或者移除这些窗口,总之你可以定制化你的安装步骤和页面。
3) 注册表问题:
和前面的操作类似,对于注册表的设置也比较简单,右键点击安装项目,选择View-&Registry即可创建、修改及移除注册表键值。
4) 创建组件注册项目:
1,右击当前解决方案—&Add—&New Project,在弹出的窗口中选择 Visual C#—&Class Library;然后在下方文本框中输入Name,点击“OK”按钮。新添加的项目会出现在解决方案列表中。
2,右键点击该项目—&Add—&New Item,在弹出的窗口中选择Installer Class;在下方文本框中输入名字,点击“Add”按钮添加文件并关闭窗口。
3,选中刚添加的文件,按F7或者View Code转到代码页,在代码页面添加以下方法:
namespace RegsvrDll{
[RunInstaller(true)]
public partial class InstallerReg : Installer
public InstallerReg()
InitializeComponent();
public override void Install(System.Collections.IDictionary stateSaver)
base.Install(stateSaver);
protected override void OnAfterInstall(IDictionary savedState)
base.OnAfterInstall(savedState);
string LogicDir = Context.Parameters[&LogicDir&];
// Close the writer and underlying file.
// 注册CDO组件
// /s 关闭注册成功的提示窗口显示,/c退出cmd窗口
System.Diagnostics.Process.Start(&cmd&, @&/c regsvr32 & + @LogicDir + @&ComUtilities.dll /s&);
string path = @LogicDir + @&App.exe&;
using (RegistryKey regWrite = Registry.LocalMachine.CreateSubKey(&SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths&))
regWrite.SetValue(&App.exe&, path);
regWrite.Close();
protected override void OnBeforeInstall(IDictionary savedState)
base.OnBeforeInstall(savedState);
注意:需要加入using System.Configuration.I
5) 在安装和部署项目中添加要安装的项目和文件:
1, 添加项目:右击项目—&View—&File System,在出现的界面中,右击左列的Application Folder—&Add—&Project Output,在弹出的窗口中选择相应的Project,然后点击“OK”按钮。多个项目重复多次。在这里我们假设我们开发的项目为 MainProject,注册组件的项目名称为RegDll,那么我在弹出的窗口中先选择项目MainProject,点击“OK”后,我在重复添加项目 RegDll。
2,添加文件:右击项目—&View—&File System,在出现的界面中,右击左列的Application Folder—&Add—&File,在弹出的窗口中选择C:\WINDOWS\system32 \misexec.exe;
3,创 建快捷方式:在右列中选择Primary output from MainProject(Active),右击 选择Create Shortcut to Primary output from MainProject(Active),你可以按F2给新添加的快捷方式更名。右击msiexec.exe 选择 Create Shortcut to misexec.exe,你可以按F2将刚生成的快捷方式更名为“卸载”;
4,创建程序组:右击左列的User’s Programs Menu选择 Add—&Fold,你可以将新创建的文件夹更名,当软件安装完毕后它将出现在程序组中,然后将上一步创建的两个快捷方式拖到新创建的文件夹中。
5,实现“卸载”的功能:选中安装和部署项目,按F4,复制ProductCode的内容,然后选中“卸载”快捷方式,按F4,将Arguments 的内容更改为:/x 刚复制的ProductCode的内容。
6) 安装时注册组件问题:
右击安装和部署项目—&View—&Custom Actions,在出现的界面中右击左列的Install—&Add Custom Action,选择Application Folder中的Primary output from RegDll(Active)。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 图7
修改“主输出来自RegDll (活动)”的CustomActionData属性为 /LogicDir=&[TARGETDIR]\&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 图8
7) 自动检测当前系统中MDAC、.Net Framework版本、Windows Installer3.1是否满足版本要求,如果不满足则安装:
右击安装和部署项目选择属性,在弹出的窗口中点击按钮 “Prerequisites”。选中MDAC2.8、.Net Framework2.0、Windows Installer3.1;然后选中Download prerequisites from the same location as my application 单选按钮,点击“OK”,再点击“OK”。
8) 重新编译项目生成项目安装包,这个时候就可以把安装包Host在网上供用户下载。
二,自动更新
1),简要介绍
众所周知,对于一般的软件开发,在开始的时候都会有一个技术选型的阶段,最大的选型就是首先要确定是选择Client/Server模式还是 Browser/Server模式。综合而论:两者各有优劣,在很多方面都不能被对方互相取代,如在适用Internet、维护工作量等方面,B/S比C /S要强很多;但在运行速度、数据安全、人机交互等方面,B/S就远不如C/S那么强大。所以综上所述,凡是C/S的强项,便是B/S的弱项,反之亦然。由于今天讨论的是自动更新组件,所以接下来我们就往这方面细讲,既然C/S模式在运行速度、数据安全、人机交互有这么多的优点,尤其是客户端技术日益发展的今天,如何解决客户端的部署与自动升级问题便是一个非常重要的问题。
2),ClickOnce与自定义之间的权衡
在前面的摘要中我们简单介绍了自动更新功能的重要性,在这一小节里我们来谈一下为什么不使用微软给我们提供的自动更新组件ClickOnce,大家都知道ClickOnce给我们提供了很多功能:简单说来,ClickOnce 应用程序就是任何使用 ClickOnce 技术发布的 Windows 窗体或控制台应用程序。可以采用三种不同的方法发布 ClickOnce 应用程序:从网页发布、从网络文件共享发布或是从媒体(如 CD-ROM)发布。ClickOnce 应用程序既可以安装在最终用户的计算机上并在本地运行(即使当计算机脱机时也可以运行),也可以仅以联机模式运行,而不在最终用户的计算机上永久安装任何内容。ClickOnce 应用程序可以自行更新;这些应用程序可以在较新版本变为可用时检查较新版本,并自动替换所有更新的文件。开发人员可以指定更新行为;网络管理员也可以控制更新策略,如将更新标记为强制性的。最终用户或管理员还可以对更新进行回滚,使应用程序恢复到早期的版本。
从上面大家可以看出ClickOnce 无疑是微软对Client/Server模式部署的最佳解决方案,但正是因为它的功能特别强大而且又要使用相当简单,所以在产品的封装上就特别严实,基本上就暴露了一些简单的操作接口,这样就无形把一些定制化的操作拒之于门外,比如:
用户不能自己指定安装路径。
对自动更新流程不能做定制化的操作。
对自动更新的UI不能定制化的设计。
正因为这几个原因,所以很多企业都会做一些定制化的组件来实现自动更新的功能,基于此,我们这里也实现了一个非常简单的自动更新组件.
3),自定义更新操作流程
其实自动更新的原理很简单,分析起来无非就是简单的几步操作,当然实现方式也是大同小异,这里我们就选一种较简单的方式:
1.启动主程序,主程序里面调用升级程序,升级程序连接到IIS或者FTP。
2.升级程序获取服务器端XML配置文件中新版本程序的更新日期或版本号或文件大小。
3.升级程序获取原有客户端应用程序的最近一次更新日期或版本号或文件大小,然后两者进行比较;如果新版本日期&原有程序的最新日期,则提示用户是否升级;或如果新版本版本号&原有程序的版本号,则提示用户是否升级;再或如果新版本文件大小&原有程序的文件大小,则提示用户是否升级。本文主要采用一般的做法,就是通过版本号来进行对比。
4.如果用户选择升级,则获取下载文件列表;
5.在本地建立与远程IIS或者FTP相应的临时目录,然后下载到这个临时目录文件下;
6.删除旧的主程序,拷贝临时文件夹中的文件到相应的位置;
8.结束升级流程并重新启动主程序。&&
4),自动更新效果图
当我们运行主程序(WinForm或者WPF),如果服务器上有最新的版本,就会弹出如下页面进行提示并让用户选择是否更新。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 图9
当用户不需要更新时,可以选择Skip按钮跳过并继续主程序流程,反之则进入如下页面。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 图10
在下载的过程中,用户可以选择Cancel停止下载并重新回到主流程。
十四,总结
上篇主要讲解历史渊源、概念引入、基本阐述以及WPF的每个知识点。中篇主要主要围绕WPF开发模式、WPF团队协作和MVVM框架三个议题进行阐述。下篇将着重强调结合其他技术共同打造WPF项目、相关性能优化、以及部署与更新问题。另外如果有不懂的地方也可以参考之前写的,最后声明一下,由于圣殿骑士才识浅薄,所以以上观点只是个人的看法与心得,遗漏和错误之处也敬请海涵。怀着技术分享与交流的态度分享出来,希望各位多多指教!
十五,详细技术索引
原文链接:
发布于 3年前,
阅读(94) | 评论(0) |
投票(0) | 收藏(1)
圣殿骑士由于工作和项目需要,所以对一些技术进行了较为深入的研究,之前在整个公司做过一些技术专场的培训,由于每次时间较短且人员较多的关系,没能讲得很透彻。一直都想以文字的形式把这些培训细节写出来,但是发现进度确实很慢,所以先来几篇宏观的讲解,希望能起到“授人与鱼也授人以渔”的效果。今天我们就来分享一下WPF内训之旅,这篇文章以WPF培训为主线,中间贯穿了一些其他技术和使用心得。其他培训专题诸如“OO到设计模式”、“WCF基础到企业应用“Silverlight基础到企业应用及优化”随后也会奉上,热诚和大家互相学习,如果有讲得不妥之处,也希望大家能够多多指点!
二. 本文提纲
& 2.本文提纲
& 3.简要介绍
& 4.WPF介绍
& 5.WPF基础
& 6.WPF工具
& 7.WPF开发模式
& 8.WPF团队协作
& 9.了解并使用MVVM框架
& 10.自己开发MVVM框架
& 11.其他技术引入
& 12.WPF项目及性能优化
& 13.部署与更新
& 15.详细技术索引
三. 简要介绍
关于如何做好一个专题的培训,圣殿骑士也有一些自己的看法,我觉得如果想要一个培训起到良好的效果,得注意以下几个方面:
1,了解受众:首先要确定培训的受众,他们是直接的受益者,所以你必须得了解他们的知识背景,这样才能合理把要讲的知识插入到他们各自的知识树上去,否则效果就会大打折扣。
2,来龙去脉:不管讲什么技术,首先得介绍这门技术的历史渊源、来龙去脉、市场前景,因为只有介绍了这些,才会使受众仔细聆听且能够跟随你的思路往下走,这也是比较关键的一环。
3,把握联系:我们要讲的这门技术往往不可能单独存在,它或多或少和之前使用的技术有一些联系,所以在讲解过程中适当引入之前的技术会起到很好的效果,并且在项目中,它也不可能单独存在。
4,大道至简:必须从基础讲起,从一个”Hello World“讲起,因为只有用大众化的思维来阐述问题,才会引起大众的共鸣,这同时也体现了一些原则,比如大道至简、深入浅出、先易后难。之后就开始不断深入浅出的讲解各知识点细节,最好以理论+Demo的形式,这样收到的效果才会达到或超过预期。
5,工具使用:对于一门技术,或多或少都有适合它的工具,这些工具不仅能提高开发效率,同时也是更好深入学习该技术的一个前提,所以合理使用工具也是一个比较重要的方面。
6,真实项目:前面讲了来龙去脉,讲了基础知识以及与其他技术的区别和联系,同时也讲了开发工具,那么这个时候就需要引入最重要的关注点——如何把之前讲过的各个方面关联起来,让它们作用在真实项目当中,一般最容易接受的当属简单页面+CRUD操作。
下面这幅图是我在半年前写的一份PPT,因为公司要求用英文表述,所以写的很简约,这也怪圣殿骑士英文不好:-D,表达不像中文那样灵活自如,不过大家可以将就看一下大纲(PPT和代码在后面的文章中提供下载,暂时还没找到提供下载的地方):
因为上面的PPT基本涵盖了WPF的所有重要知识点,所以得为每一个知识点准备相关的Demo,只有这样才能把每个知识点完全讲透,否则只能起到云里雾里、不知所云的效果。如下便是与之配套的Demo截图:
上面的代码包中主要包括:
WPFBasic:主要讲解WPF的基础概念,涵盖了WPF的方方面面。
WPFPatterns:强调Presentation模式的重要性,主要包括MVC/MVP/MVV以及一些MVVM的框架。
WPFProject:具体项目中如何把握,如何引用之前的技术和经验。
WPFTools:一门技术都有与之相应的开发、管理、协助工具,WPF也不例外。
WPF.PPT:这里是一些简单的介绍,熟悉的可以略过。
这些Demo主要来源于两个方面,一是自己写了一些;二是改编了网络上的一些素材;如果大家仔细看,可以发现它涵盖了WPF的方方面面,并且对重点和难点也做了区别对待。
四. WPF介绍
1,概念引入
Windows APIWindows Presentation Foundation (WPF) 是新一代显示系统,用于生成能带给用户震撼视觉体验的 Windows 客户端应用程序。使用 WPF,您可以创建广泛的独立应用程序以及浏览器承载的应用程序。 WPF 的核心是一个与分辨率无关并且基于向量的呈现引擎(这样就可以保证图像和影像具有高清晰度),旨在利用现代图形硬件的优势。WPF 通过一整套应用程序开发功能扩展了这个核心,这些功能包括可扩展应用程序标记语言 (XAML)、控件、数据绑定、布局、二维和三维图形、动画、样式、模板、文档、媒体、文本和版式。WPF 最先包含在如下图的 Microsoft .NET Framework 3.0中,它使您能够生成融入了 .NET Framework 类库的其他元素的应用程序(因为WPF包含在.NET Framework 3.0 里面,所以我们这里不列出3.5和4.0的框架图)。
2,历史渊源
微软在1983年春季就宣布开始研究开发Windows,到现在已经有27年的历史,这27年来,微软官方主力推行的编程语言与API有四个主要阶段:
年:C搭配Windows API。当时的程序员是很少的,并且开发一个项目也比较的不容易。
年:这段时期C++搭配MFC库。在历史上MFC是最多人用的Windows编程方法。但此后MFC技术也逐渐退出了历史的舞台。
年:(C#、VB以及其他语言)+Windows Form框架。这段期间IT技术的焦点是在Web上,所以虽然大家都在用.NET,但真正的主角是ASP.NET,而不是Windows Forms。Windows Forms还没等熬出头,WPF就出现了。Windows Forms注定会是历史中“最少人使用的微软开发技术”。Windows Forms其实是不错的技术,在很多方面都做得挺不错,比如在UI上、图形编程上、开发效率上、稳定性上都做得很让人敬佩,但是我们最后看到的结果却是大家没有引起足够的重视,很多人更偏向于用Delphi和MFC,对Windows Forms却视而不见,所以造成的最后结果就是Windows Forms生不逢时。
2007~现在 :日,Windows Vista正式全球同步发布。它之所以能实现那么绚丽的效果,最关键的一点就是其内在也使用了Windows Presentation Foundation(WPF)类似的技术,所以带来的震撼视觉效果和用户体验使Vista的效果如此绚丽,虽然Vista在后来最终成为了一个败笔,但它为 Windows 7打下了坚实的继承。后台语言(C#、VB以及其他语言)+XAML构成的WPF。你可能觉得很奇怪,微软为何释出两个作用相似,却不同且不相容的.NET API。因为时代的改进,用户对视觉感受需求不断提高。因为WPF支持硬件加速、精确颜色、浮点坐标、动画实现、三维、视频感受等要求提高。而传统的 Winform 是到不到这些效果的。
3,技术更替
旧的事物迟早会退出历史舞台,新的生命会经过曲折的里程登上王座。从图像界面的出现那一刻起,用户界面(UI)就进入了一个特殊的历史时期。在随后几年里,出现了很多具有历史意义的界面风格。现在,经典的Windows窗口风格已经存在了10多年,即使是深受用户喜爱的Windows XP风格也已出现五年有余。无疑大家与我一样,期待着全新视觉界面的出现。另一方面,当今计算机处理芯片飞速发展,特别是显示芯片,显示卡几乎成为了一台微型的计算机。但是,其强大的处理能力却没有得到充分的应用。目前,显示卡GPU(Graphics Processing Unit)的处理能力大多只应用在游戏和多媒体领域。为了给用户提供最强的体验,满足不断提高的用户视觉需求,Windows Vista引入了全新的图形子系统——WPF。她能充分利用显示卡的处理能力提供给用户最绚的视觉效果。
在Windows Vista出现之前,Windows平台的图形系统主要有:GDI、GDI+、Direct3D。其中,GDI的应用领域最为广泛。GDI图形系统已经形成了很多年并且已经逐渐形成了自己的一套开发体系。它提供2D图形处理、文本处理,以及有限的图像处理功能。虽然在一些显示卡上支持部分的GDI加速,但是其效果与现在的Direct3D相比还是很弱小。GDI+开始出现是在2001年,它引入了2D图形的反走样、浮点数坐标、渐变以及单个象素的 Alpha支持。它几乎支持所有的常用图像格式。但是,GDI+没有任何加速功能(全部是用软件实现)。
4,核心框架
如右图,在Windows Vista和Windows 7中,GDI、GDI+和WPF并行存在。但是,WPF所有的操作都不依赖于GDI和GDI+,而是间接依赖于强大的Direct3D。右图中的标示为暗红色的是WPF的三大核心组件,其中milcore组件,它的职责是完成与Direct3D的交互。并且出于效率和安全考虑,milcore由非托管代码实现。WPF 中的所有显示是通过 DirectX 引擎完成的,可实现高效的硬件和软件呈现。WPF 还要求对内存和执行进行精确控制。milcore 中的组合引擎受性能影响关系大,需要放弃 CLR 的许多优点来提高性能。
WPF的两大核心组件PresentationFramework和PresentationCore都位于通用语言运行库(CLR)之上。那么就可以看出,WPF的大部分代码都是以托管形式存在的。这两大组件提供了WPF项目需要的函数库和功能库,由于是以托管的形式存在,所以也避免了我们直接操作底层和出现诸如内存泄露的可能性。
5,功能介绍
正如上面的这幅图,可以看出一共分成了五大块(Core Presentation、User Interface Services、Base Services、Document Servies和XPS Viewer):
Core Presentation:包含了所有的图形效果,如图形、2D图形、3D图形、文本、音频、视频和显示效果。同时还包括强大的动画效果,动画可以应用前面的所有元素。最下面的那个就是视觉基本元素。
User Interface Services:包含了Application Services(应用程序服务)、Deployment Services(部署服务)、Controls(控件库)、Layout(布局)和Data Binding(数据绑定).
Base Services:提供了XAML支持、Accessibility(提高开发效率)、Input&Events(输入和事件的支持)、Property System(属性系统)。
Document Servies和XPS Viewer则提供了基本的打印和表报服务,可以通过这些组件实现自定义的打印和显示效果。
基于上面的特性以及我们使用的情况可以总结出:
&&&&& 在输入方面:WPF支持键盘、鼠标、手写笔、触摸屏,蓝牙录入、视频扑捉等,所以基本没有任何限制,在和外部设备的交互上:有驱动、COM、Win32或通信协议支持的任何设备。打印和报表方面:可访问打印对话框、打印队列、打印窗体、控件以及很多可选操作,同时对报表也支持得很好。同时支持流文档和固定文档,对命令的支持以及对文件的无限制访问,最后尤其在动画、图形图像、3D、影像的支持相当好(其他技术是很难做到的),所以WPF除了在性能方面存在着缺陷以外,其他方面可以说是做得非常优秀,同时我们有信心相信微软会在这方面做得更好!
五. WPF基础及核心概念
1,基础概念
从2007年开始接触WPF/Silverlight以来,对学习和使用它们有自己的一些浅薄心得,所以首先让我们来看看WPF的各个基础概念:
Application、Window、Navigation、Dispatcher:&& 这里强调一个应用程序的基本组成部分,也就是说它是每一个项目都会遇到的概念!
框架结构及类继承结构:&& 没有一个宏观的认识作为灯塔,是一件很危险的事情,尤其在做深入研究的时候!
XAML基础:& 作为WPF的主打概念,它似乎起着不可估量的作用,这也是大家接触WPF的首要概念!
布局基础:&& 每一个应用程序,如果没有良好的布局,似乎是一个不可想象的事情,在WPF中提供了很多布局元素,同时也提供了很多扩展点!
WPF的逻辑树和视觉树:& 它很有作用,但也很头痛,很多错误不得不归功于它!
依赖属性、路由事件、Binding、命令:&& 核心中的核心,所以我们把它列为重点讲解对象,后面分开阐述!
资源、样式、模板:&& 在很多程度上,它吸取了之前WEB方面的优势,这三个功能在很大程度上提高了复用,同时也规范了项目!
尺寸缩放、定位与变换元素:&& 由于是矢量元素,所以在做各种图形图像操作的时候就比较如鱼得水!
WPF控件分类介绍与使用技巧: 微软的每一种UI相关的技术都会伴随强大的控件库,有了它们可以大大减轻开发的难度!
用户控件和自定义控件开发:&&& 和WinForm、ASP.NET一样,开发自定义控件也很简单且类似,这里强调控件的多种分类以及区别对待!
多语言、皮肤和主题:&& 开发一个稍微大型的应用程序都会遇到多语言、皮肤和主题,在WPF中做这些元素也非常简单!
2D图形: WPF创建和使用2D图形主要集中在3个重要的数据类型之上——Drawing,Visual,Shape,所以需要分别进行研究!
3D图形: WPF之所以能带来绚丽且强大的3D图形功能,这得归功于DirectX 技术,并且提供的接口也非常简单,这也使大量动画应用成为可能!
动画(几种动画的应用):动画无疑是WPF中最吸引人的特色之一,因为一想到动画大家可能都会提到Flash,WPF的确也使动画变得非常简单!
音频、视频、语音: 这里强调的影音相关的功能,由于直接使用DirectX,所以较之前的技术,WPF在显示效果和质量上可谓是质的飞跃!
文档、打印、报表: 强调企业使用的一般功能,在WPF中也得到了很好的实现,这也是大量管理应用程序使用WPF的前提!&
Win32、Windows Form以及ActiveX之间的互用性:这里强调与其他技术之间互用的兼容性,当然,在WPF中对这些技术提供了很好的支持!
部署及更新应用程序:和其他客户端技术一样,WPF的部署与自动更新也比较容易,除了传统的三种方法以外,还提供了XBAP的方式,不过已经逐渐被Silverlight所取代。
WPF的开发模式:其他层可以保持不变,针对Presentation提供了MVC 模式、MVP模式 、MVVM 模式。
项目和性能相关:WPF在诸多方面都做得很好,除了满足其他客户端技术的功能外,也有自己的独特一面。在性能方面,只要多注意一些细节,就可以超过预期的满足企业的需求。
2,核心概念
可以看到上面的基础概念很多,但圣殿骑士认为核心概念主要有以下三点:
A,依赖属性体系
首先从依赖属性基本介绍讲起,然后过渡到依赖属性的优先级、附加属性、只读依赖属性、依赖属性元数据、依赖属性回调、验证及强制值、依赖属性监听、代码段 (自动生成) 等相关知识,最后我们会模拟一个WPF依赖属性的实现,来看看它里面的内部究竟是怎样处理的,这样就可以帮助我们更好的认清它的本质,出现问题的时候我们也可以根据原理快速找到原因。
B,事件体系
讲到WPF事件体系,我们就不得不来一场短暂旅行,由于圣殿骑士之前是从C和C++过渡到.NET和JAVA,所以对Win32程序有一些粗浅的认识,不管是Win32/C++还是MFC/C++,在窗体和事件处理上本质都是用消息(Message)来进行通信,只不过MFC对这些繁杂和通用的代码进行了一些封装,到WinForm和WPF也不例外,无疑底层还是通过这些消息在传递操作。有了Win32-&MFC-&WinForm-&WPF这种Message的演变之后,我们必须得认识其中的一些核心概念,比如函数指针、委托回调、委托和事件以及现在提的路由事件。由于这些知识太多,所以不进行深究,在这里我们只研究委托和事件的一些知识、委托和事件实现原理、路由事件的原理以及路由事件的使用,通过这么一来回,可能大家会对路由事件有一个比较清晰的认识,最主要的是能在项目中运用自如。
C,Binding
前面讲了WPF的依赖属性体系和事件体系,这里再讲第三个核心概念——Binding,WPF 绑定可以在源数据对象和UI 控件间建立联系,实现单向或双向变更通知,以此实现更好的业务逻辑和UI的分离。也正是因为Binding,才使得UI和业务逻辑的耦合隔离变得如此轻松,也正是因为Binding,我们才实现了MVVM模式,所以Binding在这个过程中起到了核心作用。同时我们也要注意到Binding的知识点非常多,所以就分成三大块来讲解。
大家可能会说为什么三大核心不包含其他概念?如为什么没有Command?为什么没有动画?为什么没有3D?其实这些技术都是比较靠上层的一些技术细节,在最底层还是依赖于上面的三大核心功能,具体本文就不再详细阐述了,后面的文章再续。
六. WPF工具
WPF工具主要分为开发工具和其他帮助工具,当然这里只是列出了使用频率最高且常见的一些工具。
开发工具:
Visual Studio 10
Expression Design 2/3/4
Expression Blend 2/3/4
Expression Encoder 2/3/4
其他常用工具:
WPF Inspector
XAML Power Toys
WPF Performance Suite
基本上就用到了以上的一些开发和帮助工具,具体使用由于受篇幅所限,这里就不做过多介绍,后面会开单独的篇幅来详述。
由于“WPF企业内训全程实录”这篇文章花了十多个晚上的时间,所以内容涵盖面广且文章较长。为了提高阅读质量,我把它拆分成了三篇,今天先发布内容较少且较简单的上篇,下周一、二会接着发布其余两篇,敬请期待!最后声明一下,由于圣殿骑士才识浅薄,所以以上观点只是个人的看法与心得,遗漏和错误之处也敬请海涵。怀着技术分享与交流的态度分享出来,希望各位多多指教!原文链接:
发布于 3年前,
阅读(53) | 评论(0) |
投票(0) | 收藏(1)
、、各种类型伤害计算、完美的
读者声音:还没写就开始激动了,典型的傻子。
一、完美的改进型寻路移动模式
何谓改进型完美;接下来即进行时时的障碍物判断,如果没有碰撞到任何障碍物或对象则将该直线移动保持到终点;但是中途一旦碰到障碍物,则以目的地为终点即时启动
原理很简单,关键技术就是如何对碰撞进行检测?
传统的方法有两种:
第一种我且称之为坐标还原法:即时时记录精灵未碰撞障碍物时的坐标是使用简单,不需要复杂的判断逻辑;缺点是效果不好,在画面上将造成精灵一瞬间被弹开的情况,虽然那一刻非常的短暂且距离微小,但是对于精灵移动动画平滑性的影响是严重的,因此我们最好不要采用此方法。
第二种为启发式预测法:该方法的原理为时时对精灵前方的区域进行预测,一旦发现前方有障碍物,则即时启动
上图中已经给了很详细的说明,即在直线移动过程中,精灵时时判断此时朝向前方的单元格是否为障碍物,如果是则启动遇到障碍物了:
障碍物预测法)
WillCollide() {
switch ((int)Spirit.Direction) {
return Matrix[(int)(Spirit.X / GridSize), (int)(Spirit.Y / GridSize) - 1] == 0 ? true : false;
return Matrix[(int)(Spirit.X / GridSize) + 1, (int)(Spirit.Y / GridSize) - 1] == 0 ? true : false;
return Matrix[(int)(Spirit.X / GridSize) + 1, (int)(Spirit.Y / GridSize)] == 0 ? true : false;
return Matrix[(int)(Spirit.X / GridSize) + 1, (int)(Spirit.Y / GridSize) + 1] == 0 ? true : false;
return Matrix[(int)(Spirit.X / GridSize), (int)(Spirit.Y / GridSize) + 1] == 0 ? true : false;
return Matrix[(int)(Spirit.X / GridSize) - 1, (int)(Spirit.Y / GridSize) + 1] == 0 ? true : false;
return Matrix[(int)(Spirit.X / GridSize) - 1, (int)(Spirit.Y / GridSize)] == 0 ? true : false;
return Matrix[(int)(Spirit.X / GridSize) - 1, (int)(Spirit.Y / GridSize) - 1] == 0 ? true : false;
return true;
WillCollide()
有了它以后,我们同样还需要像
private void NormalMoveTo(Point p) {
int totalcost = (int)Math.Sqrt(Math.Pow(p.X - Spirit.X, 2) + Math.Pow(p.Y - Spirit.Y, 2)) / GridSize * UnitMoveCost;
double direction = Super.GetDirectionByTan(p.X, p.Y, Spirit.X, Spirit.Y);
doubleAnimation = new DoubleAnimation(
direction,
direction,
new Duration(TimeSpan.FromMilliseconds(totalcost))
Storyboard.SetTarget(doubleAnimation, Spirit);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(&Direction&));
storyboard.Children.Add(doubleAnimation);
storyboard.Begin();
这里要特别注意的是我用黄色背景注明的
private void Carrier_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
Point p = e.GetPosition(Map); //中的坐标点
if (Matrix[(int)p.X / GridSize, (int)p.Y / GridSize] != 0) {
Spirit.Destination = //
&Spirit.Action = Actions.R //
Spirit.IsAStarMoving = false; //
NormalMoveTo(p); //
看完上面代码有朋友就要问了:这两种移动方式,但是如何在逻辑中对其进行很好的衔接,这里就必须加入
private void Timer_Tick(object sender, EventArgs e) {
if (ArriveTarget()) {
&&&&&&&&&&&Spirit.Action = Actions.S
} else if (!Spirit.IsAStarMoving && WillCollide()) {
//会饶过障碍物的,
AStarMoveTo(Spirit.Destination);
&&&&&Spirit.IsAStarMoving = true;
通过黄色背景代码部分的逻辑我们可以轻松实现精灵的直线移动与
二、完美遮罩层
首先我们按照第十一节中说到的方法来截取我们地图中心的这个标志物,并取名为
接下来我们同样在后台代码中初始化它:
Image Mask = new Image();
private void InitMask() {
Mask.Width = 202;
Mask.Height = 395;
Mask.Source = new BitmapImage((new Uri(@&Map\Mask3.png&, UriKind.Relative)));
Mask.Opacity = 0.7;
Carrier.Children.Add(Mask);
Canvas.SetZIndex(Mask, 612); //的高 + Mask的Y值,由于还没引进地图控件暂时这样写
最后就是在游戏窗口刷新线程中对它也进行时时的更新:
Timer_Tick(object sender, EventArgs e) {
Canvas.SetLeft(Mask, MapLeft + 793);
Canvas.SetTop(Mask, MapTop + 217);
&&&Canvas.SetLeft(Spirit, Spirit.X - Spirit.CenterX + MapLeft);
Canvas.SetTop(Spirit, Spirit.Y - Spirit.CenterY + MapTop);
Canvas.SetZIndex(Spirit, (int)Spirit.Y); //画家算法)
这里关键的代码就是黄色部分代码,我通过)Spirit.Y)
三、完美换装
这个就简单多了,因为之前的章节中已经将相关参数与实现方法都定义好了,那么剩下的就是如何调用的问题。这里为了演示方便,我在
private void ChangeEquipment(object sender, RoutedEventArgs e) {
Spirit.Equipment[0] = Convert.ToInt32(comboBox1.SelectionBoxItem.ToString());
Spirit.Equipment[1] = Convert.ToInt32(comboBox2.SelectionBoxItem.ToString());
Spirit.Source = Super.EquipPart(Spirit.Equipment, Spirit.DirectionNum, Spirit.DirectionFrameNum, Spirit.TotalWidth, Spirit.TotalHeight,Spirit.SingleWidth, Spirit.SingleHeight);
这三行代码实在太简单因此不再多做说明。需要提的是在更换衣服与武器的时候,如果内存中不存在该新衣服与武器搭配,则需要时时的进行合成,这会根据您
四、寻路之大补充
鉴于目前很多朋友反馈说
去设置其中的
因此,我引入
大家也不妨将
3,否则后果就如我上文中提到的,一张大且无规律的地图将让你痛不欲生)。但是,在
归纳补充了那么多关于
本节即将结束,同样标志着第二部分的开始。第二部分我将就本文开头用彩色字所提到的相关知识进行讲解,或许那才是您真正想要了解的,它将引领我们进入一个真正
教程目录及源码下载:
本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面显著位置给出原文连接,否则保留追究法律责任的权利。
原文链接:
发布于 3年前,
阅读(67) | 评论(0) |
投票(0) | 收藏(0)
DemoHUD4*1248
Piece hitPiece = null; //
/// &summary&
/// &/summary&
private void img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
if (hitPiece == null && (int)((sender as Piece).Code) != -1) {
hitPiece = sender as Piece;
hitPiece.Effect = new DropShadowEffect() { BlurRadius = 8, ShadowDepth = 0, Color = Colors.Red };
} else if (hitPiece != null) {
int oldRow = Grid.GetRow(hitPiece);
int oldColumn = Grid.GetColumn(hitPiece);
Piece piece = sender as Piece;
int newRow = Grid.GetRow(piece);
int newColumn = Grid.GetColumn(piece);
Grid.SetRow(piece, oldRow);
Grid.SetColumn(piece, oldColumn);
Grid.SetRow(hitPiece, newRow);
Grid.SetColumn(hitPiece, newColumn);
hitPiece.Effect = null;
hitPiece = null;
e.Handled = true;
多个则按阵型移动
mainScene.SelectedArmy[0].MoveTo(p);
for (int i = 0; i & facePlate.formation.Children.C i++) {
Piece piece = facePlate.formation.Children[i] as Piece;
if (piece.Code != -1) {
int row = Grid.GetRow(piece);
int column = Grid.GetColumn(piece);
piece.CorrespondingSprite.Enemy = null;
&&&piece.CorrespondingSprite.MoveTo(new Point(p.X + column * pieceSpace, p.Y + row * pieceSpace));
教程目录及源码下载:
本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面显著位置给出原文连接,否则保留追究法律责任的权利。
原文链接:
发布于 3年前,
阅读(26) | 评论(0) |
投票(0) | 收藏(0)
Web400*4002500800*6009
GridShowGridLines
/// &summary&
/// &/summary&
private void SetGridLines(Canvas carrier, double totalWidth, double totalHeight, double singleWidth, double singleHeight,Color lineColor, double dashWidth, double dashSpace) {
carrier.Children.Clear();
int sectionXNum = (int)(totalWidth / singleWidth);
int sectionYNum = (int)(totalHeight / singleHeight);
&&&&&&&for (int x = 1; x &= sectionXN x++) {
Line line = new Line() {
X1 = x * singleWidth,
X2 = x * singleWidth,
Y2 = totalHeight,
&&&Stroke = new SolidColorBrush(lineColor),
StrokeDashArray = new DoubleCollection() { dashWidth, dashSpace },
carrier.Children.Add(line);
for (int y = 1; y &= sectionYN y++) {
Line line = new Line() {
X2 = totalWidth,
Y1 = y * singleHeight,
Y2 = y * singleHeight,
Stroke = new SolidColorBrush(lineColor),
StrokeDashArray = new DoubleCollection() { dashWidth, dashSpace },
carrier.Children.Add(line);
FillWinFormWPFWinForm
dllWindowsFormsIntegrationlSystem.Windows.Forms
&xmlns:WinFormHost = &clr-namespace:System.Windows.Forms.Iassembly=WindowsFormsIntegration&
&xmlns:WinForm = &clr-namespace:System.Windows.Fassembly=System.Windows.Forms&
10*10250*286
)(mapWidth / (double)SectionWidth.Value);
)(mapHeight / (double)SectionHeight.Value);
x = 0; x & sectionXN x++) {
for (int y = 0; y & sectionYN y++) {
CroppedBitmap croppedBitmap =
(mapSource, new Int32Rect(x * (int)SectionWidth.Value, y * (int)SectionHeight.Value, (int)SectionWidth.Value, (int)SectionHeight.Value));
System.IO.FileStream fileStream =
new System.IO.FileStream(string.Format(@&{0}/{1}_{2}.jpg&, outputSection.SelectedPath, x, y), System.IO.FileMode.Create);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(croppedBitmap));
encoder.Save(fileStream);
fileStream.Close();
1350*40064320*400
2jpgWebPhotoshop
教程目录及源码下载:
本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面显著位置给出原文连接,否则保留追究法律责任的权利。
原文链接:
发布于 3年前,
阅读(101) | 评论(0) |
投票(0) | 收藏(0)
SilverlightJavaScriptDemoJavaScriptDemoIndex.htm
&&&&/// &/summary&
/// &param name=&content&&&/param&
[ScriptableMember]
public void RandomSay(string content) {
Dialog dialog = new Dialog() {
Duration = 5,
LocatedSpriteWidth = BodyWidth,
Top = BodyTop
this.Children.Add(dialog);
pleted += (s, e) =& {
this.Children.Remove(s as Dialog);
HtmlPage.Window.Invoke(&RandomSay&, this, new int[] { TalkContentCode });
dialog.Show(content);
/// &summary&
/// &/summary&
/// &param name=&startX&&
/// &param name=&startY&&
/// &param name=&endX&&
/// &param name=&endY&&
[ScriptableMember]
public void RandomMoveTo(int startX, int startY, int endX, int endY) {
Random random = new Random();
int x = random.Next(startX, endX);
int y = random.Next(startY, endY);
Point start = this.C
Point end = new Point(x, y);
this.destination =
double spendTime = Math.Sqrt(Math.Pow((end.X - start.X) / LocatedScene.GridSize, 2) + Math.Pow((end.Y - start.Y) / LocatedScene.GridSize, 2)) * Speed * LocatedScene.GridS //
PointAnimation pointAnimation = new PointAnimation() {
Duration = new Duration(TimeSpan.FromMilliseconds(spendTime))
Storyboard.SetTarget(pointAnimation, this);
Storyboard.SetTargetProperty(pointAnimation, new PropertyPath(&Coordinate&));
StopMovingAnimation();
&&&&&&&&&&moveingAnimation = new Storyboard();
moveingAnimation.Children.Add(pointAnimation);
pleted += (s, e) =& {
RandomMoveTo(startX, startY, endX, endY);
moveingAnimation.Begin();
JavaScript]
&& Weapon=&-1& Mount=&-1& X=&85& Y=&82& Direction=&& Scripts=&RandomSay:0&/&
&& Weapon=&-1& Mount=&-1& X=&87& Y=&82& Direction=&2& Scripts=&RandomSay:1&/&
&& Weapon=&-1& Mount=&-1& X=&86& Y=&78& Direction=&4& Scripts=&RandomMove:84,75,88,80&/&
&& Weapon=&-1& Mount=&-1& X=&86& Y=&78& Direction=&3& Scripts=&RandomSay:2_RandomMove:88,79,91,82&/&
sprite.Loaded += (s, e) =& {
string str = xSprite.Attribute(&Scripts&).V
if (str != &&) {
string[] scripts = str.Split('_');
for (int n = 0; n & scripts.Count(); n++) {
string[] values = scripts[n].Split(':');
string[] args = values[1].Split(',');
&&&&&&&&&&HtmlPage.Window.Invoke(values[0], sprite, args);
xmlJavaScript(), sprite, new int[] { x1,y1,x2,y2 });JavaScriptRandomMoveRandomMoveSilverlightRandomMoveTo-NPC5A*
158NPCScript0sprite.Mount = 8; sprite.State = States.I OK
2Script.jstalkContentScript0
omSay(sprite,3);
3NPCSprite.cs]
EventHandler MovingC
NPC(^ ^ HOHO)
Silverlight4Silverlight3HLSLSilverlightCodingSilverlight
SilverlightCPU
Silverlight200*20033200*200
currentFrame = startF
translateY = BodyHeight * (int)D
RectangleGeometry() {
Rect = new Rect() {
X = translateX,
Y = translateY,
Width = BodyWidth,
Height = BodyHeight,
TranslateTransform() { X = -translateX, Y = -translateY };
()EffectSilverlight2.8DPNGAJPGUI3DConstReadOnlyStatic50%MMORPGSilverlight
AIXMLSilverlight
教程目录及源码下载:
本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面显著位置给出原文连接,否则保留追究法律责任的权利。
原文链接:
发布于 3年前,
阅读(25) | 评论(0) |
投票(0) | 收藏(0)
5,何谓根属性?就是所有基值属性的最底层。当角色升级时,通过手动或系统自动根据角色的职业特性对这55
double _VP
/// &summary&
/// 物理攻击力(最小 - 最大)
/// &/summary&
public double VPower {
get { return _VPower + Equip[16] + Buff[16]; }
set { _VPower = value; }
double _VA
/// &summary&
/// 闪避,跑速,攻速,施法速度
/// &/summary&
public double VAgile {
get { return _VAgile + Equip[17] + Buff[17]; }
set { _VAgile = value; }
double _VP
/// &summary&
/// 物理防御力,格档率(与暴击率相反,物理或魔法攻击伤害减半)
/// &/summary&
public double VPhysique {
get { return _VPhysique + Equip[18] + Buff[18]; }
set { _VPhysique = value; }
double _VW
/// &summary&
/// 魔法防御力,魔法攻击力(最小 - 最大)
/// &/summary&
public double VWisdom {
get { return _VWisdom + Equip[19] + Buff[19]; }
set { _VWisdom = value; }
double _VL
/// &summary&
/// 物理或魔法攻击加倍)及其他
/// &/summary&
public double VLucky {
&&&&&&&get { return _VLucky + Equip[20] + Buff[20]; }
set { _VLucky = value; }
/// &summary&
/// &/summary&
public double[] ABase { get; set; }
/// &summary&
/// 15-19大属性
/// &/summary&
public double[] Equip { get; set; }
/// &summary&
/// 减持值总和
/// 15-19大属性
/// &/summary&
public double[] Buff { get; set; }
/// &summary&
/// 成长率)
/// &/summary&
public double[] Coefficient { get; set; }
/// &summary&
/// &/summary&
public double VAttackMax {
get { return ABase[2] + Equip[2] + Buff[2] + VPower * Coefficient[2]; }
CLRVAttackMax = ABase[2] + Equip[2] + Buff[2] + VPower * Coefficient[2](即通过多个影响其值的相关属性值集合而成,并非通过直接赋值得到,这样做可以轻松构建出通用且易于维护的精灵属性系统)。其中Abase[2]ABase[2]30ABase[2]10Equip[2]Buff[2]Coefficient[2]Coefficient[2]10Coefficient[2]2VAgileVPhysique
/// &summary&
/// &/summary&
/// &param name=&obj&&
/// &param name=&obj&&
/// &returns&否
private bool IsOpposition(QXSpirit me, QXSpirit obj) {
if (me == obj) {
return false;
//值大于或等于7则返回是
} else if (obj.VPK &= 7) {
return true;
//模式与对方的PK模式进行比较进行相应返回
switch (me.PKMode) {
case PKModes.Peace:
return false;
case PKModes.Whole:
&&&&&&&&&&&&&&&&&&&&return true;
case PKModes.GoodAndEvil:
return obj.PKMode == PKModes.Whole ? true : false;
case PKModes.Faction:
&&&&&&&&&&return me.VFaction != obj.VFaction ? true : false;
case PKModes.Clan:
return me.VClan != obj.VClan ? true : false;
return false;
&&&&&&&&&&}
WillAttack(QXSpirit attacker, QXSpirit defenser) {
return defenser == null ? false : Super.InCircle(attacker.X, attacker.Y, defenser.X, defenser.Y, attacker.AttackRange);
bool InCircle(double targetX, double targetY, double centerX, double centerY, double radius){
return &Math.Pow(targetX - centerX, 2) + Math.Pow(targetY - centerY, 2) &= Math.Pow(radius, 2) ? true : false;
20EffectiveFrame
private void Timer_Tick(object sender, EventArgs e) {
&&&&&&&&if (FrameCounter == EffectiveFrame[(int)Action]) {
Super.DoInjure(this);
/// &summary&
/// &/summary&
/// &param name=&spirit&&
public static void DoInjure(QXSpirit spirit) {
QXSpirit Enemy = (spirit.Parent as Canvas).FindName(spirit.LockObject) as QXSpirit;
Random random = new Random();
if (random.Next(100) &= (spirit.VHit - Enemy.VDodge)) {
Super.ShowText(Enemy, true, true, &Avoid&, &Miss&, 34, Colors.SkyBlue, 2);
int Injure = 0;
if (spirit.Action == Actions.Attack) {
Injure = Convert.ToInt32(spirit.VAttackMin + random.Next((int)(spirit.VAttackMax - spirit.VAttackMin)) - Enemy.VDefense);
} else if (spirit.Action == Actions.Magic) {
Injure = Convert.ToInt32(spirit.VMagicMin + random.Next((int)(spirit.VMagicMax - spirit.VMagicMin)) - Enemy.VMagicDefense);
if (random.Next(100) &= (spirit.VBurst - Enemy.VBlock)) {
Injure *= 2;
Super.ShowText(Enemy, true, true, &Avoid&, string.Format(&Burst), 30, Colors.Red, 2);
Super.ShowText(Enemy, true, false, &Avoid&, Injure &= 0 ? Injure.ToString() : &0&, 30, Colors.Yellow, 0.5);
Enemy.VLife = Enemy.VLife & Injure ? 0 : Enemy.VLife - I
65%18%ShowText()QXTextBorderTextOpenDoInjure()DoInjure()
QXText text = obj as QXText;
if (text.Opacity &= 0) {
&&&&&&&&Remove(text);
text.Opacity -= 0.005;
text.Y -= 0.5;
-0.0050.51-&0
教程目录及源码下载:
本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面显著位置给出原文连接,否则保留追究法律责任的权利。
原文链接:
发布于 3年前,
阅读(58) | 评论(0) |
投票(0) | 收藏(0)
800*600400*300
800*600400*300
400300x,y2_3.jpg2_391_2.jpg2_2.jpg3_2.jpg1_3.jpg2_3.jpg3_3.jpg1_4.jpg2_4.jpg3_4.jpg
Canvas MapS
int mapSectionWidth, mapSectionHeight, mapSectionXNum, mapSectionYN
/// &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&
/// &/summary&
public int leaderSectionX {
get { return _leaderSectionX; }
set { if (_leaderSectionX != value) { _leaderSectionX = value; ChangeMapSection(); } }
int _leaderSectionY;
/// &summary&
/// &/summary&
public int leaderSectionY {
get { return _leaderSectionY; }
set { if (_leaderSectionY != value) { _leaderSectionY = value; ChangeMapSection(); } }
leaderSectionXleaderSectionYXY_ChangeMapSection
Image mapS
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;
startSectionX = leaderSectionX - 1; endSectionX = leaderSectionX + 1;
if (leaderSectionY == 0) {
startSectionY = 0; endSectionY = 2;
} else if (leaderSectionY == mapSectionYNum - 1) {
startSectionY = leaderSectionY - 2; endSectionY = leaderSectionY;
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);
leaderSectionX = (int)(Leader.X / mapSectionWidth);
leaderSectionY = (int)(Leader.Y / mapSectionHeight);
Source = Super.getImage(string.Format(&Map/{0}/Surface/{1}_{2}.jpg&, mapCode.ToString(), x, y)),
Width = mapSectionWidth + 1,
Height = mapSectionHeight + 1,
Stretch = Stretch.Fill,
BUGNONO400*300
800*600400*300400300
教程目录及源码下载:
本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面显著位置给出原文连接,否则保留追究法律责任的权利。
原文链接:
发布于 3年前,
阅读(38) | 评论(0) |
投票(0) | 收藏(0)
本博客空间所有随笔及文章均采用
),使用“
(CC)”名称来支持Creative Commons 版权协议。
“创作共用”体现两个方面的含义:
“创作” 是缘自于创作者的行为,并产生作品为结果,创作者有权利要求自己的作品所附加的各种权利。在传统的“保留所有权利”的版权体系中,创作者的权利被错误地变成了“封闭”和“不传播”。在互联网时代,“保留部分权利”已经成为一种更有利于创作者的趋势。
“共用” 体现了人们愿意将作品给更多人使用的愿望,这种共同使用的前提是尊重创作者所选择的权利要求。我们把愿意共用的精神称为“分享主义”(Sharism),分享主义的前提是尊重创作者的权利,而不是随意剥夺变成“公有”。
& 署名 && 非商业用途 && 保持一致 3.0
你可以免费
拷贝、分发、呈现和表演当前作品
制作派生作品
但是必须基于以下条款:
署名。你必须明确标明作者的名字。.
非商业用途。 你不可将当前作品用于商业目的。
保持一致。如果你基于当前作品更改、变换或构造新作品,你应当按照与当前协议完全相同的协议分发最终作品。
对于任何二次使用或分发,你必须让其他人明确当前作品的授权条款
在得到作者的明确允许下,这里的某些条款可以放弃
此约定是的简单易读概要
&&& 这里的内容不是协议本身,只是一份简单的参考说明,帮助你理解完整的法律文本(完整的协议)。这是一份普通人可以理解的主要条款表达方式。可以认为是一份法律文本的用户友好界面。这里的约定本身并没有法律意义,内容不会出现在真正的许可协议中。 “创作共用”组织不是一家法律事务所,不对外提供法律服务。分发、呈现或者链接到这个共用约定不代表建立”律师—客户”这样的关系。
原文链接:
发布于 3年前,
阅读(38) | 评论(0) |
投票(0) | 收藏(0)

我要回帖

更多关于 三国策8官网 的文章

 

随机推荐