最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

HTML5游戏框架cnGameJS开发实录-游戏场景对象

来源:动视网 责编:小采 时间:2020-11-27 15:10:26
文档

HTML5游戏框架cnGameJS开发实录-游戏场景对象

HTML5游戏框架cnGameJS开发实录-游戏场景对象:1.什么时候需要场景对象? 场景对象有区别于上一篇介绍的地图对象,它们分别应用于不同类型的游戏。之前的地图对象应用于格子类的游戏,例如推箱子,坦克大战。而本节介绍的场景对象,则适用于拥有特定场景的游戏,例如超级玛丽,恐龙快打等。这类游戏通常在
推荐度:
导读HTML5游戏框架cnGameJS开发实录-游戏场景对象:1.什么时候需要场景对象? 场景对象有区别于上一篇介绍的地图对象,它们分别应用于不同类型的游戏。之前的地图对象应用于格子类的游戏,例如推箱子,坦克大战。而本节介绍的场景对象,则适用于拥有特定场景的游戏,例如超级玛丽,恐龙快打等。这类游戏通常在
 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.代码实现:
  要构造一个场景,首先需要一张足够宽的背景图片,当player向右移动时,使player始终处于背景中点,player的速度转换为背景向相反方向移动的速度。首先看初始化函数:

/**
 *初始化
 **/
 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<len;i++){
 arguments.callee.call(this,sprite[i],dir);
 }
 }
 else{
 sprite.insideDir=dir;
 this.insideArr.push(sprite);
 }
 },
 /**
 *背景移动时的更新
 **/
 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]);
 }
 },
 /**
 *绘制场景
 **/
 draw:function(){
 cg.context.drawImage(cg.loader.loadedImgs[this.src],this.x,this.y,this.width,this.height,0,0,this.width,this.height);
 }
 
 
 }
 this.View=view;
});

文档

HTML5游戏框架cnGameJS开发实录-游戏场景对象

HTML5游戏框架cnGameJS开发实录-游戏场景对象:1.什么时候需要场景对象? 场景对象有区别于上一篇介绍的地图对象,它们分别应用于不同类型的游戏。之前的地图对象应用于格子类的游戏,例如推箱子,坦克大战。而本节介绍的场景对象,则适用于拥有特定场景的游戏,例如超级玛丽,恐龙快打等。这类游戏通常在
推荐度:
标签: 游戏 开发 对象
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top