@H_404_9@前言 2014秋季开发者大会,微信报名页面上线后,大家一片惊呼声,都觉得Cocos2d-Js非常适合这种报名页和宣传页面的制作,可以以一个比较简单、快速的形式,构建出我们需要的漂亮页面。下面我们就来介绍一下,Cocos 2014秋季开发者大会的微信报名页面,是如何实现的。 在这篇教程里,我会教大家如何用Cocos2d-Js来实现一个微信宣传页面,最终结果如下几个页面。 需求分析 五个界面基本上就是整个宣传页的全部内容,通过滑动这几个页面可以看出,我们要实现这个页面,大致需要完成下面几项内容: 实现上述五个页面的切换。 实现5个页面的入场和出场动画。 添加背景音乐 屏幕适配 添加微信分享的API 接下来,我们一项一项给大家介绍,完整的代码可以在这里进行[url=local://base_request.HTML/res/register.zip]下载[/url]。 开发环境与新建项目 如果没用过cocos2d-Js的朋友们,可以到cocos官网上去下载,此处我们用的是 3.0final,或者,我们可以下载lite版本的Cocos2d-Js,lite版本可以很方便的根据需求去下载所需要的模块,可以很大的减少代码的体积, 下载地址?此处,我们需要用到的模块有core?actions?menuprogress-timer,在该页面中选择Customized Version然后勾选上述几个模块,并点击下载。 此处我们使用cocos 命令行来创建新的工程
环境搭建并不是这篇文章的重点,更详细的信息可以参考:《搭建 Cocos2d-JS 开发环境》。 主界面及其页面切换框架的实现 程序的入口代码在main.Js中,用编辑器打开并修改为下面的代码。
关键点解析如下: 设置浏览器Meta来适配屏幕,引擎内部会根据屏幕大小来设置Meta的vIEwport值,会达到更好的屏幕适配效果。 针对手机浏览器和PC浏览器启用不同的分辨率适配策略。 预加载图片声音等资源。 cc.LoaderScene.preload会生成一个“加载中 x%”的界面,等待资源加载结束后,调用第二个参数传入的匿名函数。 对于基于HTML的游戏,页面是放在服务器端供浏览器下载的,为了获得流畅的用户体验,cc.LoaderScene.preload让浏览器先把远程服务器的资源缓存到本地。需要预加载的资源定义在src/Resources.Js文件中。 启动游戏的第一个场景。 主界面分为2个部分,第一个部分是不随着屏幕移动而移动的向上箭头和音乐按钮,第二个部分是根据用户滑动屏幕而改变的场景。 我们先根据需要,构建出需要的函数,并一一实现他,这里我们使用cc.Scene.extend()?来扩展出一个scene,并在这个scene中构建出我们需要功能,并一一实现他。 由引擎提供的cc.Scene.extend方法,让Js能实现高级面向对象语言的继承特性。 onEnter方法是场景初始化完成即将展示的消息回调,在onEnter中必须调用this._super();来确保Scene被正确的初始化。 用于初始化UI的函数 initUI() 用于初始化touch事件的函数 inittouch()。 用于切换页面的函数changePage()和记录当前页面的参数currentIndex 用于控制箭头显示隐藏的函数toggleArrow() 用于控制音乐按钮回调的函数
接下来我们一一来实现他。 首先,我们来实现音乐按钮与箭头,我们在initUI()中添加如下代码。
我们在屏幕中,添加了一个背景的sprite,并且,将这个背景进行缩放,以让其在各种情况下都布满屏幕,并且我们为箭头设置了一系列动画,让其能够循环播放,Cocos2d-Js,为了方便广大开发者,提供了丰富多彩的动画(actions)。下面,我们先简单的介绍一下几个常用的action的API。 cc.repeatForever(action) 无限循环某个action cc.sequence(action1,action2,...)顺序执行括号里面的action cc.spawn(action1,...)同时执行括号里面的action cc.moveto(duration,targetPoint)从当前位置在duration(秒)时间内移动到点targetposition的action cc.easeIn(rate) 以rate为ease参数执行easeIn的action,一般是这样使用的action.easing(cc.easeIn(rate)) fadeOut(duration) 在duration时间内从屏幕淡出的action cc.delayTime(duration) 延时duration时间的action,通常用于等待一段时间后再播放某个action cc.callFunc(function) 用于执行action的回调,通常在某个action结束后需要执行某段函数的话,可以使用它。 通过上述的简单介绍,是不是对action有了一个初步的了解了呢,我们实际来 *** 作一下: 我们需要一个箭头,往上走并慢慢减速和透明,最终消失,然后在原来的位置出现重复下去,所以我们可以归纳为,移动+淡出-->回到初始位置-->移动+淡出。这样我们很清晰就归纳出如何去写这个action了,我们使用cc.spawn(cc.moveto(),cc.fadeOut())就构建出了移动+淡出这个效果,然后使用cc.callFunc()设置了这次action播放完毕要修改的位置回到初始位置,接着我们使用cc.sequence()来顺序执行这两个action,这样一来,一次action就编写完成了,最后我们只需要将这个action使用cc.repeatForever()就完成了我们需要的重复播放。 细心的读者可能会问了,代码中的位置设置,为什么是cc.pAdd(cc.visibleRect.right,cc.p())?这是cocos为了让大家更方便的做屏幕适配所定义的9个点,这9个点会根据不同屏幕大小来动态设定,例如cc.visibleRect.center,这个点的位置,无论在什么分辨率的屏幕下,都是在屏幕的正中央,这样我们就可以根据这个点的位置来做相对布局,已达到适配屏幕的目的,例如上面的代码this.arrow.setposition(cc.pAdd(cc.visibleRect.bottom,50)));就是将arrow这个sprite,放在屏幕的底部的正中央,然后再在y轴上加50个像素,这样,无论屏幕的大小,都能保持在屏幕的底部的正中央向上50个像素。这也是我们做相对布局的基础。后续的布局,我们都会根据这些点的坐标来设置。 接下来,我们要开始思考,如何填充我们的主要功能——5个页面的框架。 在这里我们使用cc.Layer.extend定义出5个Layer,并在每个layer中,实现appear方法和disappear方法,分别用于控制页面的入场动画和出场动画,后面,我们会详细介绍每个layer的动画,现在我们设计出layer的框架后呢,我们就可以动手编写MainScene里面的initUI的剩余部分和nextPage函数的编写了,一下是完整的initUI()代码:
可以看到,首先,我们在MainScene中定义了一个animLayer,用来控制各个页面的动画层,然后我们定义了一个数组用来存储我们的需要的5个Layer,最后他们添加到animLayer里面,并将非当前显示页的Layer隐藏,这样引擎就不会去绘制他们了。
我们想好如何去编写5个页面后,就可以开始编写addtouch()和changePage()了,在这里,我们设置了一个全局变量canChangePage来判断当前换页的 *** 作是否可以执行,如果动画正在播放中,我们不能进行页面的切换 *** 作。由于iOS和某些AndroID特定版本的限制,需要有实际的点击才能触发音频的播放,所以我们在ontouchended的时候,去触发音频播放。 说到音频播放,我们有2个选择,第一可以使用引擎自带的cc.audioEngine,其中集成了多种浏览器的兼容播放,可以很省时省力的进行音乐播放,不过这里,由于我们比较在意code的体积,所以直接使用简单粗暴的HTML标签<audio></audio>以下是我们简单实现的音乐播放,使用一个全局变量musicPlayStatus来控制音频的播放状态,其实现如下: 复制代码 var initMusic = function () { var audio = getByID("myAudio"); audio.src = "res/bg.mp3"; var playMusic = function (status) { if (status) { if (audio.paused) { audio.play(); musicPlayStatus = true; if (!audio.paused) { audio.pause(); musicPlayStatus = false; } |
由于我们不希望音乐在开始加载页面的时候就进行下载,所以我们使用initMusic()这个方法来初始化音乐,并使用playMusic()的方法来控制音乐的播放。
同时我们需要在MainScene加入一个方法,用来监听浏览器进入后台,和从后台进入前台的事件,用来控制音乐的播放状态,引擎已经封装好了对应的事件,我们可以非常方便的去监听这些事件,可以大大减少开发的周期。
复制代码 initHIDeEvent: function () { cc.eventManager.addCustomListener(cc.game.EVENT_SHOW,247)"> cc.eventManager.addCustomListener(cc.game.EVENT_HIDE,247)"> playMusic(false); } |
第一个页面的实现
由于我们已经制定好了,页面的规则,所以每个页面我们要做的就以下几点
实现UI的布局 实现appear入场动画 实现disappear出场动画 控制能否滑动到下一个屏幕的状态
复制代码 this.acclayer = new cc.Layer(); this.acclayer.anchorX = 0; this.acclayer.anchorY = 0; this.acclayer.x = 0; this.acclayer.y = 0; this.addChild(this.acclayer); this.logo = new cc.Sprite("#logo.png"); this.logo.scale = 0; this.logo.setposition(cc.pAdd(cc.visibleRect.center,this.logo.height / 3 * 2))); this.addChild(this.logo); this.leftFont = new cc.Sprite("#Font_left.png"); this.leftFont.setposition(cc.pAdd(cc.visibleRect.left,cc.p(-this.leftFont.wIDth / 2,-this.leftFont.height / 2))); this.addChild(this.leftFont); this.rightFont = new cc.Sprite("#Font_right.png"); this.rightFont.setposition(cc.pAdd(cc.visibleRect.right,cc.p(this.rightFont.wIDth / 2,-this.rightFont.height / 2))); this.addChild(this.rightFont); this.leftUpPic = new cc.Sprite("#block_left up.png"); this.leftUpPic.anchorX = 0,this.leftUpPic.anchorY = 1; this.leftUpPic.setposition(cc.pAdd(cc.visibleRect.topleft,cc.p(-this.leftUpPic.wIDth,this.leftUpPic.height))); this.acclayer.addChild(this.leftUpPic); this.leftDownPic = new cc.Sprite("#block_left down.png"); this.leftDownPic.anchorX = 0,this.leftDownPic.anchorY = 0; this.leftDownPic.setposition(cc.pAdd(cc.visibleRect.bottomleft,cc.p(-this.leftDownPic.wIDth + 20,-this.leftDownPic.height))); this.acclayer.addChild(this.leftDownPic); this.rightUpPic = new cc.Sprite("#block_right up.png"); this.rightUpPic.anchorX = 1,this.rightUpPic.anchorY = 1; this.rightUpPic.setposition(cc.pAdd(cc.visibleRect.topRight,cc.p(this.rightUpPic.wIDth,this.rightUpPic.height))); this.acclayer.addChild(this.rightUpPic); this.rightDownPic = new cc.Sprite("#block_right down.png"); this.rightDownPic.anchorX = 1,this.rightDownPic.anchorY = 0; this.rightDownPic.setposition(cc.pAdd(cc.visibleRect.bottomright,cc.p(this.rightDownPic.wIDth,-this.rightDownPic.height))); this.acclayer.addChild(this.rightDownPic); } |
以上是对第一个页面的布局,从图上我们其实就可以看到,页面由logo、左上、左下、右上、右下、和左右两列文字组成,至于布局我们就不多说了,主要有以下几点。
可以看到我们依然使用相对布局,让每个ui可以适应不同屏幕分辨率 由于有入场动画,所以我们将这些UI都放到屏幕外面了 我们对三角形的物体,放置在了一个独立的Layer?acclayer?为的是以后如果需要添加陀螺仪的监听,我们可以很方便的进行修改 接下来我们要实现的时入场动画
复制代码 appear: function () { var logoAction = cc.sequence(cc.scaleto(0.5,1),247)"> this.leftUpPic.leftUpAction = cc.moveto(0.5,cc.p(this.leftUpPic.x + this.leftUpPic.wIDth,this.leftUpPic.y - this.leftUpPic.height + 80)); this.leftUpPic.runAction(this.leftUpPic.leftUpAction); this.leftDownPic.leftDownAction = cc.moveto(0.5,cc.p(this.leftDownPic.x + this.leftDownPic.wIDth,this.leftDownPic.y + this.leftDownPic.height)); this.leftDownPic.runAction(this.leftDownPic.leftDownAction); this.rightUpPic.rightUpAction = cc.moveto(0.5,cc.p(this.rightUpPic.x - this.rightUpPic.wIDth - 30,this.rightUpPic.y - this.rightUpPic.height - 30)); this.rightUpPic.runAction(this.rightUpPic.rightUpAction); this.rightDownPic.rightDownAction = cc.moveto(0.5,cc.p(this.rightDownPic.x - this.rightDownPic.wIDth,this.rightDownPic.y + this.rightDownPic.height)); this.rightDownPic.runAction(this.rightDownPic.rightDownAction); this.leftFont.FontleftAction = cc.sequence(cc.delayTime(0.3),cc.moveto(0.5,cc.p(this.leftFont.x + this.leftFont.wIDth,this.leftFont.y))); this.leftFont.runAction(this.leftFont.FontleftAction); this.rightFont.FontRightAction = cc.sequence(cc.delayTime(0.4),cc.moveto(0.4,cc.p(this.rightFont.x - this.rightFont.wIDth,this.rightFont.y))); this.rightFont.runAction(this.rightFont.FontRightAction); canChangePage = true; this.logo.runAction(logoAction); } |
appear的实现方式非常简单,其实就是把几个我们上面写好的UI,移动到我们希望的位置。
logoAction,使用前面介绍过的函数cc.sequence()和cc.scaleto(),最后在结束的时候调用cc.callFunc() 在cc.callFunc()中呢,我们对其余的元素一一进行了入场动画,主要使用了cc.moveto()这个方法,可以看到,我们从屏幕外面,移动到了屏幕里面。 值得注意的是,我们在logoAction的最后,使用cc.delayTime()延时了一段时间,然后再执行canChangePage = true主要是为了在动画播放过程中,不然用户滑动改变页面。 接下来就是disappear方法的实现了:
复制代码 disappear: function (callback,target) { var action = cc.sequence(cc.scaleto(0.5,0),247)"> this.leftUpPic.runAction(this.leftUpPic.leftUpAction.reverse()); this.leftDownPic.runAction(this.leftDownPic.leftDownAction.reverse()); this.rightUpPic.runAction(this.rightUpPic.rightUpAction.reverse()); this.rightDownPic.runAction(this.rightDownPic.rightDownAction.reverse()); this.leftFont.runAction(this.leftFont.FontleftAction.reverse()); this.rightFont.runAction(this.rightFont.FontRightAction.reverse()); if (target && callback) { callback.call(target); this.logo.runAction(action); 很简单,我们也是让logo执行了一个action,然后再执行disappear传进来的回调方法就ok了。 这里,我们使用了action.reverse()这个方法,可以很简便的实现大多数action的reverse 动画播放完毕后,调用回调方法执行我们需要的回调 *** 作 ok,此时我们第一个页面已经编写完了,赶紧运行下试试吧。接下来,由于第二第四第五个页面跟第一个页面都很类似,我们就不重复讲了,大家看看代码吧,也当做练练手。我们接着重点说说第三个页面的实现。 第三个页面的实现 第三个页面,是区别于其他页面的一个页面,主要原因是其余的页面,我们基本使用的是cc.moveto()这个方法,配合上cc.delayTime()等,实现一系列的移动,只要多试验几次,我们就可以很清楚这些action的使用方法,各种混搭之后,可以实现出很复杂也很绚丽的效果。 不过接下来我们将介绍一个之前没有用过的接口cc.progresstimer()来快速实现我们的一条往下滑动的效果。 cc.progresstimer() 多数情况用于使用某个sprite进行计时,倒计时 *** 作,如下图,我们可以很清楚的看到他的效果,我们使用这个效果,可以很容易的实现出那个功能。 我们需要准备一张图片,如下图,然后使用progresstimer,就可以很容易实现这个功能了。 复制代码 ... this.line = new cc.Progresstimer(new cc.Sprite(res.line_png)); this.line.type = cc.Progresstimer.TYPE_bar; this.line.mIDPoint = cc.p(0,247)"> this.line.barChangeRate = cc.p(0,247)"> this.line.percentage = 0; this.line.setposition(cc.p(cc.winSize.wIDth / 2 - 30,cc.winSize.height - this.line.height / 2)); this.addChild(this.line); appear: function () {//20,50,80,100 this.leftUpPic.inAciton = cc.moveto(0.2,cc.p(this.leftUpPic.x + this.leftUpPic.wIDth + 20,this.leftUpPic.y - this.leftUpPic.height + 20)); this.leftUpPic.runAction(this.leftUpPic.inAciton); this.leftDownPic.inAciton = cc.moveto(0.2,cc.p(this.leftDownPic.x + this.leftDownPic.wIDth + 20,this.leftDownPic.y + this.leftDownPic.height + 20)); this.leftDownPic.runAction(this.leftDownPic.inAciton); this.rightUpPic.inAciton = cc.moveto(0.2,247)"> this.rightUpPic.runAction(this.rightUpPic.inAciton); this.rightDownPic.inAciton = cc.moveto(0.2,cc.p(this.rightDownPic.x - this.rightDownPic.wIDth - 20,this.rightDownPic.y + this.rightDownPic.height + 80)); this.rightDownPic.runAction(this.rightDownPic.inAciton); var action = cc.sequence(cc.delayTime(0.2),cc.progressto(0.3,20),247)"> this.firstPoint.inAction = cc.scaleto(0.2,247)"> this.firstPoint.runAction(this.firstPoint.inAction); this.firstText.inAction = cc.sequence(cc.delayTime(0.2),cc.spawn(cc.moveto(0.2,cc.p(this.firstText.x - this.firstText.wIDth / 2,this.firstText.y)),cc.fadeIn(0.5))); this.firstText.runAction(this.firstText.inAction); this.secondPoint.inAction = cc.scaleto(0.2,247)"> this.secondPoint.runAction(this.secondPoint.inAction); this.secondText.inAction = cc.sequence(cc.delayTime(0.2),cc.p(this.secondText.x + this.secondText.wIDth / 2,this.secondText.y)),247)"> this.secondText.runAction(this.secondText.inAction); this.thirdPoint.inAction = cc.scaleto(0.2,247)"> this.thirdPoint.runAction(this.thirdPoint.inAction); this.thirdText.inAction = cc.sequence(cc.delayTime(0.2),cc.p(this.thirdText.x - this.thirdText.wIDth / 2,this.thirdText.y)),247)"> this.thirdText.runAction(this.thirdText.inAction); this.forthPoint.inAction = cc.scaleto(0.2,247)"> this.forthPoint.runAction(this.forthPoint.inAction); this.line.runAction(action); 上面的代码看似很多,不过,只要分清楚我们的目的,那就很清晰了(ps:initUI只贴出了一部分跟progresstimer相关的代码,具体代码请直接看源码吧)。 我们重点介绍一下cc.progresstimer() 他跟所有Cocos2d-Js的API一样,使用new来创建对象 progresstimer的type参数用于设置类型,这里我们使用cc.Progresstimer.TYPE_bar也就是条状的progress mIDPoint参数,用于设置开始progress的起始位置,有点类似于锚点传入一个cc.p()x y范围都是0到1 barchangeRate就是每次dt更新的百分比 顺便介绍一下cc.progressto(duration,percent),主要用于cc.progresstimer当中,从在duration的时间内,从当前的百分比增加到percent。 介绍了基础的用法之后呢,我们对cc.progresstimer()有了一定的了解,接下来我们主要使用cc.progresstimer里面的cc.progressto()这个方法去实现第三个场景的动画,经过对图片的测量,我们选定了20%,50%,80%,100%进行分段的价值,所以我们通过cc.sequence(cc.progressto(),cc.callFunc(),cc.delayTime(),.....)这样一组循环,去分段加载那个图片。 到这里为止,我们比较详细的介绍了Cocos2d-Js一些常用的action,并且用他,实现了一个比较美观的动画,大家有兴趣可以动手亲自去试试。 微信API的集成 本功能已经有大神提供了完整的库, 地址?,以下我们做一个简单的使用分析。 复制代码 // 微信分享的数据 window.wxData = { "appID": "",// 服务号可以填写appID "imgurl": "http://upyun.cocimg.com/cocoachina/cocos_logo.png",247)"> "link": "http://devcon.cocos.com/weixin/",247)"> "desc": "Cocos 2014 开发者大会(秋季)—Great or nothing",247)"> "Title": "COCOS 2014 秋季开发者大会" WeixinAPI.ready(function (API) { // 分享的回调 var wxCallbacks = { ready: function () { cancel: function (resp) { fail: function (resp) { confirm: function (resp) { all: function (resp) { API.sharetoFrIEnd(wxData,wxCallbacks); API.sharetoTimeline(wxData,247)"> API.sharetoWeibo(wxData,247)"> }); |
如果有需要就可以对分享的回调进行监听了,针对分享过程中的每个状态,有需要的只需要在对应的函数回调里面进行编写对应代码就可以了。
混淆发布
如果使用cocos命令行,非常简单就可以进行打包发布了,在控制台输入命令:
复制代码 cocos compile -p web -m release |
程序会在当前的工程目录下,生成一个publish的文件夹,里面的HTML5文件就是我们的发布版本了,小伙伴们,赶紧也发布一个试试吧。
另外,如果需要更高得压缩比,只需要使用下面的指令:
复制代码 cocos compile -p web -m release --advanced |
添加--advanced标签会使用Closure Compiler混淆工具的高级压缩功能,将使Js代码所占的空间更加小,但是这个压缩模式有一定风险会导致错误,如果发现错误可以根据Google的 官方文档来进行调试。
最后,记得哦,完整的代码可以在附件中下载。
最后附上微信效果地址:
[ 此帖被superdragon在2014-10-23 11:49重新编辑 ]
以上是内存溢出为你收集整理的如何用Cocos2d-JS制作一个微信报名宣传页全部内容,希望文章能够帮你解决如何用Cocos2d-JS制作一个微信报名宣传页所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)