游戏中,手游新手引导设计有什么好的设计模式吗

游戏的新手任务的作用是什么,是否一定有必要?新手任务设计需要注意什么?
我的图书馆
游戏的新手任务的作用是什么,是否一定有必要?新手任务设计需要注意什么?
【叶斌的回答(22票)】:
谢谢邀请,对于,特别是页游,尽量让玩家能轻松的开始享受游戏是很重要的。
“新手任务的作用是什么,是否一定有必要?”
答:针对新手的各种设计,目的是减少玩家挫折感,保证玩家能顺利了解游戏的主要内容,对游戏产生兴趣。所以针对游戏初期做设计是非常必要的。新手任务只是这些设计的其中之一。
【新手任务】这个定义不知道是从什么时候开始的。虽然未考证,但猜测是从网游兴起后出现的。特别是游戏免费道具消费的形式出现后,继续推动了游戏前期的设计。每个玩家都很宝贵,尽量让大家都能喜欢并留下来。所以出现了各式各样的引导,由于网络游戏,特别是页游的出现,大家普遍用数据统计的方式来分析寻找什么样的方式能留下最多的玩家。慢慢的将这些有数据支撑的方式形成了一套套方法。比如:自动寻路,引导指针,等……
“新手任务设计需要注意什么?”
和大家一样,我不喜欢没有头脑的跟着提示点鼠标。但又希望能轻松的玩游戏,享受游戏的乐趣。所以在做游戏时,尽量不采用强迫式引导,多在交互和游戏表现上花心思。好的设计应该像门把一样,谁看了都知道怎么用。
在参与以前,曾经做过一段时间的网页设计师。
那段时间看了《don't make me think》至今受益匪浅,书的链接如下:
游戏的类型有很多,很难一概而论需要注意什么。掌握知识,而不是学会某种方法。方法是为了解决特定的问题,而活用知识可以因地制宜的去找到属于自己的方法。我是这么想的。
PS:从早上忙到晚,在思绪浑浊时写了这篇帖子。写完时思绪居然清楚了许多:)
【郑金条的回答(5票)】:
关于新手教程的系列分析,以下内容援引自游戏邦编译和推荐的内容:
【清晰适度原则,更合理的方式是在体验中自然熟知而不是生硬的教学,或者匹配用户的既有知识轻车熟路】
1)Aki Jarvinen(Digital Chocolate)谈游戏指南设置对引玩家入门,保证用户留存率的重要性 (长篇)
2)GameUED刊文:中的新手引导
A,上篇,从产品功能角度分析引导内容
B,中篇,新手教程引导形式
C,下篇,新手引导检查
3)游戏新手教程中的Learning Time和gamer-tax需求
4)游戏新手教程中的误区设置分析
5)长文,Cityville前4级的游戏机制
附属解构:
A,长文,CityVille功能设置原理,上篇
B,长文,CityVille功能设置原理,下篇
6)长文,Gardens of Time体验指南分析
7)如何将规则的学习变成为游戏乐趣的一个环节
【知乎用户的回答(2票)】:
我又进来不负责任的聊游戏了。
看到某君说推崇WOW类的任务,没错!完全赞同,像我这样的重度角色扮演患者,对这类任务简直就是爱极了,WOW做任务从来不开插件的。
再回到国产游戏里看看。用户多数刚刚从田里割完稻子,带着两脚泥,进了网吧。然后点燃一支2块5的烟,眯着眼睛注册了一个小号,进入游戏。
然后呢?新手任务和引导干吗的?教他快速学会,目的是让他觉得好玩,然后留下。
喂!!!很多公司居然做了几个鼠标提示就结束了 0_0
在此,我要深深的谴责一下《传奇》这款游戏,当年封测一开,冲进去杀了几只稻草人,然后被蛤蟆搞死,蜡烛掉了,泥煤的,怎么这么黑!!。默默的关掉游戏回去继续玩龙族去了。
现在知道引导有多重要了吧?搞不好就关掉游戏不玩了。
那么能不能做的更好一点?当然可以。
线索任务+连环奖励+战斗力大增(相对刚出生的时候)。然后得到几个更高等级才能享受的道具;等你升级到的时候,免费送你几个花钱才能买到的道具,试吃(用)。(这招绝对是从毒贩子那里学来的)。
一直延续到你走出新手村,去发现更大的世界。
喔,好像忘了一个问题。注意事项,呃....
老的那一套不讲了。讲点新鲜的:
2. 意外惊喜
3. 出场一定要华丽,刺激
【知乎用户的回答(2票)】:
这个要具体内容具体分析,就像马里奥、俄罗斯,没有新手任务、没有新手指引,照样可以玩。
又例如WOW,我就觉得新手引导做得不好,当我第一次进去,世界太庞大,你根本不知道要做些什么,哪怕有提示你依然觉得很别扭。
这个新手任务应该是包括新手指引的吧?
我一般会把新手指引和新手任务挂钩在一,前者是让玩家了解这个功能,后者是让玩家参与和熟悉这个功能,在作用上有点差异。
我还没入行的时候,就有很多开发者跟我说:在新手指引上,要将玩家当作小孩对待,因为他们很傻逼。(好吧,这句话我保持中立)
1、我玩过一些游戏,某些功能如果不是别人告诉我,我根本不知道,这说明引导做得不好。
2、某个页游,新手引导(只要点击鼠标就可以了),我点鼠标30分钟还没完,我决定关掉这个游戏。
3、连连看这个游戏:
我:这么简单的游戏还要教程?别2了!爸:这游戏怎么玩的?我:。。。
咳咳,总的来说,是否有必要加入新手任务,主要还是看目的。
新手任务设计需要注意什么?先确定游戏的受众群体,针对这个群体设计内容。把握新手教程的目的,不是为了做而做,而是要达到目的。控制节奏,不要太频繁,降低用户的反感。分段式:对于太复杂的功能,不用一次性告诉用户,可以逐步,分时段的完成。第一次式:对于简单又不是很重点的功能,可以在玩家第一次使用这个功能时,才触发针对这个功能的新手任务开放式:当达到一定等级/条件,才触发这个教程。
【feiyu的回答(3票)】:
看了回答,答题的朋友大多在分享页游和端游的新手教程经验,类似三消、跑酷、捕鱼类休闲手游也是需要新手教程,也和留存密切相关。
休闲游戏就算同类型游戏,不同游戏也有其特色,新手教程要引导用户发现其特色之处,以及遇到特色之处有新手引导让用户更便于理解和操作。
举例来说,我们团队上款游戏最初的新手教程比较生硬,先出现虚拟角色来说明某个武器的用途,然后出现小手来指引用户点击相关按钮来发射,经过设计和文案优化,最后保留了5步新手教程,每步说明文字在20个字以内,已经算是简单明了的介绍特色之处和基本操作了。上线后一般次日留存在45%上下浮动。
从用户数据来看,新手教程期间流失的用户较多,因为等级为1的用户群和等级为2的用户数量相差不少,这个差的数量就是在初期流失的用户,他们根本没有升到第2级。
于是考虑如何修改新手教程兼顾两种用户,A用户是玩过本类型游戏的,B用户是新手玩家未玩过本类型游戏。说实话之前的新手教程对于A用户有点多余。
重新观察完全没有玩过我们游戏的用户在有与没有新手教程的情况下的操作的差异,及玩过同类游戏的用户在没有新手教程的情况下如何操作。
得到以下结果:
1、B用户在没有新手教程的情况下,靠自己摸索可以在30秒内掌握最基本的初级操作(属于第一步新手教程告知的内容)。特色之处要玩很久才能发现。
2、B用户在有新手教程的情况下,会花更多的时间来掌握基本操作,因为他们要仔细阅读说明文字,并且要理解说明文字,才会做下一步操作。5步新手教程加起来基本都超过了160秒。
3、最初的新手教程对于A用户产生了阻扰的作用,基本经过新手教程至少也要90秒以上。
根据以上结果,我们重新优化了新手教程,毕竟之前的5步新手教程已经非常能简单明了的引导用户,我们判断流失用户是因为感觉太繁琐,而不是看不懂。
具体优化设计是在最初的5步新手教程上做以下检测及设置:
1、用户进入游戏后,如果20秒内检测到用户未发生任何操作,则出现第一步新手引导。
2、用户进入游戏后,如果20秒内发生了符合新手引导1的点击操作。那么将不出现新手引导1,等60秒后出现新手引导2。
3、如果用户进入游戏后直接进行了新手引导2,那么新手引导1不出现(因为新手引导3包含了初级操作的新手引导1)
如果新手引导2做完后过30秒未出现新手引导3的操作,则出现新手引导3的引导点击。
4、用户经过了新手引导的1、2、3步骤之后,在60秒后出现新手引导4
5、新手引导4是需要游戏自动给用户充满一种特殊能量并介绍能量如何获取,属于主动展示,所以新用户进来后是不可能越开1、2、3直接进行出现第4步。
6、经过新手引导4获取能量之后,新手引导5是引导用户发射特殊武器,以前是纯演示,新手引导5结束后就有一个正式开始游戏的按钮。这次将开始游戏按钮取消,发射特殊武器之后获取的资源也归用户所有了。
经过这些调整之后,新版本上线之后,当天1500个新用户的次日留存提高到了55%。(用户留存统计数据来自友盟)用户等级1和等级2的数量差距也缩减了不少。
多观察实际用户对于游戏的操作,从中找到合理的设计方案,设计完之后再找用户验证方案是否顺利的达到目的。最后就是上线后观察用户行为数据再次做出调整,基本上就能把新手教程做到位了。
【叶云凡的回答(1票)】:
对于游戏中的新手任务,我有以下几个观点:
1.新手任务的主要作用是引导,而不是任务。
2.多给玩家一些参与,而不是机械的根据提示点击按钮。很多游戏新手任务搞完后还是完全不知道该怎么操作。
3.循序渐进。不要一次性把所有指引都搞出来,每一个引导要等到玩家确实需要时再出现。
4.必须设置为可跳过,并可恢复!这一点很重要,我经常玩一些游戏,一进来就枯燥繁琐的新手任务,还无法跳过,直接删游戏。
【知乎用户的回答(0票)】:
1. 新手任务的作用是让这一游戏类型的新手掌握基本玩法,并介绍本款游戏和其他类似游戏在操作和玩法上的不同之处。比如我可能是个深度欧美RPG玩家,神马博德之门辐射老滚生化奇兵通吃,但是从没玩过一款RTS游戏,那么对于星际我就是新手,我首先要知道这种游戏总体上怎么玩,然后是这款游戏具体怎么玩。
2. 对大型游戏有必要。不是每个人都广泛涉猎游戏,设计一些教程式的,一步步地带着玩家先玩一两局的任务是很有必要的。但是对于游戏模式非常简单,只有有限的几种操作,小品式的游戏,就没有必要了。
3. 需要注意什么?
a) 依次介绍基础的界面布局和游戏玩法。常用的功能要介绍全,高级功能要提一下但不要太深,因为对于新手而言过早介绍高级功能也没有意义。可以采用“用到时再介绍”这种方法。
b) 要能由用户选择是否跳过,和是否重新演示一次。还是上面说的,一个资深RPG玩家进入WOW之后基本上驾轻就熟,提示他叹号是任务,红色是血条这种毫无意义。要允许用户跳过。但是为了防止部分玩家误操作,应该允许玩家随时重新打开教程。
【徐贝的回答(0票)】:
就是从头开始让你体验自动寻路 做完新手任务 你发现 还是什么都没玩 除了数据外
【杨国庆的回答(0票)】:
图片源自Game Designer 图片源自Game Designer
初入游戏时,玩家是个不折不扣的菜鸟(Newbie),除了从把他拉进坑来的哥们兴高采烈得说这游戏怎么样怎么样得到的只言片语以外,对这个游戏的真是体验为零。
根据Amy Jo KimJ的The Player's Journey,我们玩游戏一般都要经过这么几个阶段:
Onboarding:这个新手阶段让玩家明白这个游戏是干嘛的,以及基础的规则和操作。Habit-Building:这个阶段就看游戏本身是否有吸引力了,玩家在不断摸索中逐渐理解这个游戏,最后成为熟练玩家。Mastery:最后这个阶段玩家已经修成正果,对整个游戏了如指掌。 我认为新手任务的作用就在于Onboarding这个阶段,通过简单易操作的任务给予玩家积极的反馈,帮助玩家建立信心,顺利渡过游戏的“畏惧”期。
游戏中失败是很常见的事情,而这样的challenge正是游戏令人激动的地方。不过,在Onboarding阶段,游戏设计应该是”想失败都难“,轻松愉快的渡过新手阶段,让玩家能更深层次得体验游戏带来的乐趣。
——————————————————————————————————————————
拙见,欢迎指正交流。
【周瑶的回答(0票)】:
那要看什么游戏。如果我出一款游戏,砍掉任务砍掉NPC砍掉现成环境。让玩家去构造一个世界。当然,每个人都会给你一个初始工具,以及各种各样的资源!玩家之间可以通过协作完成一项伟大的发明,它可以是仿现实世界的,也可以是凭空产生的。玩家还将体会到文明的发展,如何对抗原始怪物。不需要等级,只需要技能熟练度。每个人都能实现自己在现实中无法实现的梦想,是个体更是群体。自由度100,无任务无任何强制性约束。…等等,我好像把我一个大计划展开了。答不对题了T^T
【眼镜的回答(0票)】:
具有一定的操作教学作用,趣味性很重要,而且要直观简单易懂。
【付强的回答(0票)】:
想想袁腾飞讲的历史课和你当年的历史老师的差距。
【陈大脸的回答(0票)】:
业界好像有一种说法,每多一步新手引导,就多流失一群用户。新手引导要走,因为一开始不会玩,但是不能多,因为越多说明游戏好烦,我玩个游戏还要记住那么多步骤多累啊,果断抛弃~
【陈十八的回答(0票)】:
写这些东西不应该玩家来吗?
首先,我是一个玩家;其次,我玩过一段页游。
特别,新意,就像各种无节操广告的宣传,新手任务,再无节操一点吧!
【唐仪的回答(0票)】:
关于有个哥们写马里奥的例子,忍不住吐槽一下。
新手任务初衷是解决上手问题,这样就有一个基本的界定点:你的游戏的操作是否足够简单易学?同样能保持足够的乐趣?这要求本身是相悖的,所以游戏发展这么多年,能够被称作简单到不需指引又富有乐趣的也就那么几个(比如马里奥),显然设计这样的产品需要极其高超的技艺。
那么,这么多做游戏的,能够达到这个水平的明显是少之又少。实力不足怎么办?添加更多的系统,加强表现,既然无法保证在玩法质量上跟你比,就要从玩法数量上超过你。于是各种玩法就多了,然后各种规则的重新设计和调整,最终做出一个操作很复杂的产品,大部分的小白都无法入手,咋办?新手教程!!!!
其实马里奥严格来讲也算有教程的,就是游戏中各种机制明显的反馈:跳过躲避,踩踏得分……因为它足够简单,所以反馈机制可以做的很好。但一个复杂的网络游戏要做到如此明显易懂,花费的精力就不是一个量级的了。
为了新手指引的精确进行,当然就要进行限定行动范围的考虑,如功能分阶段开放,用来严格控制产出和操作行为,使玩家总能在预订的时间或等级节点遇到需要遇到的事情。这需要主策划从一开始就要对整个游戏有个清晰而准确的规划,程序、策划、美术通力配合才能达到这样的效果。但是国内的现状是无法满足的,要么水平到了没有权限,要么权限有了水平不够,要么策划OK程序不行,要么技术OK时间来不及……各种蛋疼的原因导致你最终选择简单粗暴的解决问题:全程严格控制,不允许有一部的额外操作,将流程的顺畅提高到最高,而将乐趣降低至最低。
同样还有一个不可规避的原因:我们已经不是靠出手拷贝赚钱了,都是靠卖道具赚钱,游戏本身变成了一个自由出入的大超市,打折促销开始取代乐趣成为盈利的基本策略,市场的浮躁、各种晒数据导致绝大多数的投资者不淡定了,有机会证明自己的游戏很有乐趣且能赚打钱的人太少了,so,只能向资本妥协,先证明自己能赚钱(当然,这也是作为企业员工的基本素养,没有人有责任拿钱让你打水漂),然后证明自己的游戏有乐趣(往往大部分人在富起来以后出于盈利考虑就失去了这一目标)。怪圈就形成了,所以我们现在也只能继续这么干,直到整个行业的所有从业者意识到:不改变就灭亡。然后从废墟建立新的秩序。
忽然发现写的有点偏,权作发泄吧。
【李创奇的回答(1票)】:
固执地认为如果需要明显的新手任务的工具类应用是失败的
推崇wow式的游戏类任务式引导
【知乎用户的回答(0票)】:
我来吐槽下。
最近很关注游戏新手任务这方面的问题。因为在找产品,可是每次在体验产品的时候,碰到无尽的新手任务,真是TMD烦啊,最重要的是,我真的没有在新手任务中有体验到目的和意义何在啊。什么文字内容都不看一直点下一步……一直可以让你点1个小时以上(最多可以点多久没测试过)。
对我来说,最好的新手任务就是可以在边做任务的时候边能熟悉游戏的一些功能和玩法。
可是现在很多游戏(页游),基本上新手任务就是让你不停的打怪,在NPC接任务交任务……区别就是打怪的名字和数量的区别……
页游的前期流失率是非常高的,以我理想的想法是能在游戏的初期(10分钟内)就能体验到游戏的一些有趣之处,或者至少能让玩家熟悉游戏的功能和玩法。可是无尽且NC的新手任务的确是毁人不倦。
今天特地去体验了下《神仙道》,这是一款公认的经典游戏,在内测阶段我已经有过短暂的接触,觉得前期的引导非常好,细节非常棒。连我这个见到回合制就要吐的人至少玩了2天。时过已久,为了证明经典的游戏新手任务不会太NC的想法再次体验了半小时。稍微有点点失望,进一个又一个洞,上一个又一个山……尽管没有其他游戏那么让我烦,但也的确离我心中的的理想状态稍差一步,觉得不应该有那么多无意义的打怪。难道目的就在于升级和获得铜币么?
P.S. 新手任务应该可以设置成跳过。以免老玩家要一次又一次的做得心烦。
关于这个问题,非常希望 能和大家一起交流下,让我们能学习下。
馆藏&67959
TA的推荐TA的最新馆藏
喜欢该文的人也喜欢&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 游戏通用的新手引导模块的开发模式教程.
目前提供cocos2d-js版的,等有时间我再把其他语言的版本放出来.(注:如果需要多个引导同时存在,或者非模态方式,需要修改配置)
&目的:其实我是一个很懒的人,所以设计目的我优先考虑的是让Guide通用以后做的所有的游戏,整个Guide模块开发周期(3天+调试=一周),剩下的工作.....=&只需要配置上控件就好。
&开发思路中:Guide模块与游戏本身逻辑几乎分离,可完全根据配置来实现新手引导(同时可以多款游戏)。
&我先大概介绍下实现的功能包含哪些内容:
(1):兼容 引导时候的点击,拖动,坐标变化,放大缩小等。
(2):兼容 按钮点击后服务端短线(提示重链)等。
(3):兼容 几乎所有引导中出现的游戏异常和问题。
(4):不兼容 如果考虑多个引导同时引导,需要把单例给改掉,不用getInstance方法,ModalLayer也需要修改。
//@@@@@@@GuideComponent.js@@@@@@@@@@@@@
&一.所有引导用到的控件定义 GuideComponent.js 这里的变量关联模块中的控件
var GuideComponent = {};//整个游戏运行过程中获取控件的变量
GuideComponent[&Scene_Main&]
//主城(模块)
GuideComponent[&Scene_Recruit&]
//招募(模块)
GuideComponent[&Scene_Team&]
//队伍(模块)
GuideComponent[&Scene_TeamEdit&]
//队伍编辑(模块)
GuideComponent[&Scene_Explore&]
//剧本(模块)
//以下是单步新手引导的配置 GuideComponent[&所在模块名&][&控件名称&]
//(注:这里的控件,只要在相关的模块代码中关联就好,1.初始化的时候赋值 2.关闭模块时销毁=null)
//单个引导的控件
GuideComponent[&Scene_Main&][&recruit&]
GuideComponent[&Scene_Recruit&][&btn&]
GuideComponent[&Scene_Main&][&team&]
GuideComponent[&Scene_Team&][&btn&]
GuideComponent[&Scene_TeamEdit&][&card&] =
GuideComponent[&Scene_Main&][&explore&]
GuideComponent[&Scene_Explore&][&city&]
GuideComponent[&Scene_Explore&][&item&]
GuideComponent[&Scene_Explore&][&go&]
//@@@@@@@@@@@@@@GuideTask.js&
@@@@@@@@@@@@@
&span style=&font-size:24&&/**
* Created by cx on 14-3-20.
*这里是引导的详细配置,可以放在服务端给客户端读取,也可以独立配置再客户端
var GuideTaskInfo = [];
//第1步引导
GuideTaskInfo[0] = {};
GuideTaskInfo[0][&arrowRect&] = &left&;//up,left,right,down 箭头方向
GuideTaskInfo[0][&shape&] = &circle&;//circle,rect//引导区域的遮罩形状
GuideTaskInfo[0][&moduleName&] = &Scene_Main&;//选项框(模块名称)
GuideTaskInfo[0][&componentName&] = &recruit&;//控件名称(二级选项,控件名称)
GuideTaskInfo[0][&touchEvent&] = &click&;//促发事件 click,move
GuideTaskInfo[0][&step&] = &1&;//步骤id
GuideTaskInfo[0][&desc&] = &引导时显示的描述@@@@@@!&;//描述
GuideTaskInfo[0][&descPos&] =//描述框坐标
GuideTaskInfo[0][&isShowDragArrowView&] =//显示滑动图片
GuideTaskInfo[0][&dragArrowViewRotate&] = 0;//滑动指向图片的旋转角度
GuideTaskInfo[1] = {};
GuideTaskInfo[1][&arrowRect&] = &up&;//up,left,right,down
GuideTaskInfo[1][&shape&] = &rect&;//circle,rect
GuideTaskInfo[1][&moduleName&] = &Scene_Recruit&;//选项框(模块名称)
GuideTaskInfo[1][&componentName&] = &btn&;//控件名称(二级选项,控件名称)
GuideTaskInfo[1][&touchEvent&] = &click&;//促发事件 click,move
GuideTaskInfo[1][&step&] = &2&;//步骤id
GuideTaskInfo[1][&desc&] = &点击此处,可招募将士。&;//描述
GuideTaskInfo[1][&descPos&] =//描述框坐标
GuideTaskInfo[1][&isShowDragArrowView&] =//显示滑动图片
GuideTaskInfo[1][&dragArrowViewRotate&] = 0;//滑动指向图片的旋转角度
GuideTaskInfo[2] = {};
GuideTaskInfo[2][&arrowRect&] = &left&;//up,left,right,down
GuideTaskInfo[2][&shape&] = &circle&;//circle,rect
GuideTaskInfo[2][&moduleName&] = &Scene_Main&;//选项框(模块名称)
GuideTaskInfo[2][&componentName&] = &team&;//控件名称(二级选项,控件名称)
GuideTaskInfo[2][&touchEvent&] = &click&;//促发事件 click,move
GuideTaskInfo[2][&step&] = &3&;//步骤id
GuideTaskInfo[2][&desc&] = &刚招募的将士必须先编队,以整军备战!&;//描述
GuideTaskInfo[2][&descPos&] = cc.p(winSize.width/2, winSize.height/2+100);//描述框坐标
GuideTaskInfo[2][&isShowDragArrowView&] =//显示滑动图片
GuideTaskInfo[2][&dragArrowViewRotate&] = 0;//滑动指向图片的旋转角度&/span&
//@@@@@@@@@@@@@@ Guide.js最重要的文件再这里 @@@@@@@@@@@@
&span style=&font-size:24&&/**
* Created by cx on 14-3-17.
 * 新手引导
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Guide @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Guide @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Guide @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
var Guide = function(){
//Guide.getInstance().showModalGuide(GuideComponent[&Scene_Main&][&recruit&]);
this.currExtP =//ext point
this.guideTask =
this.currStep =//guideTaskStep:1,2,3,4,5
this.guideLayer = new GuideLayer();//GuideLayer.create();
this._currComponent =
this.isDebugTest =
this.runing =
this.isRuning = function(){
return this.
* 执行下一个步骤
this.runNextStep = function(){
cc.log(&run next step@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&+(this.currStep+1));
this.runing =
if(this.isDebugTest){
this.stopGuide();
//这里执行...
this.allowTableViewDrag();//允许其继续使用
++this.currS
if(this.currStep&this.guideTask.length){
this._runGuide();
this.stopGuide();
if(this.endCallBack!=null){
this.endCallBack();
cc.log(&执行下一步骤@@@@@@@@@@@@@&);
this.endCallBack=
* w完成引导回调
this.setEndGuideCallBack = function(_endCallBack){
this.endCallBack = _endCallB
* 停止引导
this.stopGuide = function(){
this.unRegisterSchedule();
this.hideModalGuide();
this.runing =
G.ISGUIDE =
* 运行Guide
* param:数据格式Array
* GuideTaskInfo[0] = {};
* GuideTaskInfo[0][&arrowRect&] = &down&;//up,left,right,down
* GuideTaskInfo[0][&shapre&] = &circle&;//circle,rect
* GuideTaskInfo[0][&moduleName&] = &Scene_Main&;//选项框(模块名称)
* GuideTaskInfo[0][&componentName&] = &recruit&;//控件名称(二级选项,控件名称)
* GuideTaskInfo[0][&touchEvent&] = &click&;//促发事件 click,move
* GuideTaskInfo[0][&step&] = &1&;//步骤id
this.runGuide = function(guideTaskData){
if(guideTaskData==null){
this.registerSchedule();//开始引导...
if(!(guideTaskData instanceof Array)){
cc.log(&runGuide() param must Array&);
if(guideTaskData.length&=0){
cc.log(&runGuide() guideTaskData is NULL&);
this.guideTask = guideTaskD
this.currStep = 0;//from 0
this._runGuide();
* GuideTaskInfo[0] = {};
* GuideTaskInfo[0][&arrowRect&] = &down&;//up,left,right,down
* GuideTaskInfo[0][&shapre&] = &circle&;//circle,rect
* GuideTaskInfo[0][&moduleName&] = &Scene_Main&;//选项框(模块名称)
* GuideTaskInfo[0][&componentName&] = &recruit&;//控件名称(二级选项,控件名称)
* GuideTaskInfo[0][&touchEvent&] = &click&;//促发事件 click,move
* GuideTaskInfo[0][&step&] = &1&;//步骤id
* GuideTaskInfo[0][&descPos&] = &ccp(x,x)/null&;//描述框坐标
* GuideTaskInfo[0][&isShowDragArrowView&] =//显示滑动图片
* GuideTaskInfo[0][&dragArrowViewRotate&] = 180;//滑动指向图片的旋转角度
this.tempComponentPositionX =
this.tempComponentPositionY =
this.isContinueFind =
this._runGuide = function(){
if(this.currStep&=this.guideTask.length){
//引导结束-执行相关操作
this.stopGuide();
var taskInfo = this.guideTask[this.currStep];
if(!GuideComponent.hasOwnProperty(taskInfo[&moduleName&]) || !GuideComponent[taskInfo[&moduleName&]].hasOwnProperty(taskInfo[&componentName&])){
cc.log(&引导控件不存在:Val:&+taskInfo[&moduleName&]+&=&:&+taskInfo[&componentName&]);
this.hideModalGuide();
if(JsInterface.getInstance().getDebug()){
cc.log(taskInfo[&moduleName&]+&=&:&+taskInfo[&componentName&]);
var component = GuideComponent[taskInfo[&moduleName&]][taskInfo[&componentName&]];
if(component==null){
if(this.tempComponentPositionX==component.getPositionX() || this.tempComponentPositionY==component.getPositionY()){
if(this.tempComponentPositionX!=null){
this.tempComponentPositionX = component.getPositionX();
this.tempComponentPositionY = component.getPositionY();
this.showModalGuide(component,taskInfo.shape,taskInfo.touchEvent,taskInfo.arrowRect,taskInfo.desc,taskInfo.isShowDragArrowView,taskInfo.dragArrowViewRotate,taskInfo.descPos);
this.hideModalGuide = function(){
if(this.guideLayer.getParent()){
this.guideLayer.getParent().removeChild(this.guideLayer);
* touch事件回调
this.touchEventCallBack = function(selfObj){
selfObj.runNextStep(Guide.getInstance());
this.denyTableViewDrag = function(){
//cc.log(&deny@@@@@@@@@&);
var pxparent = this._currComponent.getParent();
while(pxparent){
if(pxparent instanceof cc.TableView){
pxparent.setMoveTouchEnable(false);
pxparent = pxparent.getParent();
this.allowTableViewDrag = function(){
//cc.log(&allow@@@@@@@&);
var pxparent = this._currComponent.getParent();
while(pxparent){
if(pxparent instanceof cc.TableView){
pxparent.setMoveTouchEnable(true);
pxparent = pxparent.getParent();
* component:控件(不可为空...)
* shapre:形状
* touchEvent:touch事件
* arrowRect:箭头方向
* desc:描述
* descPos:ccp()/null 描述的坐标
this.showModalGuide = function(component,shape,touchEvent,arrowRect,desc,isShowDragArrowView,dragArrowViewRotate,descPos){
if(this.isDebugTest){
this.registerSchedule();
shape = typeof shape == &undefined& ? GuideLayer.SHAPE_TYPE_RECT :
touchEvent = typeof touchEvent == &undefined& ? GuideLayer.TOUCH_EVENT_TYPE_CLICK : touchE
arrowRect = typeof arrowRect == &undefined& ? GuideLayer.ARROW_RECT_TYPE_LEFT : arrowR
desc = typeof desc == &undefined& ? && :
isShowDragArrowView = typeof isShowDragArrowView == &undefined& ? 0 : isShowDragArrowV
dragArrowViewRotate = typeof dragArrowViewRotate == &undefined& ? 0 : dragArrowViewR
if(component!=null){
//cc.log((component[&getContentSize&]==undefined)+&==========&);
if(component==null){
//cc.log(&控件未获取成功..........&);
this.isContinueFind =
this.runing =
this.isContinueFind =
//设置控件的回调函数
component[Guide.CALLBACK_FUNCKEY] = ponentCallBackF
this._currComponent =
this.denyTableViewDrag();
this.getExtP(component);
var size = component.getContentSize();
if(this.guideLayer.getParent()){
this.guideLayer.getParent().removeChild(this.guideLayer);
var scene = cc.Director.getInstance().getRunningScene();
scene.addChild(this.guideLayer,1500);
this.guideLayer.showModalGuide(shape,component,this.currExtP,size.width,size.height,touchEvent,arrowRect,desc,isShowDragArrowView,dragArrowViewRotate,descPos);
* 控件自身出发后回调
ponentCallBackFunc = function(){
Guide.getInstance().runNextStep();
this.getCurrScale = 1;
this.getExtP = function(cpm){
this.currExtP = cc.p(0,0);
var parentC =
var winSize = cc.Director.getInstance().getWinSize();
var preSize =
var isFirst =
this.getCurrScale = 1;
while(parentC){
var parentx = parentC.getPositionX();
var parenty = parentC.getPositionY();
var thisanchor = parentC.getAnchorPoint();
var selfCurrCpSize = parentC.getContentSize();
var componentScale = parentC.getScale();
if(componentScale!=1){
this.getCurrScale *= componentS
//这里特殊处理
if(!(parentC instanceof cc.Layer)){
parentx -= thisanchor.x*selfCurrCpSize.//ok
parenty -= thisanchor.y*selfCurrCpSize.
this.currExtP.x +=//ok
this.currExtP.y +=//ok
parentC = parentC.getParent();
this.getPxx = function(){
this.currExtP = cc.p(0,0);
var parentC =
var winSize = cc.Director.getInstance().getWinSize();
var preSize =
while(parentC){
var parentx = parentC.getPositionX();
var parenty = parentC.getPositionY();
var thisanchor = parentC.getAnchorPoint();
var selfCurrCpSize = parentC.getContentSize();
parentx -= parentC.getAnchorPoint().x*selfCurrCpSize.//ok
parenty -= parentC.getAnchorPoint().y*selfCurrCpSize.//ok
if(preSize==null){
preSize = selfCurrCpS
}else if(preSize.width == selfCurrCpSize.width && preSize.height == selfCurrCpSize.height){
parentx += parentC.getAnchorPoint().x*selfCurrCpSize.
parenty += parentC.getAnchorPoint().y*selfCurrCpSize.
preSize = selfCurrCpS
this.currExtP.x +=//ok
this.currExtP.y +=//ok
parentC = parentC.getParent();
this.runRelocalGuideCount = 0;
this.update = function(){
//cc.log(&update guide schedule&);
if(this.isContinueFind==true){
this._runGuide();
this.hideModalGuide();
cc.log(&一直运行.....&);
if(!this.guideLayer.getParent()){
var scene = cc.Director.getInstance().getRunningScene();
scene.addChild(this.guideLayer);
if(this.runRelocalGuideCount++ & 30){
this._runGuide();
this.runRelocalGuideCount = 0;
//动作播放.,..
this.guideLayer.controllerArrowMove();
* 注册监听
this.registerSchedule = function(){
cc.Director.getInstance().getScheduler().scheduleUpdateForTarget(this,0,false);
* 取消监听状态
this.unRegisterSchedule = function(){
cc.Director.getInstance().getScheduler().unscheduleAllCallbacksForTarget(this);
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ GuideLayer @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ GuideLayer @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ GuideLayer @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
var GuideLayer = cc.Layer.extend({
res_arrow : &res/guide/arrow.png&,//箭头
res_descbg : &res/guide/descbg.png&,//描述框
res_drag_arrow : &res/guide/drag_arrow.png&,//拖动的箭头
selfColorLayer:null,
pClip:null,
currPosition:null,
currSize:null,
_touchEvent:null,
_arrowRect:null,
_desc:null,
_isShowDragArrowView:null,
_dragArrowViewRotate:null,
spArrow:null,
spDescbg:null,
spDragArrow:null,
descPoint_x:0,//描述x坐标
descPoint_y:0,//描述y坐标
descLable:null,
arrowMoveDistance:15,//
descTextColor:cc.c3b(0,0,0),
currComponent:null,//当前控件
ctor:function(){
this._super();
this.retain();
var winSize = cc.Director.getInstance().getWinSize();
this.selfColorLayer = cc.LayerColor.create(cc.c4f(0,0,0,150));
this.pClip = cc.ClippingNode.create();
this.pClip.setVisible(true);
this.pClip.setInverted(true);
this.pClip.addChild(this.selfColorLayer);
this.addChild(this.pClip);
this.spArrow = cc.Sprite.create(this.res_arrow);//箭头
this.spDescbg = cc.Sprite.create(this.res_descbg);//描述
this.spDragArrow = cc.Sprite.create(this.res_drag_arrow);//拖动提示试图
this.spDragArrow.setAnchorPoint(cc.p(0,0.5));
this.spDescbg.setPosition(winSize.width/2,winSize.height/2);
this.spDragArrow.setPosition(500,300);
this.spArrow.setPosition(500,300);
this.spDragArrow.setVisible(false);
this.addChild(this.spArrow,10);
this.addChild(this.spDescbg,15);
this.addChild(this.spDragArrow,5);
this.drawShape(GuideLayer.SHAPE_TYPE_CIRCLE,cc.p(0,0),1,1);
var descLableSizeHeight = 180;
this.descLable = cc.LabelTTF.create('', &Arial&, 33, cc.size(360,descLableSizeHeight), cc.TEXT_ALIGNMENT_LEFT, cc.VERTICAL_TEXT_ALIGNMENT_CENTER);
this.descLable.width = 50;
this.descLable.setAnchorPoint(cc.p(0, 0));
this.descLable.setPosition(cc.p(180, this.spDescbg.getContentSize().height-descLableSizeHeight-10));
this.descLable.setColor(this.descTextColor);
this.spDescbg.addChild(this.descLable);
this.spDescbg.setVisible(false);
* 模态引导
* touchEvent:click/touch
showModalGuide:function(GuideLayer_SHAPE_TYPE,component,componentPoint,p_width,p_height,touchEvent,arrowRect,desc,isShowDragArrowView,dragArrowViewRotate,descPos){
this.currComponent =
this._touchEvent = typeof touchEvent==&undefined& ? &click&:touchE
this._arrowRect = typeof arrowRect==&undefined& ? &down& : arrowR
this._desc = typeof desc==&undefined& ? && :
this._isShowDragArrowView = typeof isShowDragArrowView == &undefined& ? 0:this._isShowDragArrowV
this._dragArrowViewRotate = typeof _dragArrowViewRotate == &undefined& ? 0:this._dragArrowViewR
//scale start
if(typeof component!=&undefined&){
if(Guide.getInstance().getCurrScale!=1){
p_width = p_width*Guide.getInstance().getCurrS
p_height = p_height*Guide.getInstance().getCurrS
if(Guide.getInstance().getCurrScale&1){
componentPoint.x -= (p_width-component.getContentSize().width)/2;
componentPoint.y -= (p_height-component.getContentSize().height)/2;
}else if(Guide.getInstance().getCurrScale&1){
componentPoint.x += (component.getContentSize().width-p_width)/2;
componentPoint.y += (component.getContentSize().height-p_height)/2;
//scale end
this.currPosition = componentP//
this.currSize = cc.size(p_width,p_height);//
this.drawShape(GuideLayer_SHAPE_TYPE,componentPoint,p_width,p_height,component);
this.setArrowRect(arrowRect,componentPoint,p_width,p_height);
this.showDragArrowView(componentPoint,p_width,p_height,isShowDragArrowView,dragArrowViewRotate);
if(this._desc!=&&){
this.spDescbg.setVisible(true);
this.descLable.setString(desc);
if(descPos!=null){
this.spDescbg.setPosition(descPos);
var winSize = cc.Director.getInstance().getWinSize();
this.spDescbg.setPosition(cc.p(winSize.width/2,winSize.height/2));
this.spDescbg.setVisible(false);
cc.log(&添加了@@@@@@@&);
* 判断是否点钟本身
isTouchSelf:function(touchPoint,component,anchorX,anchorY){
anchorX = typeof anchorX==&undefined& ? 0 : anchorX;
anchorY = typeof anchorY==&undefined& ? 0 : anchorY;
var componentPoint = component.getPosition();
var componentSize = component.getContentSize();
var minx = componentPoint.x-componentSize.width*anchorX;
var maxx = minx+componentSize.
var miny = componentPoint.y-componentSize.height*anchorY;
var maxy = miny+componentSize.
if(touchPoint.x&=minx && touchPoint.y&=miny && touchPoint.x&=maxx && touchPoint.y&=maxy){
//判断是否点中描述窗口
isTouchDescBg:function(t_point){
//如果选中描述窗口,则隐藏描述窗口
var descPoint = this.spDescbg.getPosition();
var minx = t_point.x;
var maxx = this.spDescbg.getContentSize().width+t_point.x;
onTouchBegan:function(pTouch,pEvent){//this._touchEvent
var thisPoint = pTouch.getLocation();
var minx = this.currPosition.x;
var miny = this.currPosition.y;
var maxx = this.currPosition.x+this.currSize.
var maxy = this.currPosition.y+this.currSize.
if(this.spDescbg.isVisible() && this.isTouchSelf(thisPoint,this.spDescbg,this.spDescbg.getAnchorPoint().x,this.spDescbg.getAnchorPoint().y)){//窗口
this.spDescbg.setVisible(false);
//屏蔽之后按键
}else if(thisPoint.x&=minx && thisPoint.y&=miny && thisPoint.x&=maxx && thisPoint.y&=maxy){
Guide.getInstance()._runGuide();
closeGuideModal:function(){
cc.unregisterTouchDelegate(this);
this.setVisible(false);// =
onExit:function(){
this._super();
cc.unregisterTouchDelegate(this);
onEnter:function(){
this._super();
cc.unregisterTouchDelegate(this);
cc.registerTargetedDelegate(-998,true,this);
* 绘制形状
drawShape:function(GuideLayer_SHAPE_TYPE,pPosition,pwidth,pheight,component){
var color = cc.c4f(59,58,55,1);
var borderColor = cc.c4f(0.97, 0.76, 0.8, 1);
var drawNode = cc.DrawNode.create();
//component
switch(GuideLayer_SHAPE_TYPE){
case GuideLayer.SHAPE_TYPE_CIRCLE:
var radius = pwidth/2;
var nCount = 200;
var angel = 2*Math.PI/nC
var pointAry = [];
for(var i=0;i&nC++i){
var radian = i*
pointAry[i] = {};
pointAry[i].x = radius*Math.cos(radian)+pwidth/2+pPosition.x;
pointAry[i].y = radius*Math.sin(radian)+pwidth/2+pPosition.y;
drawNode.drawPoly(pointAry,color,1,borderColor);
drawNode.setPosition(cc.p(0,0));
this.pClip.setStencil(drawNode);
case GuideLayer.SHAPE_TYPE_RECT:
var rectCount = 4;
var drawPointAry = [];
drawPointAry[0]
drawPointAry[1]
= cc.p(pPosition.x+pwidth,pPosition.y);
drawPointAry[2]
= cc.p(pPosition.x+pwidth,pPosition.y+pheight);
drawPointAry[3]
= cc.p(pPosition.x,pPosition.y+pheight);
drawNode.drawPoly(drawPointAry,color,1,borderColor);
drawNode.setPosition(cc.p(0,0));
this.pClip.setStencil(drawNode);
actionStarP : null,//起点坐标=箭头用
actionStopP : null,//终点坐标=箭头用
* 防止箭头位置箭头
setArrowRect:function(arrowRect,componentPoint,p_width,p_height){
var actionStarP = cc.p(0,0);
var actionStopP = cc.p(0,0);
this.actionStarP = actionStarP;
this.actionStopP = actionStopP;
switch(arrowRect){
case GuideLayer.ARROW_RECT_TYPE_UP://上方
//cc.log(&上方&);
this.spArrow.setRotation(90);
actionStarP.x = componentPoint.x+p_width/2;
actionStarP.y = componentPoint.y+p_height+this.spArrow.getContentSize().height/2+this.arrowMoveD
actionStopP.x = actionStarP.x;
actionStopP.y = componentPoint.y+p_height+this.spArrow.getContentSize().height/2;
//moveFlag = GuideLayer.ARROW_RECT_TYPE_UP;
case GuideLayer.ARROW_RECT_TYPE_DOWN://下方
//cc.log(&下方&);
this.spArrow.setRotation(270);
actionStarP.x = componentPoint.x+p_width/2;
actionStarP.y = componentPoint.y-this.spArrow.getContentSize().height/2-this.arrowMoveD
actionStopP.x = actionStarP.x;
actionStopP.y = componentPoint.y-this.spArrow.getContentSize().height/2;
//moveFlag = GuideLayer.ARROW_RECT_TYPE_DOWN;
case GuideLayer.ARROW_RECT_TYPE_LEFT://左方
this.spArrow.setRotation(0);
//cc.log(&左方&);
actionStarP.y = componentPoint.y+p_height/2;
actionStarP.x = componentPoint.x-this.spArrow.getContentSize().width/2-this.arrowMoveD
actionStopP.y = actionStarP.y;
actionStopP.x = componentPoint.x-this.spArrow.getContentSize().width/2;
//moveFlag = GuideLayer.ARROW_RECT_TYPE_LEFT;
case GuideLayer.ARROW_RECT_TYPE_RIGHT://右方
this.spArrow.setRotation(180);
//cc.log(&右方&);
actionStarP.y = componentPoint.y+p_height/2;
actionStarP.x = componentPoint.x+p_width+this.spArrow.getContentSize().width/2+this.arrowMoveD
actionStopP.y = actionStarP.y;
actionStopP.x = componentPoint.x+p_width+this.spArrow.getContentSize().width/2;
//moveFlag = GuideLayer.ARROW_RECT_TYPE_RIGHT;
this.currMoveArrowP.x = actionStarP.x;
this.currMoveArrowP.y = actionStarP.y;
this.spArrow.setPosition(actionStarP);//设置坐标位置
//这里判断左,右,上,下移动...
var arrowAction = cc.RepeatForever.create(cc.Sequence.create(cc.MoveTo.create(0.5,actionStarP),cc.MoveTo.create(0.5,actionStopP)));
this.spArrow.runAction(arrowAction);
currMoveArrowP:cc.p(0,0),//当前箭头移动的位置
moveFlag:null,//0:正向/1:反向
* 控制箭头移动...
controllerArrowMove:function(){//start在远方
if(this.actionStarP==null){
if(this.actionStarP.x==this.actionStopP.x){//移动Y
t = this.actionStarP.y-this.actionStopP.y;
//正式流出
if(this.currMoveArrowP.y==this.actionStarP.y){
this.moveFlag = 'Z';
}else if(this.currMoveArrowP.y == this.actionStopP.y){
this.moveFlag = 'F';
if(t&0){//上向下
this.moveFlag==&Z& ? this.currMoveArrowP.y-- : this.currMoveArrowP.y++;
}else{//下向上
this.moveFlag==&F& ? this.currMoveArrowP.y-- : this.currMoveArrowP.y++;
}else{//移动X
t = this.actionStarP.x-this.actionStopP.x;
//正式流出
if(this.currMoveArrowP.x==this.actionStarP.x){
this.moveFlag = 'Z';
}else if(this.currMoveArrowP.x == this.actionStopP.x){
this.moveFlag = 'F';
if(t&0){//上向下
this.moveFlag==&Z& ? this.currMoveArrowP.x-- : this.currMoveArrowP.x++;
}else{//下向上
this.moveFlag==&F& ? this.currMoveArrowP.x-- : this.currMoveArrowP.x++;
this.spArrow.setPosition(this.currMoveArrowP);
* 转动滑动提示的箭头
* componentPoint:物体坐标左下角的
* p_width:sp宽度
* p_height:sp高度
* isShowDragArrowView:0隐藏 1:显示
* dragArrowViewRotate:角度0-270
showDragArrowView:function(componentPoint,p_width,p_height,isShowDragArrowView,dragArrowViewRotate){
if(isShowDragArrowView!=0){
var point = cc.p(0,0);
point.x = componentPoint.x+p_width/2;
point.y = componentPoint.y+p_height/2;
this.spDragArrow.setPosition(point);
this.spDragArrow.setRotation(dragArrowViewRotate);
this.spDragArrow.setVisible(true);
this.spDragArrow.setVisible(false);
GuideLayer.SHAPE_TYPE_CIRCLE = &circle&;//
GuideLayer.SHAPE_TYPE_RECT = &rect&;//
GuideLayer.TOUCH_EVENT_TYPE_CLICK = &click&;
GuideLayer.TOUCH_EVENT_TYPE_MOVE = &move&;
GuideLayer.ARROW_RECT_TYPE_UP = &up&;
GuideLayer.ARROW_RECT_TYPE_DOWN = &down&;
GuideLayer.ARROW_RECT_TYPE_LEFT = &left&;
GuideLayer.ARROW_RECT_TYPE_RIGHT = &right&;
Guide.instance =
Guide.getInstance = function(){
if(Guide.instance==null){
Guide.instance = new Guide();
return Guide.
Guide.CALLBACK_FUNCKEY = &guideCallBack&;
ponentCallBackFunc = function(component){
if(component==null){
cc.log(&guide component控件被销毁&);
if(component.hasOwnProperty(Guide.CALLBACK_FUNCKEY)){
var callback = component[Guide.CALLBACK_FUNCKEY];
delete component[Guide.CALLBACK_FUNCKEY];
callback();
事件类型(TouchEventType):mouseClick,mouseDrag
箭头位置(ArrowRect): up,left,right,down
文字描述(TextDesc):.......文本框
模块名称(LayerName): 选项... =& 空间名称(ComponentName);
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ GuideModel @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ GuideModel @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ GuideModel @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
var GuideModel = function(){
this.data=
* 更新引导数据
this.updateDate = function(){
this.data = GuideTaskI
//cc.log(&update data&);
Guide.getInstance().setEndGuideCallBack(function(){
GuideModel.getInstance().endGuide();
Guide.getInstance().runGuide(this.data);
* 引导完成执行...
this.endGuide = function(){
//cc.log(&看看是否右调用到这里?????????&);
Guide.getInstance().stopGuide();
//告诉服务端引导完成
//这里调用===通知引导结束
GuideModel.instance =
GuideModel.getInstance = function(){
if(GuideModel.instance==null){
GuideModel.instance = new GuideModel();
return GuideModel.
&& 感谢这些年遇到所有一切美好的人和事 auth:cx,email:
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1847次
排名:千里之外
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 新手引导设计 的文章

更多推荐

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

点击添加站长微信