使用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: