1.什麼時候需要場景物件?
場景物件有區別於上一篇介紹的地圖對象,它們分別應用於不同類型的遊戲。先前的地圖物件應用於格子類的遊戲,例如推箱子,坦克大戰。而本節介紹的場景對象,則適用於擁有特定場景的遊戲,例如超級瑪麗,恐龍快打等。這類遊戲通常在2d場景內控制一個玩家對象,隨著玩家的移動,場景跟著移動。
2.場景範例:
效果:(左右鍵控制超級瑪莉的移動)
<body> <div><canvas id="gameCanvas">请使用支持canvas的浏览器查看</canvas></div> </body> <script src="cnGame_v1.0.js"></script> <script> var Src="http://images.cnblogs.com/cnblogs_com/Cson/290336/o_player.png"; var background="background.png"; /* 初始化 */ cnGame.init('gameCanvas',{width:500,height:400}); 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(); this.background=new cnGame.View({src:background,player:this.player,imgWidth:2301}); this.background.centerPlayer(true); this.background.insideView(this.player,"x"); }, update:function(){ this.player.update(); this.background.update([this.player]); }, draw:function(){ this.background.draw(); this.player.draw(); } }; })(); cnGame.loader.start([Src,background],gameObj); </script>3.程式碼實作:
/** *初始化 **/ init:function(options){ /** *默认对象 **/ var defaultObj={ width:cg.width, height:cg.height, imgWidth:cg.width, imgHeight:cg.height, x:0, y:0 } options=options||{}; options=cg.core.extend(defaultObj,options); this.player=options.player; this.width=options.width; this.height=options.height; this.imgWidth=options.imgWidth; this.imgHeight=options.imgHeight; this.centerX=this.width/2; this.src=options.src; this.x=options.x; this.y=options.y; this.insideArr=[]; this.isLoop=false;; this.isCenterPlayer=false; this.onEnd=options.onEnd; },用戶傳入的參數除了xy以及尺寸外,另外還有三個參數,一個參數是設定是否把玩家物件置於中心,只移動背景而不移動玩家。如果要實現上面的背景移動效果,則該參數要設為true。另一個參數是設定是否循環。如果設定為循環,在背景移動到極點後,會重新回到初始位置。最後一個參數是onEnd,如果設定為非循環,那麼背景移動到極點後,會觸發該回呼函數。 場景物件的重點在於update方法:
/** *背景移动时的更新 **/ update:function(spritelist){//传入所有sprite的数组 if(this.isCenterPlayer){ if(this.player.x>this.centerX){ if(this.x<this.imgWidth-this.width){ var marginX=this.player.x-this.centerX; this.x+=marginX; if(spritelist){ for(var i=0,len=spritelist.length;i<len;i++){ if(spritelist[i]==this.player){ spritelist[i].x=this.centerX; } else{ spritelist[i].x-=marginX; } } } } else if(this.isLoop){ if(spritelist){ for(var i=0,len=spritelist.length;i<len;i++){ if(spritelist[i]!=this.player){ spritelist[i].move(this.imgWidth-this.width); } } } this.x=0; } else{ this.onEnd&&this.onEnd(); } } } for(var i=0,len=this.insideArr.length;i<len;i++){ inside.call(this,this.insideArr[i]); } },該方法首先判斷player物件是否已經超過場景中心,如果已經超過,則計算超出的距離,並且把player固定在場景中心,超出的距離設定為背景向相反方向移動的距離與除了player外其他sprite向相反方向移動的距離,這樣的話就只有背景移動和其他sprite物件移動,player固定。如果是循環的話,則在超出移動範圍後重置背景和其他sprite的x座標。如果非循環,則在移動結束後呼叫onEnd回呼函數。另外如果需要限制player始終在顯示區域內,還可以呼叫insideView方法。 附上場景物件所有程式碼:###
/** * *场景 * **/ cnGame.register("cnGame",function(cg){ /** *使指定对象在可视区域view内 **/ var inside=function(sprite){ var dir=sprite.insideDir; if(dir!="y"){ if(sprite.x<0){ sprite.x=0; } else if(sprite.x>this.width-sprite.width){ sprite.x=this.width-sprite.width; } } if(dir!="x"){ if(sprite.y<0){ sprite.y=0; } else if(sprite.y>this.height-sprite.height){ sprite.y=this.height-sprite.height; } } } var view=function(options){ this.init(options); } view.prototype={ /** *初始化 **/ init:function(options){ /** *默认对象 **/ var defaultObj={ width:cg.width, height:cg.height, imgWidth:cg.width, imgHeight:cg.height, x:0, y:0 } options=options||{}; options=cg.core.extend(defaultObj,options); this.player=options.player; this.width=options.width; this.height=options.height; this.imgWidth=options.imgWidth; this.imgHeight=options.imgHeight; this.centerX=this.width/2; this.src=options.src; this.x=options.x; this.y=options.y; this.insideArr=[]; this.isLoop=false;; this.isCenterPlayer=false; this.onEnd=options.onEnd; }, /** *使player的位置保持在场景中点之前的移动背景 **/ centerPlayer:function(isLoop){ isLoop=isLoop||false; this.isLoop=isLoop; this.isCenterPlayer=true; }, /** *使对象的位置保持在场景内 **/ insideView:function(sprite,dir){//dir为限定哪个方向在view内,值为x或y,不传则两个方向皆限定 if(cg.core.isArray(sprite)){ for(var i=0,len=sprite.length;i以上是HTML5遊戲框架cnGameJS開發實錄-遊戲場景對象的詳細內容。更多資訊請關注PHP中文網其他相關文章!