亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

從零到一:用Phaser.js寫意地開發(fā)小游戲(Chapter 4 - 游戲即將開始)

Miyang / 2051人閱讀

摘要:經(jīng)過(guò)這一節(jié),萬(wàn)事俱備只欠東風(fēng),下一節(jié)我們就來(lái)完成這個(gè)游戲的剩余邏輯,比如接蘋果加分,接到炸彈或蘋果掉到地上游戲結(jié)束,還有加入更豐富的音效。

回顧

上一節(jié)我們介紹了加載場(chǎng)景,并利用加載好的資源,豐富了開始界面?,F(xiàn)在點(diǎn)擊屏幕后仍是一片黑暗,那么,這一節(jié)我們就來(lái)完成游戲最核心的場(chǎng)景——play。我們要做的是一個(gè)接蘋果的游戲,為此我們會(huì)加入物理引擎,會(huì)使用一些過(guò)渡動(dòng)畫以及監(jiān)聽觸摸事件等等。

物理引擎

幾乎每一個(gè)游戲框架都必須具備一個(gè)甚至多個(gè)物理引擎供開發(fā)使用,使用物理引擎可以實(shí)現(xiàn)例如碰撞、加減速運(yùn)動(dòng)、摩擦力等效果。Phaser非常人性化,提供了3個(gè)物理引擎供開發(fā)者使用,每個(gè)引擎各有自己的特點(diǎn)。下面來(lái)簡(jiǎn)單介紹一下:

Arcade

最簡(jiǎn)單快速的物理引擎,因?yàn)橹恢С諥ABB式的碰撞,計(jì)算速度最快,實(shí)現(xiàn)簡(jiǎn)單的物理碰撞、接觸、重力等效果最佳。

關(guān)于AABB下面有幾個(gè)鏈接可以讓你去理解,全稱是Axis-Aligned Bounding Box,直譯就是軸對(duì)稱盒。例如一張星星的圖片,盡管邊上很多透明的部分,但如果使用AABB來(lái)計(jì)算碰撞的話,則會(huì)用一個(gè)矩形將星星框住,這樣計(jì)算起來(lái)非常方便,但精度就比較低。如此一來(lái)我們也可以想到,用Arcade構(gòu)建的body是不可以發(fā)生形變的。

相關(guān)概念:

What is AABB - Collision detection?

AABB盒

包圍盒算法

P2

如果說(shuō)Arcade是小而精,P2引擎則是大而全了。各種物理模型均可實(shí)現(xiàn),諸如多邊形、彈簧、摩擦力、碰撞物體的材質(zhì)、反彈系數(shù)等等都可以實(shí)現(xiàn)。盡管在性能上有一定消耗,畢竟要做更多復(fù)雜的運(yùn)算,但為了效果,我們也很常用P2,作者引進(jìn)P2也是由于它的全面。

Ninja

至于Ninja,則是比較專注精確的多種模式的碰撞檢測(cè)。例如凹凸面的碰撞、平面和球的碰撞等等。平常比較少用,有興趣的可以查看官方示例,另外,作者給出引進(jìn)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上關(guān)于Phaser三個(gè)引擎的介紹
Difference between Arcade, P2 and Ninja physics in Phaser

Phaser作者寫的,關(guān)于物理引擎的介紹:
Explaining Phaser 2"s multiple physics systems

Box2D

咦?為什么沒(méi)有上面沒(méi)有提到Box2D?很遺憾,這個(gè)引擎是收費(fèi)的,40刀,如果沒(méi)有特別大的需求,估計(jì)也用不上。

附上:非常有趣的官方示例,車掉坑里就爬不起來(lái)了。

正式開始
第一步:先布置好場(chǎng)景

添加背景

添加主角

添加分?jǐn)?shù)

播放背景音樂(lè)

背景音樂(lè)的使用:

// 創(chuàng)建背景音樂(lè)實(shí)例
var bgMusic = game.add.audio("bgMusic");
// 循環(huán)播放
bgMusic.loopFull();

注意:

場(chǎng)景的布置和開始場(chǎng)景差不多,在開始場(chǎng)景中我們添加了背景音樂(lè)。會(huì)有人問(wèn),為什么不進(jìn)入游戲就自動(dòng)播放,是因?yàn)橐苿?dòng)端的瀏覽器,必須要用戶操作才能播放音頻。

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標(biāo)簽設(shè)置了autoplay屬性在手機(jī)端出現(xiàn)的問(wèn)題

