디렉토리로 돌아가기
1. 스프라이트객체(스프라이트)란 무엇인가요?
소위 엘프 개체는 게임 내 동작을 포함하는 요소입니다. 슈퍼마리오를 예로 들면, 마리와 적들은 모두 엘프 개체로 간주됩니다. cnGameJS 프레임워크에서 Sprite 객체는 다음과 같은 특징을 가지고 있습니다.
1. 애니메이션 추가 : 이전 애니메이션 글에서 cnGameJS가 프레임 애니메이션을 구현하는 방법을 소개했습니다. 스프라이트 객체로서 애니메이션을 사용하는 사용자입니다. 예를 들어 Mary가 다른 방향으로 걷도록 제어하면 Mary는 걷기 애니메이션을 생성합니다.
2. 이미지 포함 : 다른 스프라이트 객체의 경우 모션 애니메이션이 필요하지 않을 수 있으므로 이미지를 사용하면 됩니다.
3. 다양한 유형의 움직임을 수행할 수 있습니다: 스프라이트 객체를 다양한 방향과 가속도로 움직일 수 있습니다.
2.demo 표시
여기에 간단한 데모가 있습니다. Mary가 정지할 때 마우스를 통해 Mary의 동작(균일 가속 이동)을 제어합니다. Mary가 움직일 때 애니메이션과 키보드의 왼쪽 및 오른쪽 화살표 키를 사용하여 Mary의 움직임을 제어하세요.
효과:
코드:
<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);//调用父类update if(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 객체도 초기화, 업데이트, 그리기의 세 단계로 구분됩니다.
스프라이트 초기화 첫 번째 살펴보기 함수 :
/** *初始化 **/ 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 애니메이션이 사용됩니다.
먼저 스프라이트 개체가 이미지를 사용하는 방법을 살펴보겠습니다.
/** *设置当前显示图像 **/ 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; } },
먼저 이미지가 지금 사용되고 있는지 확인하세요. 그렇지 않은 경우 로더에서 다운로드한 이미지 개체를 가져옵니다(모든 이미지 리소스는 게임 내에서는 처음에 다운로드 받았고, spriteSheet를 undefine(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; } } }, 复制代码
먼저 들어오는 spriteSheet 또는 spriteSheet의 ID를 기반으로 애니메이션이 사용되는지 확인합니다. 그렇지 않은 경우 사용할 스프라이트를 설정합니다. spriteSheet 애니메이션.
애니메이션을 사용하도록 Sprite 개체를 설정한 후 핵심 함수 update는 spriteSheet의 업데이트를 호출하여 SpriteSheet에서 사용하는 애니메이션을 업데이트하는 역할을 담당합니다. 스프라이트의 xy:
if(this.spriteSheet){//更新spriteSheet动画 this.spriteSheet.x=this.x this.spriteSheet.y=this.y; this.spriteSheet.update(); }
이로써 스프라이트 개체 애니메이션 표시가 완료됩니다.
마지막으로 스프라이트가 다양한 속도로 움직일 수 있도록 하는 마지막 기능을 구현하는 방법을 살펴보겠습니다.
가변 속도 모션을 수행하려면 초기 속도, 경과 시간, 가속도 등 변수를 설정해야 합니다. 이제 가변 속도 이동을 담당하는 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를 호출할 때마다 스프라이트의 초기 속도와 이동이 시작되는 시간이 유지됩니다. 이런 방식으로 업데이트할 때마다 이전 두 변수를 기반으로 스프라이트의 현재 속도를 얻을 수 있으며 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); 复制代码
업데이트가 스프라이트의 변위를 업데이트하면 3단계 그리기 방법을 통해 스프라이트가 그려집니다.
/** *绘制出sprite **/ draw:function(){ var context=cg.context; if(this.spriteSheet){ this.spriteSheet.x=this.x this.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(); } },
스프라이트가 spriteSheet 애니메이션을 사용하는지, 이미지를 사용하는지에 따라 그리기 메서드 실행이 다르다는 점에 유의하세요. sprieSheet 애니메이션을 사용할 때 draw 메서드는 기본적으로 spriteSheet의 draw 메서드를 호출하여 프레임 이미지를 그립니다. Sprite가 이미지를 사용할 때 이미지를 그리기 전에 회전할 수도 있습니다.
스프라이트 개체는 스프라이트 개체가 포함된 사각형을 반환하는 getRect 메서드도 제공합니다. 이 방법은 스프라이트 객체와 다른 객체 간의 충돌을 감지하는 편의성을 제공합니다. 충돌 감지에 대해서는 다음을 참조하십시오: HTML5 게임 프레임워크 cnGameJS 개발 기록(충돌 감지)
또한 스프라이트 객체에는 move, moveTo, resize, resizeTo 등과 같은 기능이 있어 제어를 용이하게 합니다. 물체의 위치와 크기.
스프라이트 객체의 모든 소스 코드:
/** * *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.x this.spriteSheet.y=this.y; this.spriteSheet.update(); } }, /** *绘制出sprite **/ draw:function(){ var context=cg.context; if(this.spriteSheet){ this.spriteSheet.x=this.x this.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; }); 复制代码
위 내용은 HTML5 게임 프레임워크 cnGameJS 개발 기록 - elf 객체 장의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!