使用Collada
Collada 是基于XML文件格式建模的开放标准(译者注:最早由SONY公司提出,是一种基于XML的文件格式,它能提供快速的3D图片交换,它将允许设计者自由地在各个平台中交换数据。已经被认可成为数字娱乐工业的标准),很多3D建模软件都支持将其模型文件导出为这种格式,后缀名是.dae的文件。
在本章节,我们用一个大猩猩模型来替换我们前面创建的角色对象。 下载大猩猩模型 文件和大猩猩纹理文件,并将它们放在同一个目录里:
创建collada模板
为了将我们的模型文件转换成对象,需要重新定义一个模板。我们用gma.colladaTemplate函数从一个collada文件里生成我们所需的3D对象。在如下的定义模板的代码段中,我们定义了一个名为gorilla的模板对象,以及所使用的collada文件:
manager.addCustomDefinitions({
templates : {
gorilla : ['colladaTemplate',
{
collada : {
document : 'gorilla.dae'
}
}
]
}
})
然而,不幸的是我们所创建的大猩猩脸的朝向不太对,而且也不在场景的最中间。为了解决这个问题,我们要将模型旋转180o(约1.57弧度),向下移动0.5个单位并水平缩放0.7倍:
manager.addCustomDefinitions({
templates : {
gorilla : ['colladaTemplate',
{
collada : {
document : 'gorilla.dae'
},
yRot : 1.57,
yOffset : -0.5,
yScale : 0.7
}
]
}
})
提示
加载Collada文件时,必须通过WEB服务器来访问game.js和collada模型文件才可以看到效果。通过本地文件系统来访问,即如果浏览器中的地址栏是以"file:///"开头的地址是不会生效的,你必须将所有文件部署到诸Apache, Lighttpd 或IIS如等web服务上才可以。
将模板和角色关联起来
要将上面创建的模板和角色对象关联起来,下面这几行代码就搞定:
manager.character = gma.character({
left : 0,
bottom : 0,
width : 3,
height : 6,
depth : 3,
template : 'gorilla'
});
最终示范代码
require([
'gma/base',
'gma/manager',
'gma/entities/character',
'gma/events',
'gma/entities/enemy'
],
function(gma) {
var manager = gma.manager({
width : 600,
height : 500
});
manager.character = gma.character({
left : 0,
bottom : 0,
width : 3,
height : 6,
depth : 3,
template : 'gorilla'
});
manager.addCustomDefinitions({
templates : {
greencube : ['meshTemplate', {
mesh : gma.unitCubeInfo.mesh,
material : {color : "#090"}
}],
brickscube : ['meshTemplate', {
mesh : gma.unitCubeInfo.mesh,
texture : {
src:'bricks.jpg',
repeatX:0.5,
repeatY:0.5
}
}],
gorilla : ['colladaTemplate',
{
collada : {
document : 'gorilla.dae'
},
yRot : 1.57,
yOffset : -0.5,
yScale : 0.7
}
]
},
types : {
jumpingJack: ['jumpingEnemy', {
width : 1,
height : 2,
template : 'greencube'
}]
}
});
var myLevel = {
spawn : {
main : [15, 24]
},
camera : {
attached : ['character', 0, 6, 60]
},
light : {
myLight : {
type : GLGE.L_POINT,
rotY : 1.54,
color : "#fff",
attached : ['character', 0,5,20]
}
},
entities : [
{template:'brickscube', top:0, left:0, width:30, height:3},
{template:'brickscube', top:0, left:39, width:30, height:3},
gma.platformEnemy({bottom:0, left:45, width:3, height:6}),
gma.patrolEnemy({bottom:0, left:6, width:3, height:6, limitLeft: 3, limitRight:12}),
{type:'jumpingJack', bottom:0, left:21},
{type:'jumpingJack', bottom:3, left:24},
{type:'jumpingJack', bottom:6, left:27}
]
};
manager.storeLevels(myLevel);
gma.keyHandler.register(37, manager.character.move.curry(gma.constants.LEFT));
gma.keyHandler.register(39, manager.character.move.curry(gma.constants.RIGHT));
gma.keyHandler.register(32, manager.character.jump);
manager.init();
}
);
创建多级关卡
创建多级关卡时需要多定义个关卡对象。例如:
var myLevel = {
//specification
};
var anotherLevel = {
//specification
};
需要多次调用storeLevels函数,每次传递一个关卡对象给它:
manager.storeLevels(myLevel);
manager.storeLevels(anotherLevel);
或者将所有关卡对象放在一个数组里,仅调用一次storeLevels方法即可:
manager.storeLevels([myLevel, anotherLevel]);
当manager.init()方法被调用时,第一个关卡对象会被加载。与此同时,我们可以通过一个“门”来实现从一个关卡到另一个关卡的切换。
创建“门”
Gamma提供了对象。在关卡中,如果角色碰到这个门,Gamma管理器会将我们的角色载入到另外一个关卡里。
为了在关卡中添加门,必须导入依赖包gma/entities/door。然后指定gma.door的大小,以及当角色碰到门以后需要将其带到哪个关卡等参数。门应该被添加到myLevel关卡的entities列表中,如下:
entities : [
gma.door({
bottom:0, left:5, width:3, height:3,
level:1
})
]
提示
门的level属性值决定了哪一个新的关卡将会被加载。JavaScript中的数组下标是从0开始,第一个元素下标是0,第二个元素下标是1,以此类推。关卡的编号是按照其被添加的顺序依次累加的,如下:
manager.storeLevels([myLevel, anotherLevel]);
manager.storeLevels(hardLevel);
// 关卡:0 加载后 myLevel, 其下标是 0
// 关卡:1 加载后anotherLevel, 其下标是1
// 关卡:2 加载后hardLevel, 其下标是2
创建另一个关卡
下面创建第二个关卡,现在我的游戏中包含了一个门,当角色碰到它后会被带回到第一个关卡中:
var otherLevel = {
spawn : {
main : [0, 0]
},
camera : {
attached : ['character', 0, 6, 60]
},
light : {
myLight : {
type : GLGE.L_POINT,
rotY : 1.54,
color : "#fff",
attached : ['character', 0,5,20]
}
},
entities : [
gma.door({bottom:0, left:25, width:0.5, height:9, level:0}),
{template:'brickscube', top:0, left:0, width:30, height:3}
]
};
在场景中存储了myLevel后,再存储otherLevel :
manager.storeLevels(myLevel); // 关卡:0
manager.storeLevels(otherLevel); // 关卡:1
最终示范代码
在最终示范代码中,我们的大猩猩可以通过门在两个关卡里互相切换(译者注:源代码有BUG,下面的代码译者已修改调试通过。):
require([
'gma/base',
'gma/manager',
'gma/entities/character',
'gma/events',
'gma/entities/enemy',
'gma/entities/door'
], function(gma) {
var manager = gma.manager({
width : 600,
height : 500
});
manager.character = gma.character({
left : 0,
bottom : 0,
width : 3,
height : 6,
depth : 3,
template : 'gorilla'
});
manager.addCustomDefinitions({
templates : {
greencube : ['meshTemplate', {
mesh : gma.unitCubeInfo.mesh,
material : {color : "#090"}
}],
brickscube : ['meshTemplate', {
mesh : gma.unitCubeInfo.mesh,
material : {
texture:'bricks.jpg'
//texture : 'bricks.jpg',
//This will make the bricks double the size
//repeatX : 0.5,
//repeatY : 0.5
}
}],
gorilla : ['colladaTemplate',
{
collada : {
document : 'gorilla.dae'
},
yRot : 1.57,
yOffset : -0.5,
yScale : 0.7
}
]
},
types : {
jumpingJack: ['jumpingEnemy', {
width : 1,
height : 2,
template : 'greencube'
}]
}
});
var myLevel = {
spawn : {
main : [15, 24]
},
camera : {
locZ : 60,
attached : ['character',0, 6]
},
light : {
myLight : {
type : GLGE.L_POINT,
rotY : 1.54,
color : "#fff",
attached : ['character', 0,5,20]
}
},
entities : [
gma.door({bottom:0, left:25, width:0.5, height:9, level:1}),
{template:'brickscube',top:0, left:0, width:30, height:3},
{template:'brickscube',top:0, left:39, width:30, height:3},
gma.platformEnemy({bottom:0, left:45, width:3, height:6}),
gma.patrolEnemy({bottom:0, left:6, width:3, height:6, limitLeft: 3, limitRight:12}),
{type:'jumpingJack', bottom:0, left:21},
{type:'jumpingJack', bottom:3, left:24},
{type:'jumpingJack', bottom:6, left:27}
]
};
var otherLevel = {
spawn : {
main : [0, 0]
},
camera : {
attached : ['character', 0, 6, 60]
},
light : {
myLight : {
type : GLGE.L_POINT,
rotY : 1.54,
color : "#fff",
attached : ['character', 0,5,20]
}
},
entities : [
gma.door({bottom:0, left:25, width:0.5, height:9, level:0}),
{template:'brickscube', top:0, left:0, width:30, height:3}
]
};
manager.storeLevels(myLevel);
manager.storeLevels(otherLevel);
gma.keyHandler.register(37, manager.character.move.curry(gma.constants.LEFT));
gma.keyHandler.register(39, manager.character.move.curry(gma.constants.RIGHT));
gma.keyHandler.register(32, manager.character.jump);
manager.init();
}
);
最终游戏效果如下:
初始时位于关卡0 mylevel:
碰到时空穿梭门后到到关卡1 otherLevel: