在游戏中,游戏角色的动画效果是一个游戏必不可少的一部分。这节我们以构造超级马里奥的角色为例,讲解cnGameJS里动画的实现。
1.原理:
一个动画如果要实现一连串动作,我们可以把每个动作的快照保留起来,并放在一个大图上面,然后每次帧更新的时候,就在每个动作的快照之间循环显示,最终得出一个动画。因此我们首先要准备一个类似下面的这种图片:
看到不?把每个动作放在图片的不同位置上,之后就可以通过改变显示位置实现动画效果了。
当cnGameJS调用start方法开始游戏后,将会调用传入的gameObj的initialize方法进行初始化,并且生成一个游戏循环,循环里每次调用gameObj的update和draw方法。因此我们可以把动画的初始化放在gameObj的initialize中,update和draw分别放在gameObj的update和draw中,实现动画播放。
效果:
代码:
<body> <canvas id="gameCanvas">请使用支持canvas的浏览器查看</canvas> </body> <script src="http://files.cnblogs.com/Cson/cnGame_v1.0.js"></script> <script> var Src="http://pic002.cnblogs.com/images/2012/273330/2012021312050269.png"; /* 初始化 */ cnGame.init('gameCanvas',{width:50,height:60}); var gameObj={ initialize:function(){ this.marie=cnGame.SpriteSheet("marie",Src,{frameSize:[50,60],width:150,height:60,loop:true}); }, update:function(){ this.marie.update(); }, draw:function(){ this.marie.draw(); } } cnGame.loader.start([Src],gameObj); </script>
2.实现
正如上面看到的,我们只需要用很少的代码量,就可以实现一个帧动画的播放,接下来将介绍cnGameJS里的帧动画是怎样封装的。
大家很容易可以发现,cnGameJS都遵循一个特定的模式,把对象的阶段分为三个:initialize(初始化),update(帧更新)和draw(绘制)。这样我们可以很方便地把不同功能的代码写在对应的阶段内。spriteSheet帧动画也不例外,同样按照这种模式来写。
初始化:用户对一些必要的信息进行设定。
spriteSheet.prototype={ /** *初始化 **/ init:function(id,src,options){ /** *默认对象 **/ var defaultObj={ x:0, y:0, width:120, height:40, frameSize:[40,40], frameDuration:100, direction:"right", //从左到右 beginX:0, beginY:0, loop:false, bounce:false }; options=options||{}; options=cg.core.extend(defaultObj,options); this.id=id; //spriteSheet的id this.src=src; //图片地址 this.x=options.x; //动画X位置 this.y=options.y; //动画Y位置 this.width=options.width; //图片的宽度 this.height=options.height; //图片的高度 this.image=cg.loader.loadedImgs[this.src]; //图片对象 this.frameSize=options.frameSize; //每帧尺寸 this.frameDuration=options.frameDuration; //每帧持续时间 this.direction=options.direction; //读取帧的方向(从做到右或从上到下) this.currentIndex=0; //目前帧索引 this.beginX=options.beginX; //截取图片的起始位置X this.beginY=options.beginY; //截图图片的起始位置Y this.loop=options.loop; //是否循环播放 this.bounce=options.bounce; //是否往返播放 this.onFinsh=options.onFinsh; //播放完毕后的回调函数 this.frames=caculateFrames(options); //帧信息集合 this.now=new Date().getTime(); //当前时间 this.last=new Date().getTime(); //上一帧开始时间 },
上面的参数比较多,都是一些对帧动画属性的预设置。需要注意的是我们调用了私有方法caculateFrames来计算每个帧的信息,并保存到frames内,为帧绘制做准备。
帧更新:
在每一帧的更新过程中,我们首先获取当前时间作为帧的开始时间,并且和上一次帧的开始时间相减,就得出上一次帧的用时。如果用时超过之前设置的每帧的用时,则可以进行帧更新。然后判断是否循环或者往返播放动画,按情况更新对应的帧索引。在最终确定帧的索引后,就可以从frames数组中获取该帧的信息,并返回。
/** *更新帧 **/ update:function(){ this.now=new Date().getTime(); var frames=this.frames; if((this.now-this.last)>this.frameDuration){//如果间隔大于帧间间隔,则update var currentIndex=this.currentIndex; var length=this.frames.length; this.last=this.now; if(currentIndex>=length-1){ if(this.loop){ //循环 return frames[this.currentIndex=0]; } else if(!this.bounce){//没有循环并且没有往返滚动,则停止在最后一帧 this.onFinsh&&this.onFinsh(); this.onFinsh=undefined; return frames[currentIndex]; } } if((this.bounce)&&((currentIndex>=length-1&&path>0)||(currentIndex<=0&&path<0))){ //往返 path*=(-1); } this.currentIndex+=path; } return frames[this.currentIndex]; },
帧绘制:
在帧更新后,已经获取到当前帧的索引,因此draw方法就可以从保存所有帧信息的frames获取到当前帧的信息(包括图像截取的起始位置等),从而在指定位置截取大图片,并画出该图片区域的图像:
/** *在特定位置绘制该帧 **/ draw:function(){ var currentFrame=this.getCurrentFrame(); var width=this.frameSize[0]; var height=this.frameSize[1]; cg.context.drawImage(this.image,currentFrame.x,currentFrame.y,width,height,this.x,this.y,width,height); }
最后,还提供跳到特定帧等方法。
动画模块所有源码:
/** *包含多帧图像的大图片 **/ spriteSheet=function(id,src,options){ if(!(this instanceof arguments.callee)){ return new arguments.callee(id,src,options); } this.init(id,src,options); } spriteSheet.prototype={ /** *初始化 **/ init:function(id,src,options){ /** *默认对象 **/ var defaultObj={ x:0, y:0, width:120, height:40, frameSize:[40,40], frameDuration:100, direction:"right", //从左到右 beginX:0, beginY:0, loop:false, bounce:false }; options=options||{}; options=cg.core.extend(defaultObj,options); this.id=id; //spriteSheet的id this.src=src; //图片地址 this.x=options.x; //动画X位置 this.y=options.y; //动画Y位置 this.width=options.width; //图片的宽度 this.height=options.height; //图片的高度 this.image=cg.loader.loadedImgs[this.src]; //图片对象 this.frameSize=options.frameSize; //每帧尺寸 this.frameDuration=options.frameDuration; //每帧持续时间 this.direction=options.direction; //读取帧的方向(从做到右或从上到下) this.currentIndex=0; //目前帧索引 this.beginX=options.beginX; //截取图片的起始位置X this.beginY=options.beginY; //截图图片的起始位置Y this.loop=options.loop; //是否循环播放 this.bounce=options.bounce; //是否往返播放 this.onFinsh=options.onFinsh; //播放完毕后的回调函数 this.frames=caculateFrames(options); //帧信息集合 this.now=new Date().getTime(); //当前时间 this.last=new Date().getTime(); //上一帧开始时间 }, /** *更新帧 **/ update:function(){ this.now=new Date().getTime(); var frames=this.frames; if((this.now-this.last)>this.frameDuration){//如果间隔大于帧间间隔,则update var currentIndex=this.currentIndex; var length=this.frames.length; this.last=this.now; if(currentIndex>=length-1){ if(this.loop){ //循环 return frames[this.currentIndex=0]; } else if(!this.bounce){//没有循环并且没有往返滚动,则停止在最后一帧 this.onFinsh&&this.onFinsh(); this.onFinsh=undefined; return frames[currentIndex]; } } if((this.bounce)&&((currentIndex>=length-1&&path>0)||(currentIndex<=0&&path<0))){ //往返 path*=(-1); } this.currentIndex+=path; } return frames[this.currentIndex]; }, /** *跳到特定帧 **/ index:function(index){ this.currentIndex=index; return this.frames[this.currentIndex]; }, /** *获取现时帧 **/ getCurrentFrame:function(){ return this.frames[this.currentIndex]; }, /** *在特定位置绘制该帧 **/ draw:function(){ var currentFrame=this.getCurrentFrame(); var width=this.frameSize[0]; var height=this.frameSize[1]; cg.context.drawImage(this.image,currentFrame.x,currentFrame.y,width,height,this.x,this.y,width,height); } } this.SpriteSheet=spriteSheet; });
以上是HTML5游戏框架cnGameJS开发实录-实现动画原理的详细内容。更多信息请关注PHP中文网其他相关文章!

HTML5带来了五个关键改进:1.语义化标签提升了代码清晰度和SEO效果;2.多媒体支持简化了视频和音频嵌入;3.表单增强简化了验证;4.离线与本地存储提高了用户体验;5.画布与图形功能增强了网页的可视化效果。

HTML5的核心特性包括语义化标签、多媒体支持、离线存储与本地存储、表单增强。1.语义化标签如、等,提升代码可读性和SEO效果。2.和标签简化多媒体嵌入。3.离线存储和本地存储如ApplicationCache和LocalStorage,支持无网络运行和数据存储。4.表单增强引入新输入类型和验证属性,简化处理和验证。

H5提供了多种新特性和功能,极大地增强了前端开发的能力。1.多媒体支持:通过和元素嵌入媒体,无需插件。2.画布(Canvas):使用元素动态渲染2D图形和动画。3.本地存储:通过localStorage和sessionStorage实现数据持久化存储,提升用户体验。

H5和HTML5是不同的概念:HTML5是HTML的一个版本,包含新元素和API;H5是基于HTML5的移动应用开发框架。HTML5通过浏览器解析和渲染代码,H5应用则需要容器运行并通过JavaScript与原生代码交互。

HTML5的关键元素包括、、、、、等,用于构建现代网页。1.定义头部内容,2.用于导航链接,3.表示独立文章内容,4.组织页面内容,5.展示侧边栏内容,6.定义页脚,这些元素增强了网页的结构和功能性。

HTML5和H5没有区别,H5是HTML5的简称。1.HTML5是HTML的第五个版本,增强了网页的多媒体和交互功能。2.H5常用于指代基于HTML5的移动网页或应用,适用于各种移动设备。

HTML5是超文本标记语言的最新版本,由W3C标准化。HTML5引入了新的语义化标签、多媒体支持和表单增强,提升了网页结构、用户体验和SEO效果。HTML5引入了新的语义化标签,如、、、等,使网页结构更清晰,SEO效果更好。HTML5支持多媒体元素和,无需第三方插件,提升了用户体验和加载速度。HTML5增强了表单功能,引入了新的输入类型如、等,提高了用户体验和表单验证效率。

如何写出干净高效的HTML5代码?答案是通过语义化标签、结构化代码、性能优化和避免常见错误。1.使用语义化标签如、等,提升代码可读性和SEO效果。2.保持代码结构化和可读性,使用适当缩进和注释。3.优化性能,通过减少不必要的标签、使用CDN和压缩代码。4.避免常见错误,如标签未闭合,确保代码有效性。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。