摘要:經過這一節,萬事俱備只欠東風,下一節我們就來完成這個游戲的剩余邏輯,比如接蘋果加分,接到炸彈或蘋果掉到地上游戲結束,還有加入更豐富的音效。
回顧
上一節我們介紹了加載場景,并利用加載好的資源,豐富了開始界面。現在點擊屏幕后仍是一片黑暗,那么,這一節我們就來完成游戲最核心的場景——play。我們要做的是一個接蘋果的游戲,為此我們會加入物理引擎,會使用一些過渡動畫以及監聽觸摸事件等等。
物理引擎幾乎每一個游戲框架都必須具備一個甚至多個物理引擎供開發使用,使用物理引擎可以實現例如碰撞、加減速運動、摩擦力等效果。Phaser非常人性化,提供了3個物理引擎供開發者使用,每個引擎各有自己的特點。下面來簡單介紹一下:
最簡單快速的物理引擎,因為只支持AABB式的碰撞,計算速度最快,實現簡單的物理碰撞、接觸、重力等效果最佳。
關于AABB下面有幾個鏈接可以讓你去理解,全稱是Axis-Aligned Bounding Box,直譯就是軸對稱盒。例如一張星星的圖片,盡管邊上很多透明的部分,但如果使用AABB來計算碰撞的話,則會用一個矩形將星星框住,這樣計算起來非常方便,但精度就比較低。如此一來我們也可以想到,用Arcade構建的body是不可以發生形變的。
相關概念:
What is AABB - Collision detection?
AABB盒
包圍盒算法
如果說Arcade是小而精,P2引擎則是大而全了。各種物理模型均可實現,諸如多邊形、彈簧、摩擦力、碰撞物體的材質、反彈系數等等都可以實現。盡管在性能上有一定消耗,畢竟要做更多復雜的運算,但為了效果,我們也很常用P2,作者引進P2也是由于它的全面。
至于Ninja,則是比較專注精確的多種模式的碰撞檢測。例如凹凸面的碰撞、平面和球的碰撞等等。平常比較少用,有興趣的可以查看官方示例,另外,作者給出引進Ninja的理由是:
It"s a really nice little physics system, supporting AABB and Circle vs. Tile collision, with lots of defs for sloping, convex and concave tile types. But that"s all it does, it"s not trying to be anything more really.
Stack Exchange - Game Development上關于Phaser三個引擎的介紹
Difference between Arcade, P2 and Ninja physics in PhaserPhaser作者寫的,關于物理引擎的介紹:
Explaining Phaser 2"s multiple physics systems
咦?為什么沒有上面沒有提到Box2D?很遺憾,這個引擎是收費的,40刀,如果沒有特別大的需求,估計也用不上。
附上:非常有趣的官方示例,車掉坑里就爬不起來了。
正式開始添加背景
添加主角
添加分數
播放背景音樂
背景音樂的使用:
// 創建背景音樂實例 var bgMusic = game.add.audio("bgMusic"); // 循環播放 bgMusic.loopFull();
注意:
場景的布置和開始場景差不多,在開始場景中我們添加了背景音樂。會有人問,為什么不進入游戲就自動播放,是因為移動端的瀏覽器,必須要用戶操作才能播放音頻。
Safari HTML5 Audio and Video Guide
Warning: To prevent unsolicited downloads over cellular networks at the user’s expense, embedded media cannot be played automatically in Safari on iOS—the user always initiates playback.
另外可參考:
segmentfault上的討論:HTML5的audio標簽設置了autoplay屬性在手機端出現的問題
示例代碼:https://jsfiddle.net/Vincent_...
監聽滑動事件
移動主角位置
主要使用的就是input的addMoveCallback方法:
// 監聽滑動事件 game.input.addMoveCallback(function(pointer, x, y, isTap) { if (!isTap) man.x = x; });
第四個參數非常有用,可以判斷是否為點擊事件,如果是點擊就不移動主角。
示例代碼:https://jsfiddle.net/Vincent_...
很快你就會發覺在PC上主角一直跟著鼠標移動,根本無法停下來!
其實原因也很簡單,在PC端,Phaser的move事件對應的是mousemove;在移動端,對應的是touchmove。這兩個事件有什么區別?主要區別就是touchmove必須手指觸摸屏幕并滑動才會觸發,而mousemove則不需要點住鼠標,只需要移動鼠標就會觸發。
于是,我們來修改一下代碼:
// 是否正在觸摸 var touching = false; // 監聽按下事件 game.input.onDown.add(function() { touching = true; }); // 監聽離開事件 game.input.onUp.add(function() { touching = false; }); // 監聽滑動事件 game.input.addMoveCallback(function(pointer, x, y, isTap) { if (!isTap && touching) man.x = x; });
Good!加入了觸摸標記以后,我們監聽了按下和離開事件,在PC端和移動端的表現一致了!
示例代碼:https://jsfiddle.net/Vincent_...
細心的你多測試了幾下,這時候發現了一個非常詭異的情況,當開始點擊的時候,不是點在主角身上,主角就會瞬移過去!不難理解,因為我們是直接設置主角的x坐標,等于觸摸位置的x坐標的。如果開始時x坐標不在主角身上,就會在一瞬間移動到手指的位置。
于是,我們又來修改一下代碼,非常簡單的一個方法:
// 監聽按下事件 game.input.onDown.add(function(pointer) { // 要判斷是否點住主角,避免瞬移 if (Math.abs(pointer.x - man.x) < man.width / 2) touching = true; });
上述代碼的意思就是,開始觸摸的位置必須在主角的最左邊到最右邊的x坐標范圍內,才算作開始觸摸,否則不算。
Excellent!現在可以隨心所欲地操控你的主角了!
示例代碼:https://jsfiddle.net/Vincent_...
這里用到了Phaser的group,實際上可以理解成是一個數組,只不過更形象,組的常用方法:
add/addChild/addChildAt - 創建成員
countDead/countLiving - 統計成員
forEach/forEachAlive/forEachDead - 遍歷成員
remove/removeAll/removeChildAt - 刪除成員
create - 創建成員
bringToTop - 整個組的元素的圖層提到最上層
另外組本身也有x,y等屬性,也就是說,整個組的成員都可以根據組的偏移值而一起偏移!另外組還提供了很多豐富的方法,活用組可以達到事半功倍的效果。
// 添加蘋果組 var apples = game.add.group(); var green = apples.create(50, 0, "green"); var red = apples.create(150, 0, "red"); var yellow = apples.create(250, 0, "yellow");
示例代碼:https://jsfiddle.net/Vincent_...
上面我們看到有三種蘋果,那么下面我們來實現:每隔一段時間,隨機創建三種蘋果中的一種,并且擺放到不同的位置。
為此我們用到Phaser的timer,用于創建定時任務。會有人問為什么不用setInterval,setTimeout這些,是因為Phaser只要焦點離開了頁面,就會自動暫停游戲,包括定時任務也會暫停,而setInterval和setTimeout則不會。
一般會用到add和loop兩個方法,分別對應setTimeout和setInterval:
我們修改一下代碼:
// 添加蘋果組 var apples = game.add.group(); // 蘋果類型 var appleTypes = ["green", "red", "yellow"]; var appleTimer = game.time.create(true); appleTimer.loop(1000, function() { var x = Math.random() * game.world.width; var y = Math.random() * game.world.height; var type = appleTypes[Math.floor(Math.random() * appleTypes.length)]; apples.create(x, y, type); }); appleTimer.start();
現在每隔1秒就會在屏幕隨機位置出現一個蘋果了,而且種類是隨機的。
示例代碼:https://jsfiddle.net/Vincent_...
這里就要使用到物理引擎了,考慮到接蘋果的游戲對碰撞精度要求不是很高,我們選擇使用Arcade,也就是Phaser默認的物理引擎。
關鍵代碼:
// 開啟物理引擎 game.physics.startSystem(Phaser.Physics.Arcade); game.physics.arcade.gravity.y = 300;
// 設置蘋果加入物理運動 game.physics.enable(apple);
于是,我們繼續修改上面的代碼:
// 添加蘋果組 var apples = game.add.group(); // 蘋果類型 var appleTypes = ["green", "red", "yellow"]; var appleTimer = game.time.create(true); appleTimer.loop(1000, function() { var x = Math.random() * game.world.width; var type = appleTypes[Math.floor(Math.random() * appleTypes.length)]; var apple = apples.create(x, 0, type); // 設置蘋果大小 var appleImg = game.cache.getImage(type); apple.width = game.world.width / 8; apple.height = apple.width / appleImg.width * appleImg.height; // 設置蘋果加入物理運動 game.physics.enable(apple); }); appleTimer.start(); // 開啟物理引擎 game.physics.startSystem(Phaser.Physics.Arcade); game.physics.arcade.gravity.y = 300;
Perfect!現在滿天蘋果都會有了重力,加速掉向地上了。
示例代碼:https://jsfiddle.net/Vincent_...
小結這一節內容比較多,我們首先布置了游戲場景,加入了背景音樂。然后實現了對主角的操作,最后實現了蘋果的隨機掉落。經過這一節,萬事俱備只欠東風,下一節我們就來完成這個游戲的剩余邏輯,比如接蘋果加分,接到炸彈或蘋果掉到地上游戲結束,還有加入更豐富的音效。
游戲截圖:
未完待續Chapter 1 - 認識Phaser.js
Chapter 2 - 搭建游戲的骨架
Chapter 3 - 加載游戲資源
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/82823.html
摘要:回顧上一節我們完成了游戲核心場景的大部分工作,能操控主角,能隨機掉落蘋果了。于是我們修改之前的方法,也就是接到蘋果后的方法。接到炸彈后結束和蘋果掉地上的調用方式是一樣的。 showImg(https://segmentfault.com/img/bVNawu?w=900&h=500); 回顧 上一節我們完成了游戲核心場景play的大部分工作,能操控主角,能隨機掉落蘋果了。那么這一節我們...
摘要:順帶一說,這次的示例是做一個接蘋果的游戲,一句話說完就是控制主角接住每一個從天上掉下來的蘋果,否則就算輸。那么如何利用這些資源構建出游戲的玩法,蘋果怎么掉,怎么控制主角等等,將是下一節的內容。 showImg(https://segmentfault.com/img/bVMWgO?w=900&h=500); 回顧 上一節我們搭建了游戲的骨架,添加了四個游戲場景,分別是加載、開始、游戲、...
閱讀 1320·2021-09-22 15:09
閱讀 2656·2021-08-20 09:38
閱讀 2402·2021-08-03 14:03
閱讀 863·2019-08-30 15:55
閱讀 3368·2019-08-30 12:59
閱讀 3550·2019-08-26 13:48
閱讀 1885·2019-08-26 11:40
閱讀 647·2019-08-26 10:30