【CSON原创】HTML5游戏框架cnGameJS开发实录(游戏场景对象)

返回目录

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;
});

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

### 回答1: protobuf是一种语言无关的数据序列化格式,可以将结构化数据以二进制形式进行存储、传输和解析。相比其他序列化格式(如JSON和XML),protobuf具有更高的效率和更小的存储空间,特别适用于性能要求较高的场景CSON是一种基于文本的数据交换格式,它的语法和JSON类似,但更加简洁易读。CSON可以直接嵌入到许多编程语言中,而无需额外的解析器或库。相比JSON,CSON有更好的人机可读性,可以更快地编写和解析。在一些开发工具中,如Atom编辑器,CSON被广泛用于配置文件。 当我们使用protobuf和CSON时,两者的作用是不同的。protobuf主要用于高效的数据存储和传输,主要用于网络通信和持久化存储。它定义了用于描述结构化数据的消息格式,并生成相应的编解码代码。protobuf允许我们使用预定义的消息结构定义数据模型,并将其序列化为二进制数据进行传输或存储。在接收端,我们可以将二进制数据反序列化为原始的消息结构,以进行后续处理。 CSON则更适用于配置文件和简单数据的存储和交换。与JSON相比,CSON的语法更简洁易读,可以更方便地进行人工编辑和修改。在开发过程中,我们可以使用CSON格式的配置文件来定义应用程序的设置和参数,以及其他需要在运行时进行调整的数据。CSON可以与各种编程语言一起使用,通过相应的解析库来读取和写入CSON数据。 综上所述,protobuf和CSON都是用于数据交换和存储的格式,但其使用场景和特点有所不同。protobuf适合高效的网络通信和持久化存储,而CSON则适用于配置文件和简单数据的存储和交换。 ### 回答2: protobuf cson 是 Google 开发的一种数据序列化格式,可以用于不同编程语言之间的数据交换。cson 是 CSN(CoffeeScript Object Notation)的缩写,它是一种类似于 JSON 的数据格式,但具有更简洁和易读的语法。 protobuf cson 结合了 Protocol Buffers(一种用于结构化数据的语言无关、平台无关、可扩展的序列化格式)和 cson 的优势,既可以确定数据结构,又可以通过人类可读的方式来表示数据。相比于 JSON,protobuf cson 使用更少的字符来表示相同的数据结构,因此也更加紧凑和高效。 使用 protobuf cson开发者可以根据预先定义好的消息结构来序列化和反序列化数据。通过定义消息类型和字段,我们可以精确控制所要传输的数据结构,在不同语言中实现数据的互相转换。同时,protobuf cson 还支持扩展和向后兼容性,可以轻松地向已有的消息类型添加新的字段。 protobuf cson 在分布式系统、微服务架构以及网络通信中广泛应用。它的高效和灵活性使得数据的传输和解析更加方便和高效。此外,由于具备易读的特性,一些配置文件和参数文件也可以使用 protobuf cson 进行存储和传输。 总而言之,protobuf cson 是一种强大的数据序列化格式,它兼具 Protocol Buffers 和 cson 的优势。通过结构化和紧凑的表示,protobuf cson 提供了高效的数据传输和解析方式,广泛应用于不同领域和语言环境中。 ### 回答3: protobuf是一种数据序列化格式,用于将结构化数据转化为可传输和存储的二进制格式。而CSON则是一种用于存储和表示数据的文本格式,类似于JSON,但更接近于CoffeeScript语法。 protobuf和CSON在功能和用途上有一些差异。protobuf适合用于高效地序列化和反序列化数据,并且可以在多种编程语言之间进行数据交换。它使用二进制格式,因此在数据传输和存储方面更高效,尤其是对于大量数据和复杂结构的数据。protobuf还提供了强大的扩展和版本控制机制,使得在不同版本之间进行数据兼容性处理更加方便。 CSON则更加适用于人类可读和可编辑的数据表示。它使用文本格式并支持类似于CoffeeScript的语法,因此更加容易阅读和理解。与JSON相比,CSON提供了一些额外的功能,比如支持注释和多行字符串。但是,CSON相对于protobuf而言在性能上差一些,因为它需要将文本转换为内部数据结构,并且在解析和生成过程中需要进行额外的处理。 总的来说,如果需要高效的数据传输和存储,或者需要跨多种编程语言进行数据交换,protobuf是更好的选择。而如果需要人类可读和可编辑的数据表示,或者对数据格式有更高的灵活性要求,使用CSON可能更合适。但是,具体使用哪种格式还是要根据具体的应用场景和需求来决定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值