讓角色動起來
當鍵盤上特定的按鍵被按下時,爲了讓我們創建的角色同步地動起來,需要讓Gamma來爲我們改變對象水平、垂直方向的位置狀態。在本章節,我們將實現如下功能:
· 鍵盤上向左的方向鍵控制角色往左移動
· 鍵盤上向右的方向鍵控制角色往右移動
· 鍵盤上的空格鍵控制角色跳躍
按鍵碼
首先我們得知道這三個按鍵(左鍵,右鍵和空格鍵)分別對應的鍵碼(譯者注:就是我們所說的按鍵所對應的ASCII碼)。通過查閱鍵碼錶 我可以知道左鍵對應的ASCII碼值是37,右鍵是39,空格是32。
移動角色的函數
然後,我們得弄清楚Gamma提供了哪些函數可以用於改變角色的位置狀態。當遊戲開始後,一旦我們給角色下達了向右移動的按鍵指令,那麼角色就會以一個固定的速率動起來。本例中我們主要會用到Gamma提供的move 和jump 兩個API庫函數。調用move時爲其傳遞LEFT參數實現角色向左移動的功能,同理,讓角色向右移動時只要將move函數的參數改爲RIGHT即可。調用 jump就可以實現角色的跳躍動作。move和jump函數都需要一個按鍵事件的對象作爲其輸入參數。
我們使用Gamma提供的register API爲按鍵註冊響應處理函數。響應處理函數被調用時系統會爲其傳遞一個鍵盤事件,用於區分是按鍵被按下還是按鍵彈起。
gma.keyHandler.register(37, function (keyEvent) {
manager.character.move(gma.constants.LEFT, keyEvent);
});
gma.keyHandler.register(39, function (keyEvent) {
manager.character.move(gma.constants.RIGHT, keyEvent);
});
gma.keyHandler.register(32, manager.character.jump);
爲按鍵註冊消息處理功能的API包含gma.keyHandler包裏,所以在game.js開頭的require函數裏需要導入gma/events依賴包。
科裏化/閉包
上面的代碼不是很優美,我們可以使用Javascript的科裏化功能。科裏化是一種根據輸入參數返回函數的函數,是閉包最偉大的應用之一(譯者注)。例如下面的(f1 和f2)函數是等價的。創建f2時,根據其第一個輸入參數對其進行科裏化之後,就只需要一個按鍵事件作爲其輸入參數就可以了:
f1 = function (keyEvent) {
manager.character.move(gma.constants.LEFT, keyEvent);
};
f2 = manager.character.move.curry(gma.constants.LEFT);
所以,前面關於按鍵消息處理函數的註冊代碼可以簡化成:
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);
最終示範代碼
require([
'gma/base',
'gma/manager',
'gma/entities/character',
'gma/events'
],
function(gma) {
var manager = gma.manager({
width : 600,
height : 500
});
manager.character = gma.character({
left : 0,
bottom : 0,
width : 3,
height : 6,
depth : 3
});
var myLevel = {
spawn : {
main : [15, 24]
},
entities : [
{top:0, left:0, width:30, height:3},
{top:0, left:36, width:30, height:3}
]
};
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();
}
);
添加障礙
Gamma也提供了一些用於定義障礙的對象,這些對象都有自己的行爲方式。如果要在遊戲關卡里添加障礙,必須將其放置在一個數組裏。
在本篇中,我們會用gma.platformEnemy創建一個從一邊移動到另一邊的場景障礙,用gma.patrolEnemy創建一個在兩點之間移動的巡邏障礙,以及用gma.jumpingEnemy創建一些不斷跳躍的障礙物:
entities : [
gma.platformEnemy({bottom:0, left:45, width:3, height:6}),
gma.patrolEnemy({bottom:0, left:6, width:3, height:6, limitLeft: 3, limitRight:12}),
gma.jumpingEnemy ({bottom:0, left:7, width:1, height:2}),
gma.jumpingEnemy ({bottom:3, left:8, width:1, height:2}),
gma.jumpingEnemy ({bottom:6, left:9, width:1, height:2})
]
場景障礙和跳躍的障礙只需要限定其大小和位置即可,而巡邏障礙還需要設置它巡邏時的範圍,即最大左右邊界點limitLeft 和 limitRight。
類型
如果以普通屬性來創建遊戲中的障礙物,可以將其設置成一個用戶自定義類型。在創建障礙時來引用該類型以降低代碼冗餘。我們用addCustomDefinitions來定義類型。例如:
manager.addCustomDefinitions({
types : {
jumpingJack: ['jumpingEnemy', {
width : 1,
height : 2
}]
}
});
在定義障礙的類型時,需要將其放在數組裏,且數組的第一個元素是類名,用它來實例化一個具體的對象,例如我們所要創建gma.jumpingEnemy的跳躍障礙的對象;數組的第二個參數是一個對象,該對象裏包含了一些屬性值,這些屬性會被應用到所有實例化的對象上面。
下面我們通過引用上面定義的jumpingJack類型來重新創建跳躍障礙:
// 此時,引用自定義類型junpingJack
entities : [
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}
]
提示
後面我們不再顯式的調用gma.jumpingEnemy函數來創建跳躍障礙,而是通過設置其寬、高屬性來定義它們。因爲我們已經有了類型這個神奇的法寶(譯者注)。
模板
默認情況下,所有被創建出來的障礙都是一個藍色的方形柱體結構,這是由對象的模板屬性決定的。對象的缺省模板是一個立方體,可以用下面的方法來設置其模板屬性(雖然這一步操作顯得多此一舉):
manager.addCustomDefinitions({
types : {
jumpingJack: ['jumpingEnemy', {
width : 1,
height : 2
template : 'cube'
}
}
});
如果需要自定義障礙的外觀,就必須通過創建模板來實現。下面的代碼中,我們用模板助手gma.meshTemplate創建了一個綠色的方柱體的模板:
manager.addCustomDefinitions({,
templates : {
greencube : ['meshTemplate', {
mesh : gma.unitCubeInfo.mesh,
material : {color : "#090"} // 非常的綠
}
}
});
讓後將這個模板應用到前面定義的jumpingJack類型裏:
manager.addCustomDefinitions({
types : {
jumpingJack: ['jumpingEnemy', {
width : 1,
height : 2
template : 'greencube'
}
}
});
提示
默認情況下,Gamma已經提供了藍色和紅色模板,可以使我們很方便的就創建紅色和藍色立方體。在外觀 章節的目錄裏,有模板對象類型的詳細介紹,以及它們的用法。
另外,Gamma中的遊戲障礙缺省情況下都有一個默認的類型,使用藍色模板定義的一個平臺障礙gma.platform。
最終示範代碼
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
});
manager.addCustomDefinitions({
templates : {
greencube : ['meshTemplate', {
mesh : gma.unitCubeInfo.mesh,
material : {color : "#090"}
}]
},
types : {
jumpingJack: ['jumpingEnemy', {
width : 1,
height : 2,
template : 'greencube'
}]
}
});
var myLevel = {
spawn : {
main : [15, 24]
},
entities : [
{top:0, left:0, width:30, height:3},
{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();
}
);
自定義視角
Gamma創建的默認視角是跟隨角色一起移動的,位於角色前50個單位,z座標也是50。
在關卡里我們可以在camera標籤裏設置其屬性值來改變視角。在每個關卡里只需設置一個視角。注意:如果在你的關卡里提供了新視角,那麼Gamma提供的默認視角將會被覆蓋。
下面這段代碼的效果和缺省視角的效果是等效的:
var myLevel = {
camera : {
locZ : 50,
attached : ['character']
}
};
接下來,我們設置一個距離角色稍微遠一點點,並且總是比角色只高那麼一丁點的視角:
var myLevel = {
camera : {
locZ : 60,
attached : ['character',0, 6]
}
};