关于“新手引导界面”界面,按钮如何对应引导?

1、开场介绍
在玩家安装好星际火线,并首次开启时,会进入新手引导!首先玩家会看到一段开场动画,我们可以通过开场动画了解星际火线的游戏背景及故事发展!
2、操作引导
在新手引导中,系统会通过简单的关卡对玩家进行引导,教大家基础的操作及武器、机甲的使用!游戏画面左下角有一个圆圈状的虚拟按钮,玩家通过滑动虚拟按钮控制人物的移动。而右下角分别有三个武器按钮,两个技能按钮和一个机甲按钮!玩家可以自由选择武器、机甲、技能的使用!
3、战斗引导
在新手引导中,玩家会逐步解锁各种类型的武器!分别体验突袭系、毁灭系、特殊性的武器特性,及机甲的操作和技能!
1、登陆界面
当玩家通过新手引导后,便会进入登陆界面!玩家在这里可以看到【与微信好友玩】、【与QQ好友玩】两个按钮,分别是微信登陆和QQ登陆通道。玩家可以根据自己的需要,选择并使用对应帐号登陆星际火线!
2、区服选择
当玩家进入游戏后,可以通过点击选区进入服务器选择界面,这里有很多服务器可以供玩家选择!玩家选择区服后,便可正式进入游戏。
3、角色建立
星际火线设有男、女两种角色,玩家选择自己喜欢的角色后,输出昵称便可进入游戏。
活动系统处于游戏主界面的右上角,充值活动、签到奖励、在线奖励、嘉年华、累积登陆应有尽有,玩家可以通过各种福利活动活动更多资源和道具,从而更好的提升自己的战斗力。
2、主体界面
当玩家进入游戏后,会看到角色、机甲等标志,这是星际火线的主要界面!各种福利、不同的副本、竞技入口都在这里。点击机甲,还可以进入机甲界面,进行解锁、强化机甲!往右拖动后,还可以看到商店、军团、生活区、排行榜、科技实验室等玩法哦!
在主界面的左侧一览中,为星际火线的社交系统区域!这里有社区、部落、好友、聊天等功能,玩家可以随心所欲的和小伙伴交流游戏心得!
在屏幕的正下方是星际火线的装备系统栏,角色、枪械、军衔、装备、飞翼、佣兵、星宠、任务、仓库入口都在这里,玩家可以通过强化各种装备提升自己的战斗力。
在主界面的右下角,有战役副本入口。玩家通过战役副本可以了解并参与剧情,挑战高难度关卡,获得更多的资源!
1、系统简介
角色系统是星际火线中的基础系统,角色系统是一个非常精彩多样的系统!其中涵盖角色、技能、衣橱、天赋、枪械图鉴、成就、机甲图鉴、能量晶石、巅峰技能等9个玩法!
2、角色名片
角色名片是角色系统中的基础,玩家可以在角色名片中看到玩家的基础信息!比如角色属性、装备、机甲、的播放机、段位、军衔等,玩家可以通过角色名片了解自己角色的战斗力!
3、角色技能
角色技能是玩家在战斗中的辅助技能,玩家可以通过提高角色等级获得角色技能,并且装备在技能栏中,以便于在战斗中释放。角色技能是主动技能,不同的技能具有不同的实战效果。
衣橱是星际火线中的时装系统,玩家可以在各种玩法中获取衣服、发型、翅膀幻化外观等到道具,然后再通关衣橱装备在角色身上,让角色变的更加炫酷!而且角色的衣服、发型、幻化都有加成属性哦。
5、角色天赋
天赋系统是角色的被动技能,玩家可以通过开启天赋、提升天赋等级,来获得更高的战斗力。如果玩家对天赋的加点不满意,也可以通过重置按钮,重置所有的天赋点。
6、巅峰技能
当角色满级之后再获得经验,将会获得巅峰等级!当玩家的每次提升巅峰等级时,可以获得巅峰技能点升级巅峰技能。巅峰技能同属被动技能,可以在各方面提高玩家的战斗力。
装备是由6个部件组成,玩家可以通过战役、时空战役获取装备!并且当玩家达到一定等级时,可以开启装备强化、升星等操作,从而提升战斗力。
枪械是星际火线中的核心装备,玩家可以通过各种玩法获取强大的枪械,并且进行升品、升星、升级等操作,从而提高输出能力。而且枪械还拥有强大的被动技能,可以帮助玩家在副本、竞技场中打出更高的伤害。不同品级的枪械,威力也是不一样的哟!
飞翼是星际火线中一种特殊装备,玩家获取飞翼后,可以进行装备,并且搭配组件,获得极高的战斗力加成。而且飞翼可以幻化成各种炫酷的翅膀外观,让玩家的角色更加炫酷。
佣兵是玩家征战各种副本的好伙伴,佣兵不但可以在副本中帮助玩家战斗,还能提供战力加成。而且佣兵也可以使用枪械、装备、技能。玩家升级佣兵,可以获得更多的战斗收益。
1、日常任务
日常任务是玩家在星际火线中必做的任务,玩家每天完成对应的日常任务,可以获得大量的升级经验!
2、成就任务
成就并不是在任务系统中,玩家可以通过角色系统进入成就任务界面。成就任务分为三种,分别是养成、战斗、交互。完成不同的成就任务,可以获得大量的钻石、道具等奖励。
1、累积登录
当玩家进入星际火线后,便可以参与累积登录活动。每天登陆星际火线即可领取福利,海量金币、超神武器、炫酷机甲任你拿!
2、开服嘉年华
开服嘉年华是限时活动,玩家可以通过完成嘉年华的活动,获得大量的钻石、机甲碎片、枪械升级材料、枪械碎片等珍惜道具。但开服嘉年华只能在开服的前7天参与哦!
3、签到有礼
签到活动是星际火线中最基本的福利活动,玩家每天登陆星际火线,便可以点击领取奖励。累积一定的签到天数,还能领取额外的奖励。玩家如果少签或漏签,也可以通过补签找回奖励。
4、活动福利
活动福利包括很多种,比如资源找回、新兵补给包、贸易大促销、积少成多、月卡福利、成长基金。玩家进入星际火线后,可以根据自己的需求,参与并获得奖励。
5、在线有礼
在线有礼是在线时间奖励,玩家在线达到一定的时间后,可以领取对应的在线奖励。玩家每天在线120分钟,便可领取全部奖励。
1、仓库分类
仓库是玩家的储存系统,玩家的一些道具、枪械都可以在仓库中找到。仓库系统分为两个,分别是枪械仓库和道具仓库!
2、枪械仓库
玩家点击进入仓库后,最先看到的就是枪械仓库!而且枪械仓库根据枪械的系别,分为突袭系、毁灭系、特殊系,玩家可以根据自己想要的枪械类别,快速的找到对应的枪械。
3、道具仓库
道具仓库主要存放玩家的一些消耗道具,比如枪械升品材料箱、宠物经验材料、觉醒石、货柜钥匙等物品。
1、商店入口
游戏商店是玩家购买装备和道具的地方,玩家可以直接在推荐类别中购买各种装备、道具!不过星际火线中的商城入口是单独设计的,玩家在进入游戏后,向右拖动界面,便可以找到商店入口!
2、神秘货柜
神秘货柜是星际火线中的抽奖系统,玩家可以花费钻石开启货柜,并随机获得海量道具。而且玩家每开启一次神秘货柜,便可以获得1点信誉点。当玩家获得足够的信誉点后,可以通过信誉点兑换,兑换一些珍惜道具!
3、地下集市
地下集市是每天按时刷新的福利商店,玩家可以在这里使用钻石、金币购买道具。而且这里的道具性价比都非常高!
4、最强兵王商店
最强兵王商店是竞技商店的一种,玩家可以在最强兵王商店中购买紫色武器碎片、机甲碎片等道具。不过在最强兵王商店中,玩家需要花费攻擂点购买道具。而攻擂点则需要玩家在竞技玩法的最强兵王中获取。
5、竞技场商店
顾名思义,竞技场商店是专属竞技玩法的商店!如果想要购买竞技商店中的道具,则需要在竞技技场中获得足够的竞技场功勋才行哦!
6、军团商店
军团商店是军团专属商店,首先玩家要加入军团,然后通过军团捐献或军团中的各种玩法,获得军团贡献点。然后才能通过军团商店,购买对应的道具。
1、战役副本
战役副本是星际火线中的剧情副本,分为主线、精英、时空三个系列!玩家可以通过战役副本获取经验、道具,提升自身的等级和战斗力。其中时空副本可以产出大量的装备,玩家可以多多参与。
2、上古遗迹
上古遗迹是星际火线中飞翼的重要产出地,玩家可以以单人、组队的形式挑战各种上古文明遗迹。不同难度的上古遗迹,会掉落不同品级的飞翼。如果玩家达到至尊8,还可以开启宝藏功能,直接破坏宝箱获得奖励。
3、挑战——全息训练场
全息训练场有三种,分别是产出金币的黄金国度;产出枪械经验卡的极速战场,以及产出佣兵经验卡的虚空星源。全息训练场中的每种玩法每天可以挑战三次,挑战成功便可获得对应的奖励。
4、挑战——丧尸围城
丧尸围城也是挑战系列玩法之一。玩家从第一层开始逐层挑战大量的丧尸,丧尸的难度会随着挑战层数的增加而变大,不过玩家也可以通过奖励层获得增益BUFF,提高自己的通关能力。丧尸围城玩法主要产出机甲碎片、金币、枪械经验卡等经验道具!
5、挑战——异次元杀阵
玩家首次解锁异次元杀阵后,将会被自动分配到一个最多10人组成的小组。玩家每次可以选择任意四个关卡进行闯关,闯关成功后则可以挑战BOSS并获得击败BOSS的奖励。系统将会以玩家本日最好的挑战成绩进行排名,并结算奖励。异次元杀阵主要产出晶石宝箱,可用来镶嵌在装备上。
6、挑战——迷失空间
迷失空间可以为玩家提供金币、星宠食物等奖励,迷失空间作为日常挑战,玩家失败后可以再次挑战,通关层数越高,奖励也越加丰厚哦,且至尊10即可开启精英难度。
7、无尽位面
无尽位面有两种玩法,分别是位面入侵和位面裂隙。位面入侵玩法需要两名旺季合作战斗,抵御入侵位面的生物,在一定的时间内,保护位面控制塔。
而位面裂隙则是限时活动,玩家可以在活动时间内进入位面裂隙,对【收割者格萨拉】进行攻击,玩家造成的伤害越高,排名越靠前,获得的奖励也越多!
星际火线中的竞技玩法有两种,分别是最强兵王玩法和竞技场玩法。其中最强兵王为自动竞技,而竞技场则玩法较多。
1、最强兵王
最强兵王是星际火线中的自动竞技玩法,玩家自主选择对手进行膜拜或攻擂!如果战斗胜利,若防守方的排名高于进攻方,双方排名对调!玩家每天可以发起5次免费挑战,挑战成功可提升排名,当玩家到达一定的排名后,可以获得丰厚的排名奖励
竞技场中玩法比较多样化,玩家可以自由选择1V1、3V3或终极大乱斗进行对战。其中1V1是单人竞技,而3V3是组队竞技。大乱斗则是系统随机匹配6名玩家,各自为战并争夺最后的胜利!在竞技场玩法中,玩家可以获得枪械碎片、竞技场功勋等道具。
1、军团系统
玩家达到一定的等级后,便可以通过军团入口,加入自己喜欢的军团。军团内不但有各种精彩的玩法,还有更多的福利。最主要的是,玩家可以通过军团认识更多志同道合的小伙伴,丰富游戏内的乐趣。
2、好友系统
在星际火线中,好友系统也是经过精心设计的哟!系统会将玩家的好友分为QQ/微信好友和游戏好友,让大家更清楚的找到自己的小伙伴。而且好友系统中设置了好友礼品,大家千万不要忘了为小伙伴送个好礼。
为了让大家更好的体验游戏,避免被自己不喜欢的人骚扰。星际火线还为玩家设计了黑名单,不想见到的人,统统把他们扔进黑名单吧!
3、聊天系统
聊天系统是星际火线中最主要的社交方式,玩家可以在聊天界面自由选择世界、军团、好友、组队、公告频道,和自己的队友、伙伴进行沟通。
1、军衔系统
军衔系统是星际火线中的成就玩法之一,当玩家参与各种玩法,并且满足一定的条件即可提升军衔等级。当玩家提升军衔等级时,可以获得枪械、机甲和相应的军衔属性。
排行榜是一种公开的成就系统!玩家在星际火线各种玩法中获得的成就,都将在这里展示,并且被所有的玩家看到。排行榜中分别设置了战力榜、最强兵王榜、军团榜、魅力榜、鲜花周榜、丧尸围城、星宠榜等,只要你有足够的实力,必然可以登顶星际!新手引导-找化网
1、注册步骤首页图
步骤一、打开找化网首页,点击红色标记的“请登录/注册”,弹出“会员中心”页面,点击“去注册”。
会员中心-注册账号页面
步骤二、正确填写手机号,点击“获取验证码”按钮,即可收到系统发送的短信验证码;将收到的验证码信息填写到相应位置,阅读并勾选平台“服务协议”,点击“提交注册信息”按钮,即可进入步骤三。
会员中心-基本信息填写页面
步骤三、填写您的用户名信息(提示:用户名为字母、数字及其组合,6-20个字符),并设置密码,点击“提交注册信息”按钮,即可完成注册。会员中心-注册成功页面
2、登录步骤
步骤一、打开找化网首页,点击红色标记的“请登录/注册”,弹出“登录”页面。
步骤二、输入用户名/手机号/邮箱和密码,点击“登录”即可完成登录步骤。登录页面使用第三方登录场景
步骤一、打开找化网首页,点击红色标记的“请登录/注册”,弹出“登录”页面。
步骤二、选择登录页上的第三方登录,弹出第三方的登录页面。
第三方的登录页面
步骤三、登录后,弹出“第三方登录账号信息完善”页面。
第三方登录账号信息完善页面
步骤四、填写设置用户名、密码、手机号、验证码等信息后,点击“提交”按钮,即可完成登录步骤并弹框提示成功。账号解绑手机号后登录场景:
步骤一、打开找化网首页,点击红色标记的“请登录/注册”,弹出“登录”页面。
步骤二、输入用户名/邮箱和密码,点击“登录”后弹出“账号登录信息完善”页面。
步骤三、填写手机号和验证码,点击“提交”即可弹框提示完善信息成功。
1、个人基本信息/企业信息
目前的会员等级分为:普通会员、企业会员、认证企业会员和资深企业会员。其中普通会员仅能采购商城中的商品(不包括危险品);企业会员、认证企业会员拥有发布求购/供应信息,在供应中询价购买时,或在求购中发布报价后,或发布求购信息后,可获得交易员的协助,能在商城中采购需要的商品,并且能享受平台的金融和物流服务;资深企业会员则在认证企业会员的基础上,加上商城店铺功能,包括设置店铺信息、发布商城商品、商品摆放设置、店铺活动等。
用户直接注册即可成为普通会员;成为企业会员或认证企业会员需通过审核,用户可以在“企业信息”页面填写所需的相应信息;若要升级为资深企业会员,请致电找化网客服热线。&会员中心-首页
登录后进入“会员中心”,点击导航栏中“账号管理”,弹出“账号管理”下的子导航“个人基本信息”、“企业信息”、“子账号管理”、“安全设置”和“地址管理”。
个人基本信息页面
个人基本信息:所有网站会员均可在“个人基本信息”中修改姓名、性别、头像、邮箱等一系列信息。
企业信息:普通会员升级为企业会员,或者企业会员升级为认证企业会员时,需要填写一系列企业信息,待信息审核通过后,即可完成会员升级。点击“企业信息”即可显示当前会员等级状态下的企业信息页面。会员中心-企业会员页面2、子账号管理会员中心-子账号管理若当前用户为企业会员的管理员时,则可以使用“子账号管理”功能:点击“开通本公司子账号”即可弹框申请子账号。弹框
子账号在“未激活”状态下,管理员可以重置子账号的密码。弹框
子账号在“已激活”状态下,管理员可以解绑子账号的手机号。
若该企业会员为资深企业会员(v4)时,则可以在网站商城开设店铺,并设置店铺管理员:点击“设置店铺管理员”按钮,弹框选择其中的某一会员为店铺管理员。
3、安全设置
“会员中心”-“安全设置”中可以“解绑手机号”、“绑定邮箱”、“解绑邮箱”以及“修改密码”的功能。
4、地址管理
“会员中心”-“地址管理”中点击“新增收货地址”即可创建收货人地址,并可以在相应地址下进行“编辑”和“删除”操作;此外会员可以将收货地址中的一条设置为“默认地址”。
登录页步骤一、点击“登录”页面中的“忘记密码”按钮,弹出“找回密码”页面。找回密码页步骤二、正确输入您的手机号或者邮箱信息,点击“获取验证码”按钮,即可收到系统发送的短信验证码;将收到的验证码信息填写到相应位置,点击“立即找回”按钮进入“密码重置”页面。密码重置页步骤三、两次输入设置的新密码,点击“提交”按钮即可完成密码修改,并进入“重置成功”页面提示成功找回密码信息。密码重置成功页面
商品已成功加入购物车
乙基-N-异丙基苯胺硼烷(71-22-1)
欢迎登录找化网WEB页面1549人阅读
other(51)
/post/58.html
使用框架:AS3
任务描述:了解游戏中新手的制作原理及流程
本章源码下载:
有人问我,都两年过去了,AS3&Coder系列怎么才出了10篇文章都不到?答案很简单:我TM懒得写!原计划出到10篇就洗手不写了,现在还有最后两篇,加把劲冲刺一下吧!
新手引导基本上在每个游戏中都会出现,或长或短,或简单或复杂,当然,新手引导流程越长越容易出现BUG,且传统的新手引导做法会极大地破坏代码的耦合性,为了解决“不稳定”及“破坏耦合性”这两个问题,贫道想了一种相对较好一点的(到底是好还是不好,列位看完本文之后就仁者见仁智者见智了)方式,在本文中介绍给大家。
传统的新手引导制作方式
传统的新手引导方式一般是设置一个全局的静态变量来保存当前新手引导进度,然后在项目中每个可能出现新手引导的位置添加一句判断:若当前新手引导步骤等于我所期望的步骤就执行引导部分的逻辑。例如,一个游戏中的新手引导第四步是引导用户去打开一个A窗口,然后第五步引导则是引导用户点击A窗口中的某个按钮。那么在A窗口的“打开窗口”函数中就会加上对当前新手引导步骤的一个判断,若当前步骤等于5,就执行相应的新手引导逻辑(例如,给A中需要引导用户点击的按钮加上一个箭头神马的)
public&function&onOpen():void
&if(&GuideManager.currentStep&==&5&)//GuideManager.currentStep是一个静态变量,用于存储当前新手引导进行到的步骤&&&
&{&&&&&//执行相应的引导逻辑&&&}
这种做法的弊端在于,它破坏了代码的耦合性,因为新手引导每涉及到一个组件,就需要在该组件中添加相应的判断语句及引导逻辑。而且当新手引导的步骤一多之后就会出现不稳定的情况,最烦人的是,一旦策划要求你在新手引导中插入几个步骤,那你几乎全部的涉及到新手引导的组件都会遭殃(原先if语句里的判断条件都会发生变动),而且你涉案组件那么多,难免会漏改几个位置。
基于接口的编程——降低耦合度的最佳方式
为了降低新手引导对项目耦合度的破坏性,有人提出了使用“继承”的方式,即游戏中的全部可视化组件都继承于同一个父类,然后在这个父类里面写上新手引导相关的逻辑代码,这样就可以一劳永逸了。不过话说回来,不一定全部涉及到新手引导的类都是继承自你这个共同的父类,而且使用你这种继承的方式来做,就会让全部继承自该共同父类的那些子类里面多出很多冗余的代码(因为只有极少的一部分子类会涉及到新手引导),尤其是在未启动新手引导时(玩家已经完成全部新手引导之后每次登陆游戏都是不会启动新手引导的)产生极大的浪费。
使用“接口”(Interface)的编程思想来做,就可以仅给有需要出现的新手引导的类添加相应的代码,最大限度地避免浪费的产生。
所谓“接口”的作用,就是让没有继承关系的类之间产生联系。让我们先来看一个小例子吧。现在我们有两个窗口类A与B,它们之间没有继承关系,虽然如此,但它们还是有共同之处的,就是都声明了一个名为“open”的打开窗口的方法,当执行该方法时,A/B窗口就会被打开。现在我想创建一个格式如下的方法:
public&function&openWindow(&win:*&):void
&&&&win.open();
使用openWindow方法,我可以快速地打开一个窗口,而A和B类的对象都有可能被当做参数传入该方法中,但是由于A、B两个类之间没有共同的父类,所以我openWindow的参数类型只能写成通配符(*)。当然,使用通配符是存在隐患的,因为传入的参数很有可能不具备一个名为open的public方法,这样的话就会发生报错。
为了将A、B联系起来,我们此时可以声明一个接口,该接口中声明了A、B类中所拥有的那些个同名函数和属性(在该例中A、B所拥有的同名函数只有一个open方法):
public&interface&IWindow
&&&&/**&执行打开窗口逻辑&*/
&&&&function&open():
声明完该接口之后,需要让A、B实现该接口:
public&class&A&extends&AP&implements&IWindow
&&&&public&function&open():void&&&&
&&&&&&&&&//do&something&&&&
//--------------------------------------------------------------//
public&class&B&extends&BP&implements&IWindow
&&&&public&function&open():void&&&&
&&&&{&&&&&
&&&&&&&&//do&something&&&&
现在,A、B类中的open方法都是对于接口IWindow的一个实现。之后,不论一个对象是A类型还是B类型,我们都可以使用IWindow的类型来引用它,这样的话,我们之前定义的openWindow方法就可以改成:
public&function&openWindow(&win:IWindow&):void
&&&&win.open();
参数win的类型不再是全部类型(*),而是将范围缩小到了所有实现了IWindow接口的对象,由于所有实现了IWindow接口的对象中都一定会有open方法,所以我们可以放心大胆地调用win.open()而不必担心再报错了。
&&“接口”不同于“继承”,继承必须按照从上至下的层级顺序,且一个类只能于一个父类,但接口却不同,一个类可以实现多个接口,如下类就同时实现了两个接口:
public&class&A&extends&AP&implements&IWindow,&IFucker
&&&&//class&body
正是因为接口的这个特性,使我们“仅给需要类添加代码”的假设成为了可能。下面,我们就来写一个接口,该接口约定了一些新手引导过程中将会用到的方法和属性:
&/**&*&如果某个面板将在新手引导中出现,那么它必须实现该接口&&*&@author&S_eVent&*&&*/public&interface&IGuideComponent{/**&处理新手引导相关事务&*&@param&data执行当前步骤时需用到的数据&*/function&guideProcess(data:Object=null):/**&执行新手引导卸载相关清理工作&*/function&guideClear():/**&注册到GuideManager中的实例名&*/function&get&instanceName():Sfunction&set&instanceName(value:String):}
该接口定义了两个方法(guideProcess及guideClear)和一个属性(instanceName)。在新手引导过程中会用到的类,都需要实现该接口才可以。使用基于接口的编程的好处有以下三点:
1.避免冗余代码的产生,哪个类需要实现新手引导的功能就让哪个类来实现该接口;
2.方便查找:你只要在项目中搜索该接口的引用位置,就可以一次性找全全部涉及到新手引导的类;
3.方便管理:全部与新手引导有关的逻辑代码都存放于名为guideProcess的函数中,某组件涉及到的新手引导步骤执行完毕后的清理工作都放在guideClear函数中。
新手引导管理器
为了便于管理和查询新手引导各步骤,我创建了一张XML表guide.xml用于记录新手引导的各个步骤,其格式如下:
&?xml&version=&1.0&&encoding=&utf-8&?&
&!--&Author:S_eVent
说明:节点名请保证使用step,否则将不被识别。
每个节点中的必须属性如下:
&sequence:显示此步骤出现的次序
&instanceName:此步骤所关联的实例名称
每个节点中的可选属性如下:
&subSeq:子步骤。某些界面可能会涉及到多次引导步骤,在每次步骤时执行的逻辑都不一样。此时用该属性来识别当前步骤该干嘛
&&step&sequence=&0&&instanceName=&ButtomButtonBar&&subSeq=&1&/&
&&step&sequence=&1&&instanceName=&Window1&&subSeq=&1&/&
&&step&sequence=&2&&instanceName=&Window1&&subSeq=&2&/&
&&step&sequence=&3&&instanceName=&ButtomButtonBar&&subSeq=&2&/&
sequence属性用以标示新手引导的步骤号;
instanceName则表示负责展示该步引导的实例名;
subSeq用于区分同一个组件展示出来的两个不同步骤。比如在上面的XML里面,“Window1”这个实例将负责展示步骤1和步骤2的新手引导,展示步骤1时,“Window1”这个窗口将引导用户点击窗口中的某个功能按钮(比如在该功能按钮上加一个箭头),而展示步骤2时,“Window1”就将引导用户点击窗口右上角的关闭按钮来关闭窗口。subSeq属性将会被传入&Window1&类的guideProcess方法中用于区分当前引导步骤应该执行哪个引导动作(是该引导用户点击窗口中某个功能按钮还是关闭按钮)。
在某个用户登录游戏时,服务器端会判断该用户是否需要进行新手引导,若该用户需要进行新手引导,那么咱们Flash前端就需要加载guide.xml以获取新手引导的步骤数据。实现代码如下:
private&function&onGameStart(&e:Event&):void
&&&&if(&_needGuide&)
&&&&&&&&loadGuideXML();
private&function&onResize(&e:Event&):void
&&&&_globalVariables.stageWidth&=&stage.stageW
&&&&_globalVariables.stageHeight&=&stage.stageH
private&function&loadGuideXML():void
&&&&var&loader:URLLoader&=&new&URLLoader();
&&&&loader.PLETE,&onGuideXMLLoadComp);
&&&&loader.load(&new&URLRequest(&guide.xml&)&);
private&function&onGuideXMLLoadComp(e:Event):void
&&&&var&data:XML&=&XML(&(e.currentTarget&as&URLLoader).data&);
&&&&var&guideData:Array&=&[];
&&&&for&each(var&x:XML&in&data..step)
&&&&&&&&guideData.push(&xml2Object(x)&);
&&&&guideData.sortOn(&sequence&,&Array.NUMERIC);
&&&&function&xml2Object(&xml:XML&):Object
&&&&&&&&var&obj:Object&=&{};
&&&&&&&&var&attributes:XMLList&=&xml.attributes();
&&&&&&&&for&each(var&a:XML&in&attributes)
&&&&&&&&&&&&obj[a.name().toString()]&=&a.toString();
&&&&&&&&return&
&&&&GuideManager.setUp(&guideData&);
&&&&GuideManager.start();
&加载完guide.xml之后我们需要将XML中的每一个标签都转换成相应的Object对象便于使用,最后把全部步骤对象放进一个数组中传递给我们接下来要介绍的新手引导管理器GuideManager类的setUp方法进行新手引导的启动工作,稍后,在需要开始新手引导时调用GuideManager.start方法开始新手引导的播放。
GuideManager类负责调度新手引导的暂停与播放,它提供了一系列static的静态方法,在项目中任意位置都可以调用到这些方法。
&*&新手引导管理器。请确保只有需要进入新手引导时才调用其setUp方法。
&*&@author&S_eVent
public&class&GuideManager&
&/**&指示符容器。高亮边框、引导指针等指示符都会被添加于此容器之上。若不设置值,则无法显示指示符&*/
&public&static&var&stage:S
&/**&新手引导完成一个步骤之后执行函数。此函数需接受一个Object型参数,代表当前完成步骤的配置数据&*/
&public&static&var&onStepFinish:F
&/**&新手引导播放完成后执行函数&*/
&public&static&var&onGuideFinish:F
&/**&注册成员地图。格式为{className1:IGuideComponent,&className2:IGuideComponent,&......}&*/
&private&static&var&_memberMap:Object&=&{};
&/**&新手引导播放队列,其中元素为每一步的实例&*/
&private&static&var&_guideQueue:Vector.&IGuideComponent&;
&private&static&var&_isSetUp:Boolean&=&
&/**&当前执行的步骤索引&*/
&private&static&var&_currentStep:int=-1;
&/**&下一个将执行的步骤索引&*/
&private&static&var&_nextStep:int=0;
&/**&记录新手引导具体步骤的数组。其中元素为每一步的实例名&*/
&private&static&var&_sequenceArray:A
&/**&记录新手引导每步所包含数据的数组&*/
&private&static&var&_dataArray:A
&/**&完成步骤列表。键为步骤序号,值为true/false,表示是否完成&*/
&private&static&var&_finishList:O
&private&static&var&_paused:B
&/**&存储一切当前使用的遮罩对象&*/
&private&static&var&_maskHome:Object&=&{};
&private&static&var&_border:S
&/**&启动新手引导&*/
&public&static&function&setUp(&config:Array&):void
&&if(&_isSetUp&==&false&)
&&&_isSetUp&=&
&&&_sequenceArray&=&[];
&&&_dataArray&=&[];
&&&_finishList&=&{};
&&&var&len:int&=&config.
&&&for(var&i:int=0;&i&&i++)
_sequenceArray[i]&=&config[i].instanceName.toString();
_dataArray[i]&=&config[i];
&&&_guideQueue&=&new&Vector.&IGuideComponent&();
&&&for(i=0;&i&&i++)
_guideQueue[i]&=&_memberMap[_sequenceArray[i]];
&/**&卸载新手引导&*/
&public&static&function&uninstall():void
&&if(&_isSetUp&)
&&&_isSetUp&=&
&&&if(&_currentStep&&=&0&)
doClear(_guideQueue[_currentStep]);
&&&_guideQueue&=&
&&&_currentStep&=&-1;
&&*&注册一个&IGuideComponent&到GuideManager中,这样它就会出现在新手引导过程中。
&&*&GuideManager会根据注册对象的instanceName来注册对象类名。若注册时发现instanceName
&&*&已被注册,则不执行接下来的注册过程
&&*&@param&instance&&欲注册对象
&public&static&function&register(instance:IGuideComponent):void
&&if(&instance&)
&&&var&name:String&=&instance.instanceN
if(&_memberMap[name]&)
_memberMap[name]&=&
//注册的时候若是发现新手引导已经启动,则搜索当前注册对象是否是新手引导的其中
//一个步骤,若是,则加入到引导队列中
if(&_isSetUp&)
&var&index:int&=&_sequenceArray.indexOf(name);
&while(&index&!=&-1&)
&&_guideQueue[index]&=&
&&//有时候,两个相邻步骤间会存在时间差。如步骤1执行完毕后调用nextStep发现步骤2
&&//尚未注册,此时会导致GuideManager暂停运作,那么就等待步骤2在注册时重新启动
&&//GuideManager的播放
&&if(&_nextStep&==&index&)
&&&nextStep(index);
&&&index&=&_sequenceArray.indexOf(name,&index+1);
&/**&开始新手引导
&&*&@param&from&从第几部开始&*/
&public&static&function&start(from:uint=0):void
&&nextStep(from);
&&*&进行下一步引导&
&&*&@param&designedStep&跳到指定的步骤。若该值为-1,则走到当前步骤的下一步。若将跳转到的步骤不存在,则结束新手引导
&public&static&function&nextStep(designedStep:int=-1):void
&&//若在暂停时调用nextStep,则自动执行resume方法继续播放新手引导
&&if(&_paused&)
&&&resume();
&&if(&designedStep&&&0&)
&&&_nextStep&=&_currentStep+1;
&&&_nextStep&=&designedS
&&//若该方法是由start方法调用情况下(此时_currentStep==-1)不需要让上一部引导完成:
&&if(&_nextStep&&&0&&&&_currentStep&&=&0&)
&&&markFinish(_currentStep);
&&if(&&_nextStep&&&_guideQueue.length&&&&_guideQueue[_nextStep]&)
&&&var&data:Object&=&_dataArray[_nextStep];
&&&_guideQueue[_nextStep].guideProcess(data);
&&&_currentStep&=&_nextS
&&//若无法执行欲跳转到的步骤,则不改变_currentStep的值
&&&//播放结束
&&&if(&_nextStep&==&_sequenceArray.length&)
if(&onGuideFinish&!=&null&)
&onGuideFinish();
uninstall();
&/**&暂停引导播放&*/
&public&static&function&pause():void
&&if(&!_paused&)
&&&_paused&=&
&/**&继续引导播放&*/
&public&static&function&resume():void
&&if(&_paused&)
&&&_paused&=&
&&&_guideQueue[_nextStep].guideProcess(_dataArray[_nextStep]);
&&&_currentStep&=&_nextS
&&*&显示全屏遮罩以限制交互范围
&&*&@param&showRect&唯一显示出来的能接受交互的矩形区域
&&*&@param&maskAlpha&遮罩透明度
&&*&@param&maskColor&遮罩颜色
&&*&@param&parent&&&遮罩添加到的父容器。若留空,则父容器就等于GuideManager.indicatorContainer
&public&static&function&showScreenMask(&showRect:Rectangle=null,&maskAlpha:Number=0.5,&maskColor:uint=0,&
&parent:DisplayObjectContainer=null,&maskName:String=&hotgirl&&):void
&&if(&!parent&)
&&&parent&=&
&&&if(&!parent&)
&&var&mask:Sprite&=&_maskHome[maskName];
&&if(&!mask&)
&&&//遮挡物必须是能够响应鼠标事件的类,如Sprite。否则鼠标点击之将会穿透它以触发其挡住的对象的鼠标事件
&&&mask&=&new&Sprite();
&&&_maskHome[maskName]&=&
&&var&w:Number&=&parent&==&stage&?&stage.stageWidth&:&parent.
&&var&h:Number&=&parent&==&stage&?&stage.stageHeight&:&parent.
&&var&g:Graphics&=&mask.
&&g.clear();
&&g.beginFill(maskColor,&maskAlpha);
&&g.drawRect(0,&0,&w,&h);
&&if(&showRect&)
&&&//利用Graphics重叠绘制会消去重叠区域像素的原理进行挖洞动作
&&&g.drawRect(showRect.x,&showRect.y,&showRect.width,&showRect.height);
&&g.endFill();
&&if(&!parent.contains(mask)&)
&&&parent.addChild(mask);
&&*隐藏全屏遮罩&
&public&static&function&hideScreenMask(maskName:String=&hotgirl&):void
&&var&mask:Sprite&=&_maskHome[maskName];
&&if(&mask&&&&mask.parent&)
&&&mask.parent.removeChild(mask);
&&*&显示一个高亮矩形边框,该边框会被添加到当前正在播放新手引导的组件上
&&*&@param&bounds&矩形边框显示位置。该矩形的参考系是当前正在播放新手引导的组件的父容器
&&*&@param&parent&&边框添加到的父容器。若留空,则父容器就等于GuideManager.indicatorContainer
&public&static&function&showRectBorder(&bounds:Rectangle,&parent:DisplayObjectContainer=null&):void
&&if(&!parent&)
&&&parent&=&
&&&if(&!parent&)
&&if(&!_border&)
&&&_border&=&new&Shape();
&&&_border.filters&=&[new&GlowFilter(0xff911b,&.8,&8,&8,&4,&2)];
&&if(&!parent.contains(_border)&)
&&&parent.addChild(_border);
&&_border.graphics.clear();
&&_border.graphics.lineStyle(1,&0xFFFF00);
&&_border.graphics.drawRect(0,&0,&bounds.width,&bounds.height);
&&_border.x&=&bounds.x;
&&_border.y&=&bounds.y;
&&*&隐藏边框&
&public&static&function&hideBorder():void
&&if(&_border&&&&_border.parent&)
&&&_border.parent.removeChild(_border);
//------------------------------------------private&functions--------------------------------------------------//
&private&static&function&doClear(step:IGuideComponent):void
&&if(&step&)
&&&step.guideClear();
&&hideBorder();
&&hideScreenMask();
&private&static&function&markFinish(sequence:int):void
&&if(&!_finishList[sequence]&)
&&&doClear(_guideQueue[sequence]);
&&&if(&onStepFinish&!=&null&)
onStepFinish(_dataArray[sequence]);
&&&_finishList[sequence]&=&
&/**&是否已启动新手引导&*/
&public&static&function&get&isSetUp():Boolean
&&return&_isSetUp;
&/**&新手引导是否正被暂停&*/
&public&static&function&get&paused():Boolean
&&return&_
&/**&当前执行到的步骤&*/
&public&static&function&get&currentStep():int
&&return&_currentS
GuideManager是本章代码最多也是最复杂的一个类,如果你现在看不懂,没关系,你只需要学会如何使用就可以了,毕竟这个类也不是我一朝一夕就写出来的,也是经过了反复的修改才造就的。下图演示了GuideManager的大致工作原理:
主要需要解释的地方有如下几个:
1.加载guide.xml后得到的新手引导数据先会被存放进一个数组中,之后该数组被作为实参传给GuideManager.setUp()方法供GuideManager使用。细心的朋友会注意到,GuideManager在调度每一步的新手引导执行顺序的时候是根据每一步在数组中的索引,而并不是按照每一步的sequence属性。换句话说,如果我guide.xml里面的XML标签中sequence属性的最小值不是1,而是100,那么该标签代表的步骤仍然是首先被播放的:
&step&sequence=&100&&instanceName=&ButtomButtonBar&&subSeq=&1&/&&!--第一步--&
&&step&sequence=&200&&instanceName=&Window1&&subSeq=&1&/&&!--第二步--&
&&step&sequence=&300&&instanceName=&Window1&&subSeq=&2&/&&!--第三步--&
&&step&sequence=&400&&instanceName=&ButtomButtonBar&&subSeq=&2&/&&!--第四步--&
因此,根据我的这种方法,在guide.xml里面配置的新手引导步骤的sequence属性不必遵循从0开始的连贯数值,这样就便于插入新的步骤数据。比如我在设计新手引导步骤时,考虑到两个步骤间有可能在今后会插入一些新的步骤,那么我就可以让这两个步骤的sequence值差距大一些:
&step&sequence=&1&&instanceName=&ButtomButtonBar&/&
&&step&sequence=&20&instanceName=&Window1&/&
2.由于涉及到新手引导的组件不可能在程序刚启动的时候都已经准备好展示新手引导(如实例化完成时、被添加到舞台上时、摆好位置时等等),所以我需要提供一个regist方法来让外部调用,在涉案组件准备好时才会被注册到引导管理器中。当一个组件被注册到引导管理器时,引导管理器会检查当前是否正在播放新手引导,若正在播放,则会检查当前播放到的引导步骤是否是由当前被注册组件负责展示的,若是,则马上开始展示当前引导
3.nextStep方法被调用时会让新手引导进入到下一步。若下一步的instanceName对应组件还未注册,则暂停引导,直到它被注册了再继续播放。若当前步是最后一步,则结束引导,执行卸载工作
有了guide.xml,有了IGuideComponent和GuideManager之后我们的新手引导基本框架已经搭建完毕,接下来就是需要在咱们的项目中实际运用上这套框架来试试看效果如何了。
在下面这个例子里,我希望能够引导用户逐个点击我游戏右下角摆放着的按钮条(ButtomButtonBar)中的四个按钮。于是我可以这样设计guide.xml表的内容:
&step&sequence=&0&&instanceName=&ButtomButtonBar&&subSeq=&1&/&
&&step&sequence=&1&&instanceName=&ButtomButtonBar&&subSeq=&2&/&
&&step&sequence=&2&&instanceName=&ButtomButtonBar&&subSeq=&3&/&
&&step&sequence=&3&&instanceName=&ButtomButtonBar&&subSeq=&4&/&
下面是文档类和ButtonBar的代码:
&*&&&新手引导测试
&*&&&Created&by&S_eVent
[SWF(backgroundColor=&0xFFFFFF&)]
public&class&GuideTest&extends&Sprite
&private&var&_uiContainer:Sprite&=&new&Sprite();
&private&var&_buttonBar:ButtonBar&=&new&ButtonBar();
&private&var&_globalVariables:GlobalVariables&=&GlobalVariables.
&private&var&_needGuide:Boolean&=&
&public&function&GuideTest()
&&initUI();
&&if(&stage&)
&&&onAdded(null);
&&&addEventListener(Event.ADDED_TO_STAGE,&onAdded);
&private&function&initUI():void
&&addChild(_uiContainer);
&&var&dp:Array&=&[];
&&for(var&i:&i&6;&i++)
&&&dp[i]&=&{label:&按钮&&+&(i+1)};
&&_buttonBar.dataProvider&=&
&&_uiContainer.addChild(_buttonBar);
&private&function&onAdded(&e:Event&):void
&&stage.scaleMode&=&StageScaleMode.NO_SCALE;
&&stage.align&=&StageAlign.TOP_LEFT;
&&stage.addEventListener(Event.RESIZE,&onResize);
&&onResize(null);
&&Message.stage&=&
&&if(&_needGuide&)
&&&loadGuideXML();
&private&function&onResize(&e:Event&):void
&&_globalVariables.stageWidth&=&stage.stageW
&&_globalVariables.stageHeight&=&stage.stageH
&private&function&loadGuideXML():void
&&var&loader:URLLoader&=&new&URLLoader();
&&loader.PLETE,&onGuideXMLLoadComp);
&&loader.load(&new&URLRequest(&guide.xml&)&);
&private&function&onGuideXMLLoadComp(e:Event):void
&&var&data:XML&=&XML(&(e.currentTarget&as&URLLoader).data&);
&&var&guideData:Array&=&[];
&&for&each(var&x:XML&in&data..step)
&&&guideData.push(&xml2Object(x)&);
&&guideData.sortOn(&sequence&,&Array.NUMERIC);
&&function&xml2Object(&xml:XML&):Object
&&&var&obj:Object&=&{};
&&&var&attributes:XMLList&=&xml.attributes();
&&&for&each(var&a:XML&in&attributes)
obj[a.name().toString()]&=&a.toString();
&&&return&
&&GuideManager.setUp(&guideData&);
&&GuideManager.stage&=&
&&GuideManager.onStepFinish&=&onStepF
&&GuideManager.onGuideFinish&=&onGuideF
&&GuideManager.start();
&private&function&onStepFinish(data:Object):void
&&Message.show(&您已完成第&&+&data.sequence&+&&步&);
&private&function&onGuideFinish():void
&&Message.show(&恭喜您,您已完全部新手引导步骤!&);
//---------------------------ButtonBar.as---------------------------------//
&*&&&按钮条
&*&&&Created&by&S_eVent
public&class&ButtonBar&extends&Sprite&implements&IGuideComponent
&/**&当ButtonBar中的某个按钮被按下时调用。该函数接收一个代表按下按钮索引号的int型参数&*/
&public&var&onBtnClick:F
&private&var&_dataProvider:A
&private&var&_buttons:Vector.&CustomButton&&=&new&Vector.&CustomButton&();
&private&var&_gap:Number&=&4;
&private&var&_globalVariables:GlobalVariables&=&GlobalVariables.
&public&function&ButtonBar()
&&super();
&&this.mouseEnabled&=&
&&GuideManager.register(this);
&&this.addEventListener(Event.ADDED_TO_STAGE,&onAdded);
&public&function&clear():void
&&var&btn:CustomB
&&while(&_buttons.length&&&0&)
&&&btn&=&_buttons.pop();
&&&if(&this.contains(&btn)&)
this.removeChild(&btn&);
//--------------------------------private&functions-----------------------------------//
&private&function&onAdded(&e:Event&):void
&&this.addEventListener(Event.REMOVED_FROM_STAGE,&onRemoved);
&&this.addEventListener(MouseEvent.CLICK,&onClick);
&&//侦听舞台尺寸发生变化事件
&&_globalVariables.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,&onPC);
&private&function&onRemoved(&e:Event&):void
&&this.removeEventListener(Event.REMOVED_FROM_STAGE,&onRemoved);
&&this.removeEventListener(MouseEvent.CLICK,&onClick);
&&_globalVariables.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE,&onPC);
&private&function&onClick(&e:MouseEvent&):void
&&var&btn:CustomButton&=&e.target&as&CustomB
&&if(&btn&&&&onBtnClick&!=&null&)
&&&onBtnClick(&_buttons.indexOf(btn)&);
&private&function&onPC(&e:PropertyChangeEvent&):void
&&if(&e.property&==&&stageWidth&&||&e.property&==&&stageHeight&&)
&&&this.x&=&_globalVariables.stageWidth&-&this.
&&&this.y&=&_globalVariables.stageHeight&-&this.
&&&if(&_guideTarget&)
var&maskArea:Rectangle&=&_guideTarget.getBounds(stage);
GuideManager.showScreenMask(maskArea);
&private&function&layout():void
&&var&crtW:Number&=&0;
&&for&each(var&btn:CustomButton&in&_buttons)
&&&btn.x&=&crtW;
&&&crtW&+=&btn.width&+&_
//-------------------------------get&/&set&functions----------------------------------//
&public&function&get&dataProvider():Array
&&return&_dataP
&public&function&set&dataProvider(value:Array):void
&&_dataProvider&=&
&&clear();
&&var&len:int&=&_dataProvider.length,&btn:CustomB
&&for(var&i:&i&&i++)
&&&btn&=&new&CustomButton(&_dataProvider[i].label&);
&&&addChild(&btn&);
&&&_buttons[i]&=&
&&layout();
&public&function&get&gap():Number
&&return&_
&public&function&set&gap(value:Number):void
&&layout();
//-------------------------------interface&implement----------------------------------//
&private&var&_instanceName:String&=&&ButtomButtonBar&;
&private&var&_guideTarget:CustomB
&public&function&guideProcess(data:Object=null):void
&&_guideTarget&=&_buttons[data.subSeq-1];
&&var&maskArea:Rectangle&=&_guideTarget.getBounds(stage);
&&GuideManager.showScreenMask(maskArea);
&&_guideTarget.addEventListener(MouseEvent.CLICK,&onNextStep);
&public&function&guideClear():void
&&//没什么好做的这里
&private&function&onNextStep(&e:MouseEvent&):void
&&e.currentTarget.removeEventListener(MouseEvent.CLICK,&onNextStep);
&&GuideManager.nextStep();
&public&function&get&instanceName():String
&&return&_instanceN
&public&function&set&instanceName(value:String):void
&&_instanceName&=&
对于文档类来说,它首先要做的,自然就是在需要启动新手引导的时候去加载guide.xml,之后将加载得到的XML数据转换成GuideManager能识别的Object数组并传递给GuideManager使用,之后马上开始新手引导的播放。
对于按钮条ButtonBar来说,要让它成为一个能够展示新手引导的组件,必须实现之前我们所说的IGuideComponent接口,然后在文件末尾处写上实现IGuideComponent接口的两个方法及一个属性。由于在我的项目中,ButtonBar只可能有一个实例,所以它的instanceName我就直接在它内部写死了。如果在项目中存在多个ButtonBar实例,那么我们需要在外部动态地为每个ButtonBar实例的instanceName属性赋值才行。在guideProcess方法中我需要写出轮到ButtonBar展示引导时会发生什么事情,在本例中,它要做的就是根据引导数据的子步骤sebSeq的不同而引导用户点击不同的按钮。为了方便,我这里就不加什么箭头来指示用户了,直接用GuideManager里面自带的全屏遮罩(实现原理可参考《》)来限制用户的点击范围为我需要让用户点击的区域。
那么上述代码最终的实现效果如下:
经过这个例子,差不多我们熟悉了一点这套新手引导框架的使用方式了,那么在教程中,我们将考虑新手引导的更多方面:如与服务器端进行同步的问题、新手引导组件注册时机不对导致引导箭头指向位置不正确的问题以及如何使用开放式引导的问题等等。如果遇到这些问题,你知道该如何解决吗?i&know&what&to&do....
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:337996次
积分:4254
积分:4254
排名:第7224名
原创:11篇
转载:559篇
评论:12条
(6)(3)(6)(1)(1)(12)(4)(9)(4)(2)(20)(6)(1)(2)(11)(27)(4)(4)(5)(4)(4)(12)(3)(22)(2)(1)(17)(5)(3)(4)(9)(1)(16)(5)(6)(4)(18)(51)(13)(8)(50)(23)(12)(8)(5)(7)(8)(18)(7)(11)(6)(17)(11)(7)(6)(5)(28)(5)}

我要回帖

更多关于 qt点击按钮界面切换 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信