返回目录

1.什么是精灵对象(sprite)?

  所谓的精灵对象,就是游戏中的一个具有行为的元素,以超级玛丽为例,玛丽,敌人都算是一个精灵对象。在cnGameJS框架中,精灵对象如下几个特点:

  1.添加动画:在之前的动画篇中,我们介绍过cnGameJS如何实现帧动画。而作为精灵对象,就是动画的使用者。例如我们控制玛丽向不同方向的行走,玛丽会产生行走的动画。

  2.包含图像:对于另外一些精灵对象,它可能不需要运动动画,这时我们就可以只让它使用图像。

  3.能进行不同类型的运动:可以让精灵对象向不同方向,以不同加速度进行移动。

2.demo展现

  这里以一个简单的demo进行展现,我们通过鼠标控制玛丽的行动(匀加速运动),当玛丽停止时,使用图片。当玛丽移动时,使用动画,键盘左右方向键控制玛丽的移动

  效果:

  代码:

<body><div><canvas id="gameCanvas">请使用支持canvas的浏览器查看</canvas></div></body><script src="http://files.cnblogs.com/Cson/cnGame_v1.0.js"></script><script>var Src="http://images.cnblogs.com/cnblogs_com/Cson/290336/o_player.png";

/* 初始化 */cnGame.init('gameCanvas',{width:300,height:150});var floorY=cnGame.height-40;var gameObj=(function(){/* 玩家对象 */var player=function(options){this.init(options);    this.speedX=0;this.moveDir;this.isJump=false;    }    cnGame.core.inherit(player,cnGame.Sprite);    player.prototype.initialize=function(){this.addAnimation(new cnGame.SpriteSheet("playerRight",Src,{frameSize:[50,60],loop:true,width:150,height:60}));this.addAnimation(new cnGame.SpriteSheet("playerLeft",Src,{frameSize:[50,60],loop:true,width:150,height:120,beginY:60}));    }    player.prototype.moveRight=function(){if(cnGame.core.isUndefined(this.moveDir)||this.moveDir!="right"){this.moveDir="right";this.speedX<0&&(this.speedX=0);this.setMovement({aX:10,maxSpeedX:15});this.setCurrentAnimation("playerRight");        }    }    player.prototype.moveLeft=function(){if(cnGame.core.isUndefined(this.moveDir)||this.moveDir!="left"){this.moveDir="left";this.speedX>0&&(this.speedX=0);this.setMovement({aX:-10,maxSpeedX:15});this.setCurrentAnimation("playerLeft");        }    }    player.prototype.stopMove=function(){

if(this.speedX<0){this.setCurrentImage(Src,0,60);        }else if(this.speedX>0){this.setCurrentImage(Src);        }    this.moveDir=undefined;this.resetMovement();

    }    player.prototype.update=function(){        player.prototype.parent.prototype.update.call(this);//调用父类updateif(cnGame.input.isPressed("right")){this.moveRight();            }else if(cnGame.input.isPressed("left")){this.moveLeft();        }else{this.stopMove();        }

    }

return {        initialize:function(){            cnGame.input.preventDefault(["left","right","up","down"]);this.player=new player({src:Src,width:50,height:60,x:0,y:floorY-60});this.player.initialize();        },        update:function(){this.player.update();        },        draw:function(){this.player.draw();        }

    };})();cnGame.loader.start([Src],gameObj);</script>
复制代码