示例代碼:https://jsfiddle.net/Vincent_...

第二步:讓你的主角動(dòng)起來(lái)

監(jiān)聽滑動(dòng)事件

移動(dòng)主角位置

主要使用的就是input的addMoveCallback方法:

// 監(jiān)聽滑動(dòng)事件
game.input.addMoveCallback(function(pointer, x, y, isTap) {
    if (!isTap) man.x = x;
});

第四個(gè)參數(shù)非常有用,可以判斷是否為點(diǎn)擊事件,如果是點(diǎn)擊就不移動(dòng)主角。

示例代碼:https://jsfiddle.net/Vincent_...

就這么簡(jiǎn)單?NO,NO,NO

很快你就會(huì)發(fā)覺在PC上主角一直跟著鼠標(biāo)移動(dòng),根本無(wú)法停下來(lái)!

其實(shí)原因也很簡(jiǎn)單,在PC端,Phaser的move事件對(duì)應(yīng)的是mousemove;在移動(dòng)端,對(duì)應(yīng)的是touchmove。這兩個(gè)事件有什么區(qū)別?主要區(qū)別就是touchmove必須手指觸摸屏幕并滑動(dòng)才會(huì)觸發(fā),而mousemove則不需要點(diǎn)住鼠標(biāo),只需要移動(dòng)鼠標(biāo)就會(huì)觸發(fā)。

于是,我們來(lái)修改一下代碼:

// 是否正在觸摸
var touching = false;
// 監(jiān)聽按下事件
game.input.onDown.add(function() {
    touching = true;
});
// 監(jiān)聽離開事件
game.input.onUp.add(function() {
    touching = false;
});
// 監(jiān)聽滑動(dòng)事件
game.input.addMoveCallback(function(pointer, x, y, isTap) {
    if (!isTap && touching) man.x = x;
});

Good!加入了觸摸標(biāo)記以后,我們監(jiān)聽了按下和離開事件,在PC端和移動(dòng)端的表現(xiàn)一致了!

示例代碼:https://jsfiddle.net/Vincent_...

這樣算完事了?NO,NO,NO

細(xì)心的你多測(cè)試了幾下,這時(shí)候發(fā)現(xiàn)了一個(gè)非常詭異的情況,當(dāng)開始點(diǎn)擊的時(shí)候,不是點(diǎn)在主角身上,主角就會(huì)瞬移過(guò)去!不難理解,因?yàn)槲覀兪侵苯釉O(shè)置主角的x坐標(biāo),等于觸摸位置的x坐標(biāo)的。如果開始時(shí)x坐標(biāo)不在主角身上,就會(huì)在一瞬間移動(dòng)到手指的位置。

于是,我們又來(lái)修改一下代碼,非常簡(jiǎn)單的一個(gè)方法:

// 監(jiān)聽按下事件
game.input.onDown.add(function(pointer) {
    // 要判斷是否點(diǎn)住主角,避免瞬移
    if (Math.abs(pointer.x - man.x) < man.width / 2) touching = true;
});

上述代碼的意思就是,開始觸摸的位置必須在主角的最左邊到最右邊的x坐標(biāo)范圍內(nèi),才算作開始觸摸,否則不算。

Excellent!現(xiàn)在可以隨心所欲地操控你的主角了!

示例代碼:https://jsfiddle.net/Vincent_...

第三步:讓蘋果掉下來(lái)吧
先來(lái)創(chuàng)造幾個(gè)蘋果看看

這里用到了Phaser的group,實(shí)際上可以理解成是一個(gè)數(shù)組,只不過(guò)更形象,組的常用方法:

add/addChild/addChildAt - 創(chuàng)建成員

countDead/countLiving - 統(tǒng)計(jì)成員

forEach/forEachAlive/forEachDead - 遍歷成員

remove/removeAll/removeChildAt - 刪除成員

create - 創(chuàng)建成員

bringToTop - 整個(gè)組的元素的圖層提到最上層

另外組本身也有x,y等屬性,也就是說(shuō),整個(gè)組的成員都可以根據(jù)組的偏移值而一起偏移!另外組還提供了很多豐富的方法,活用組可以達(dá)到事半功倍的效果。

// 添加蘋果組
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_...

定時(shí)隨機(jī)創(chuàng)造蘋果

上面我們看到有三種蘋果,那么下面我們來(lái)實(shí)現(xiàn):每隔一段時(shí)間,隨機(jī)創(chuàng)建三種蘋果中的一種,并且擺放到不同的位置。

為此我們用到Phaser的timer,用于創(chuàng)建定時(shí)任務(wù)。會(huì)有人問(wèn)為什么不用setInterval,setTimeout這些,是因?yàn)镻haser只要焦點(diǎn)離開了頁(yè)面,就會(huì)自動(dòng)暫停游戲,包括定時(shí)任務(wù)也會(huì)暫停,而setInterval和setTimeout則不會(huì)。

一般會(huì)用到addloop兩個(gè)方法,分別對(duì)應(yīng)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();

現(xiàn)在每隔1秒就會(huì)在屏幕隨機(jī)位置出現(xiàn)一個(gè)蘋果了,而且種類是隨機(jī)的。

示例代碼:https://jsfiddle.net/Vincent_...

最后,我們讓蘋果掉下來(lái)

這里就要使用到物理引擎了,考慮到接蘋果的游戲?qū)ε鲎簿纫蟛皇呛芨?,我們選擇使用Arcade,也就是Phaser默認(rèn)的物理引擎。

關(guān)鍵代碼:

// 開啟物理引擎
game.physics.startSystem(Phaser.Physics.Arcade);
game.physics.arcade.gravity.y = 300;
// 設(shè)置蘋果加入物理運(yùn)動(dòng)
game.physics.enable(apple);

于是,我們繼續(xù)修改上面的代碼:

// 添加蘋果組
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);
    // 設(shè)置蘋果大小
    var appleImg = game.cache.getImage(type);
    apple.width = game.world.width / 8;
    apple.height = apple.width / appleImg.width * appleImg.height;
    // 設(shè)置蘋果加入物理運(yùn)動(dòng)
    game.physics.enable(apple);
});
appleTimer.start();
// 開啟物理引擎
game.physics.startSystem(Phaser.Physics.Arcade);
game.physics.arcade.gravity.y = 300;

Perfect!現(xiàn)在滿天蘋果都會(huì)有了重力,加速掉向地上了。

示例代碼:https://jsfiddle.net/Vincent_...

小結(jié)

這一節(jié)內(nèi)容比較多,我們首先布置了游戲場(chǎng)景,加入了背景音樂(lè)。然后實(shí)現(xiàn)了對(duì)主角的操作,最后實(shí)現(xiàn)了蘋果的隨機(jī)掉落。經(jīng)過(guò)這一節(jié),萬(wàn)事俱備只欠東風(fēng),下一節(jié)我們就來(lái)完成這個(gè)游戲的剩余邏輯,比如接蘋果加分,接到炸彈或蘋果掉到地上游戲結(jié)束,還有加入更豐富的音效。

游戲截圖:

未完待續(xù)
回顧:

Chapter 1 - 認(rèn)識(shí)Phaser.js

Chapter 2 - 搭建游戲的骨架

Chapter 3 - 加載游戲資源

下一節(jié):Chapter 5 - 游戲大功告成

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/82823.html

相關(guān)文章

  • 從零到一Phaser.js寫意開發(fā)游戲Chapter 5 - 游戲大功告成)

    摘要:回顧上一節(jié)我們完成了游戲核心場(chǎng)景的大部分工作,能操控主角,能隨機(jī)掉落蘋果了。于是我們修改之前的方法,也就是接到蘋果后的方法。接到炸彈后結(jié)束和蘋果掉地上的調(diào)用方式是一樣的。 showImg(https://segmentfault.com/img/bVNawu?w=900&h=500); 回顧 上一節(jié)我們完成了游戲核心場(chǎng)景play的大部分工作,能操控主角,能隨機(jī)掉落蘋果了。那么這一節(jié)我們...

    Jeff 評(píng)論0 收藏0
  • 從零到一Phaser.js寫意開發(fā)游戲Chapter 3 - 加載游戲資源)

    摘要:順帶一說(shuō),這次的示例是做一個(gè)接蘋果的游戲,一句話說(shuō)完就是控制主角接住每一個(gè)從天上掉下來(lái)的蘋果,否則就算輸。那么如何利用這些資源構(gòu)建出游戲的玩法,蘋果怎么掉,怎么控制主角等等,將是下一節(jié)的內(nèi)容。 showImg(https://segmentfault.com/img/bVMWgO?w=900&h=500); 回顧 上一節(jié)我們搭建了游戲的骨架,添加了四個(gè)游戲場(chǎng)景,分別是加載、開始、游戲、...

    BingqiChen 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<