3.实现

  和动画篇spriteSheet对象一样,sprite对象同样划分三个阶段:初始化,更新,绘制

  首先看sprite的初始化函数:

        /**         *初始化        **/        init:function(options){

/**             *默认对象            **/    var defaultObj={                x:0,                y:0,                imgX:0,                imgY:0,                width:32,                height:32,                angle:0,                speedX:0,                speedY:0,                aX:0,                aY:0,                maxSpeedX:postive_infinity,                maxSpeedY:postive_infinity,                maxX:postive_infinity,                maxY:postive_infinity,                minX:-postive_infinity,                minY:-postive_infinity            };            options=options||{};            options=cg.core.extend(defaultObj,options);this.x=options.x;this.y=options.y;this.angle=options.angle;this.width=options.width;this.height=options.height;this.angle=options.angle;this.speedX=options.speedX;this.speedY=options.speedY;this.aX=options.aX;this.aY=options.aY;this.maxSpeedX=options.maxSpeedX;this.maxSpeedY=options.maxSpeedY;this.maxX=options.maxX;this.maxY=options.maxY;this.minX=options.minX;this.minY=options.minY;

this.spriteSheetList={};if(options.src){    //传入图片路径                this.setCurrentImage(options.src,options.imgX,options.imgY);            }else if(options.spriteSheet){//传入spriteSheet对象                this.addAnimation(options.spriteSheet);                        setCurrentAnimation(options.spriteSheet);            }

        }
复制代码

  参数很多,主要包括:对象位置,旋转角度,尺寸,xy方向的速度,xy方向的加速度,xy方向的最大速度。另外如果用户传入图片地址,则设置当前sprite对象使用图片,否则使用spriteSheet动画。

  先看看sprite对象如何使用图像:

        /**         *设置当前显示图像        **/        setCurrentImage:function(src,imgX,imgY){if(!this.isCurrentImage(src,imgX,imgY)){                imgX=imgX||0;                imgY=imgY||0;this.image=cg.loader.loadedImgs[src];    this.imgX=imgX;this.imgY=imgY;    this.spriteSheet=undefined;            }        },
复制代码

  首先检测现在是否正在使用该图像,如果不是,则从loader里获取下载好的image对象(所有图像资源在游戏开始时已下载好,详情请看:HTML5游戏框架cnGameJS开发实录(资源加载模块篇)),并且设置spriteSheet为undefined(表示不使用spriteSheet动画),这样sprite对象就可以使用图像了。

  再看看如何使用动画:

        /**         *设置当前显示动画        **/        setCurrentAnimation:function(id){//可传入id或spriteSheet            if(!this.isCurrentAnimation(id)){if(cg.core.isString(id)){this.spriteSheet=this.spriteSheetList[id];this.image=this.imgX=this.imgY=undefined;                }else if(cg.core.isObject(id)){this.spriteSheet=id;this.addAnimation(id);this.image=this.imgX=this.imgY=undefined;                }            }

        },
复制代码

  首先根据传入的spriteSheet或spriteSheet的id判断是否正在使用该动画,如果不是,则设置sprite使用spriteSheet动画。

  设置好sprite对象使用动画后,核心函数update就负责调用spriteSheet的update,更新sprite使用的动画,需要注意的是使spriteSheet的xy为sprite的xy:

if(this.spriteSheet){//更新spriteSheet动画                this.spriteSheet.x=this.xthis.spriteSheet.y=this.y;this.spriteSheet.update();            }
复制代码

  这样就完成的sprite对象动画的展示。

  最后看看如何实现最后一个特点:使sprite能进行变速的运动。

  要进行变速运动,我们需要确立如下几个变量:初始速度,经过的时间,以及加速度。现在看cnGameJS负责变速运动的部分:

        /**         *设置移动参数        **/        setMovement:function(options){            isUndefined=cg.core.isUndefined;            isUndefined(options.speedX)?this.speedX=this.speedX:this.speedX=options.speedX;            isUndefined(options.speedY)?this.speedY=this.speedY:this.speedY=options.speedY;

            isUndefined(options.aX)?this.aX=this.aX:this.aX=options.aX;            isUndefined(options.aY)?this.aY=this.aY:this.aY=options.aY;            isUndefined(options.maxX)?this.maxX=this.maxX:this.maxX=options.maxX;            isUndefined(options.maxY)?this.maxY=this.maxY:this.maxY=options.maxY;            isUndefined(options.minX)?this.minX=this.minX:this.minX=options.minX;            isUndefined(options.minY)?this.minY=this.minY:this.minY=options.minY;

if(this.aX!=0){this.startTimeX=new Date().getTime();this.oriSpeedX=this.speedX;                isUndefined(options.maxSpeedX)?this.maxSpeedX=this.maxSpeedX:this.maxSpeedX=options.maxSpeedX;                }if(this.aY!=0){this.startTimeY=new Date().getTime();this.oriSpeedY=this.speedY;                isUndefined(options.maxSpeedY)?this.maxSpeedY=this.maxSpeedY:this.maxSpeedY=options.maxSpeedY;                }

        }
复制代码

  每次用户调用setMovement,就保留sprite的初速度,和运动开始的时间。这样在每次update的时候,就可以根据前面两个变量,获取到sprite现时的速度,并计算现时的XY方向上的位移:

 

            if(this.aX!=0){var now=new Date().getTime();var durationX=now-this.startTimeX;var speedX=this.oriSpeedX+this.aX*durationX/1000;if(this.maxSpeedX<0){this.maxSpeedX*=-1;                }if(speedX<0){this.speedX=Math.max(speedX,this.maxSpeedX*-1)    ;                }else{this.speedX=Math.min(speedX,this.maxSpeedX);                }            }if(this.aY!=0){var now=new Date().getTime();var durationY=now-this.startTimeY;this.speedY=this.oriSpeedY+this.aY*durationY/1000;                }this.move(this.speedX,this.speedY);
复制代码

  当update更新了sprite的位移,就可以通过第三个阶段draw方法,把sprite绘制出来。

        /**         *绘制出sprite        **/        draw:function(){var context=cg.context;if(this.spriteSheet){this.spriteSheet.x=this.xthis.spriteSheet.y=this.y;this.spriteSheet.draw();            }else if(this.image){                context.save()                context.translate(this.x, this.y);                context.rotate(this.angle * Math.PI / 180);                context.drawImage(this.image,this.imgX,this.imgY,this.width,this.height,0,0,this.width,this.height);                context.restore();            }

        },
复制代码

  注意sprite在使用spriteSheet动画或在使用图像,draw方法执行都不相同。当使用sprieSheet动画时,draw方法实质上是调用了spriteSheet的draw方法绘制帧图像,而当sprite使用图像,我们还可以让图像旋转之后再绘制。

  sprite对象还提供一个getRect方法,返回包含该sprite对象的矩形。该方法为检测sprite对象和其他对象的碰撞带来方便。有关碰撞检测请看:HTML5游戏框架cnGameJS开发实录(碰撞检测篇)

  另外sprite对象同样具有move,moveTo,resize,resizeTo等功能,方便对该对象的位置和尺寸进行操控。

  sprite对象所有源码:

/** * *sprite对象 ***/cnGame.register("cnGame",function(cg){

var postive_infinity=Number.POSITIVE_INFINITY;            

var sprite=function(id,options){if(!(this instanceof arguments.callee)){return new arguments.callee(id,options);        }this.init(id,options);    }    sprite.prototype={/**         *初始化        **/        init:function(options){

/**             *默认对象            **/    var defaultObj={                x:0,                y:0,                imgX:0,                imgY:0,                width:32,                height:32,                angle:0,                speedX:0,                speedY:0,                aX:0,                aY:0,                maxSpeedX:postive_infinity,                maxSpeedY:postive_infinity,                maxX:postive_infinity,                maxY:postive_infinity,                minX:-postive_infinity,                minY:-postive_infinity            };            options=options||{};            options=cg.core.extend(defaultObj,options);this.x=options.x;this.y=options.y;this.angle=options.angle;this.width=options.width;this.height=options.height;this.angle=options.angle;this.speedX=options.speedX;this.speedY=options.speedY;this.aX=options.aX;this.aY=options.aY;this.maxSpeedX=options.maxSpeedX;this.maxSpeedY=options.maxSpeedY;this.maxX=options.maxX;this.maxY=options.maxY;this.minX=options.minX;this.minY=options.minY;

this.spriteSheetList={};if(options.src){    //传入图片路径                this.setCurrentImage(options.src,options.imgX,options.imgY);            }else if(options.spriteSheet){//传入spriteSheet对象                this.addAnimation(options.spriteSheet);                        setCurrentAnimation(options.spriteSheet);            }

        },/**         *返回包含该sprite的矩形对象        **/        getRect:function(){return new cg.shape.Rect({x:this.x,y:this.y,width:this.width,height:this.height});

        },/**         *添加动画        **/        addAnimation:function(spriteSheet){this.spriteSheetList[spriteSheet.id]=spriteSheet;            },/**         *设置当前显示动画        **/        setCurrentAnimation:function(id){//可传入id或spriteSheet            if(!this.isCurrentAnimation(id)){if(cg.core.isString(id)){this.spriteSheet=this.spriteSheetList[id];this.image=this.imgX=this.imgY=undefined;                }else if(cg.core.isObject(id)){this.spriteSheet=id;this.addAnimation(id);this.image=this.imgX=this.imgY=undefined;                }            }

        },/**         *判断当前动画是否为该id的动画        **/        isCurrentAnimation:function(id){if(cg.core.isString(id)){return (this.spriteSheet&&this.spriteSheet.id===id);            }else if(cg.core.isObject(id)){return this.spriteSheet===id;            }        },/**         *设置当前显示图像        **/        setCurrentImage:function(src,imgX,imgY){if(!this.isCurrentImage(src,imgX,imgY)){                imgX=imgX||0;                imgY=imgY||0;this.image=cg.loader.loadedImgs[src];    this.imgX=imgX;this.imgY=imgY;    this.spriteSheet=undefined;            }        },/**         *判断当前图像是否为该src的图像        **/        isCurrentImage:function(src,imgX,imgY){            imgX=imgX||0;            imgY=imgY||0;var image=this.image;if(cg.core.isString(src)){return (image&&image.srcPath===src&&this.imgX===imgX&&this.imgY===imgY);            }        },/**         *设置移动参数        **/        setMovement:function(options){            isUndefined=cg.core.isUndefined;            isUndefined(options.speedX)?this.speedX=this.speedX:this.speedX=options.speedX;            isUndefined(options.speedY)?this.speedY=this.speedY:this.speedY=options.speedY;

            isUndefined(options.aX)?this.aX=this.aX:this.aX=options.aX;            isUndefined(options.aY)?this.aY=this.aY:this.aY=options.aY;            isUndefined(options.maxX)?this.maxX=this.maxX:this.maxX=options.maxX;            isUndefined(options.maxY)?this.maxY=this.maxY:this.maxY=options.maxY;            isUndefined(options.minX)?this.minX=this.minX:this.minX=options.minX;            isUndefined(options.minY)?this.minY=this.minY:this.minY=options.minY;

if(this.aX!=0){this.startTimeX=new Date().getTime();this.oriSpeedX=this.speedX;                isUndefined(options.maxSpeedX)?this.maxSpeedX=this.maxSpeedX:this.maxSpeedX=options.maxSpeedX;                }if(this.aY!=0){this.startTimeY=new Date().getTime();this.oriSpeedY=this.speedY;                isUndefined(options.maxSpeedY)?this.maxSpeedY=this.maxSpeedY:this.maxSpeedY=options.maxSpeedY;                }

        },/**         *重置移动参数回到初始值        **/        resetMovement:function(){this.speedX=0;this.speedY=0;this.aX=0;this.aY=0;this.maxSpeedX=postive_infinity;this.maxSpeedY=postive_infinity;this.maxX=postive_infinity;this.minX=-postive_infinity;this.maxY=postive_infinity;this.minY=-postive_infinity;        },/**         *更新位置和帧动画        **/        update:function(){if(this.aX!=0){var now=new Date().getTime();var durationX=now-this.startTimeX;var speedX=this.oriSpeedX+this.aX*durationX/1000;if(this.maxSpeedX<0){this.maxSpeedX*=-1;                }if(speedX<0){this.speedX=Math.max(speedX,this.maxSpeedX*-1)    ;                }else{this.speedX=Math.min(speedX,this.maxSpeedX);                }            }if(this.aY!=0){var now=new Date().getTime();var durationY=now-this.startTimeY;this.speedY=this.oriSpeedY+this.aY*durationY/1000;                }this.move(this.speedX,this.speedY);

if(this.spriteSheet){//更新spriteSheet动画                this.spriteSheet.x=this.xthis.spriteSheet.y=this.y;this.spriteSheet.update();            }        },/**         *绘制出sprite        **/        draw:function(){var context=cg.context;if(this.spriteSheet){this.spriteSheet.x=this.xthis.spriteSheet.y=this.y;this.spriteSheet.draw();            }else if(this.image){                context.save()                context.translate(this.x, this.y);                context.rotate(this.angle * Math.PI / 180);                context.drawImage(this.image,this.imgX,this.imgY,this.width,this.height,0,0,this.width,this.height);                context.restore();            }

        },/**         *移动一定距离        **/        move:function(dx,dy){            dx=dx||0;            dy=dy||0;var x=this.x+dx;var y=this.y+dy;this.x=Math.min(Math.max(this.minX,x),this.maxX);this.y=Math.min(Math.max(this.minY,y),this.maxY);return this;

        },/**         *移动到某处        **/        moveTo:function(x,y){this.x=Math.min(Math.max(this.minX,x),this.maxX);this.y=Math.min(Math.max(this.minY,y),this.maxY);return this;        },/**         *旋转一定角度        **/        rotate:function(da){this.angle+=da;return this;        },/**         *旋转到一定角度        **/        rotateTo:function(){this.angle=da;return this;

        },/**         *改变一定尺寸        **/        resize:function(dw,dh){this.width+=dw;this.height+=dh;return this;        },/**         *改变到一定尺寸        **/        resizeTo:function(width,height){this.width=width;this.height=height;return this;        }

    }this.Sprite=sprite;                              

});
复制代码

转载于:https://www.cnblogs.com/Cson/archive/2012/02/14/2349661.html

【CSON原创】HTML5游戏框架cnGameJS开发实录(精灵对象篇)相关推荐

  1. html 游戏 精灵,HTML5游戏框架cnGameJS开发实录-精灵对象篇

    返回目录 1.什么是精灵对象(sprite)? 所谓的精灵对象,就是游戏中的一个具有行为的元素,以超级玛丽为例,玛丽,敌人都算是一个精灵对象.在cnGameJS框架中,精灵对象如下几个特点: 1.添加 ...

  2. 【CSON原创】HTML5游戏框架cnGameJS开发实录(外部输入模块篇)

    返回目录 1.为什么我们需要外部输入模块? 在游戏中我们常常用到类似这样的操作:鼠标点击某位置,玩家对象移动到该位置,或者按鼠标方向键,玩家向不同方向移动,等等.这些操作无一不用与外部输入设备打交道. ...

  3. 【CSON原创】HTML5游戏框架cnGameJS开发实录

    cnGameJS是本人开发的一个基于HTML5的游戏框架,包括资源加载,碰撞检测,动画等模块.本系列文章主要介绍各个模块的开发流程,以及附上两个使用该框架进行开发的游戏demo. 目录: 1.核心函数 ...

  4. javascript+HTMl5游戏下载,开发一个都能月薪上万!舅服你

    HTML5时代已经到来许久了,你是否已经掌握了那么一点呢?今天小编给大家讲讲h5的折叠多设备.跨平台特性, 即用HTML5制作游戏.相比flash,HTML5更加灵活方便,随着浏览器技术的不断升级,H ...

  5. 推荐25款很棒的 HTML5 前端框架和开发工具【下篇】

    快速,安全,响应式,互动和美丽,这些优点吸引更多的 Web 开发人员使用 HTML5.HTML5 有许多新的特性功能,允许开发人员和设计师创建应用程序和网站,带给用户桌面应用程序的速度,性能和体验. ...

  6. Phaser开源2d引擎 javascript/html5游戏框架

    功能特点(Features) 易维护代码(Easy Asset Loading) Phaser可以加载图片,音频文件,数据文件,文本文件和自动解析精灵图和纹理地图集数据(出口纹理封隔器或Flash C ...

  7. HTML5游戏开发经验及开发工具分享

    当你开发基于HTML5的游戏时,你有很多选择.使用什么样的编辑器?是否用到Canvas 2d.WebGL?采用什么样的呈现框架和游戏引擎?这些选择大部分由开发者的个人经验和游戏将要发布的平台决定. 幸 ...

  8. Html5游戏框架createJS组件--EaselJS

    CreateJS库是一款HTML5游戏开发的引擎,是一套可以构建丰富交互体验的HTML5游戏的开源工具包,旨在降低HTML5项目的开发难度和成本,让开发者以熟悉的方式打造更具现代感的网络交互体验. 掌 ...

  9. Phaser开源2d引擎 html5游戏框架中文简介

    功能特点(Features) 易维护代码(Easy Asset Loading) Phaser可以加载图片,音频文件,数据文件,文本文件和自动解析精灵图和纹理地图集数据(出口纹理封隔器或Flash C ...

最新文章

  1. DataWorks 功能实践 — 生产开发环境隔离
  2. 使用机器学习预测电子竞技游戏《守望先锋》的胜负
  3. 嵌入式c语言移植,嵌入式C语言位操作的移植方法
  4. 设置双网卡mic linux,linux双网卡绑定为逻辑网卡
  5. 超详细|一篇搞定操作系统——处理器管理
  6. css-盒子模型详解以及远视图的制作
  7. oracle多个参数查询,Oracle 多参数查询语句
  8. 25种让你精力充沛的方法
  9. [HNOI2007] 紧急疏散EVACUATE
  10. python简笔画程序_社会了,教小白如何用Python画出小猪佩琪!
  11. 2108 JAVASE每日复习总结 链接汇总
  12. 软件工程实训——点歌管理系统开发记录
  13. html文档主体的根标签,HTML详细介绍(基础标签篇)
  14. 欧几里得算法及其扩展欧几里得算法——数论
  15. 窗口桌面置顶(主窗口和子窗口)
  16. Blockchain for Internet of Energy management: Review, solutions, and challenges
  17. 有趣的Python:Python控制键盘鼠标
  18. 使用python判断成绩是否合格
  19. C#/.NET 解析Cron表达式,根据Cron表达式获取最近执行时间
  20. [原创]开源跨平台大型网络端口扫描器K8PortScan(支持批量A段/B段/C段/IP列表)

热门文章

  1. Python 列表 list() 方法
  2. 注意,ruby循环体定义的变量在结束时后,变量还存在
  3. 忍一时得寸进尺, 退一步变本加厉。
  4. (转)xshell无法在vim中复制黏贴
  5. 面试之BI-SQL--table转换
  6. 认识Axure的软件界面
  7. SQL Server R2 地图报表制作(四)
  8. 如何解决弹出窗口固定大小及内容的问题
  9. uboot启动linux,uboot中ramdisk启动linux的两种方法
  10. mysql打包备份数据到_thinkPHP使用pclzip打包备份mysql数据库的方法