SceneKit框架詳細(xì)解析(六) —— 基于SceneKit的簡(jiǎn)單游戲示例的實(shí)現(xiàn)(五)

版本記錄

版本號(hào) 時(shí)間
V1.0 2018.10.20 星期六

前言

SceneKit使用高級(jí)場(chǎng)景描述創(chuàng)建3D游戲并將3D內(nèi)容添加到應(yīng)用程序。 輕松添加動(dòng)畫(huà),物理模擬,粒子效果和逼真的基于物理性的渲染。接下來(lái)這幾篇我們就詳細(xì)的解析一下這個(gè)框架。感興趣的看下面幾篇文章。
1. SceneKit框架詳細(xì)解析(一) —— 基本概覽(一)
2. SceneKit框架詳細(xì)解析(二) —— 基于SceneKit的簡(jiǎn)單游戲示例的實(shí)現(xiàn)(一)
3. SceneKit框架詳細(xì)解析(三) —— 基于SceneKit的簡(jiǎn)單游戲示例的實(shí)現(xiàn)(二)
4. SceneKit框架詳細(xì)解析(四) —— 基于SceneKit的簡(jiǎn)單游戲示例的實(shí)現(xiàn)(三)
5. SceneKit框架詳細(xì)解析(五) —— 基于SceneKit的簡(jiǎn)單游戲示例的實(shí)現(xiàn)(四)

開(kāi)始

在這部分中,您將為游戲添加一些很酷的粒子系統(tǒng)并將其包裝起來(lái)!

想象自己在電影院里手持爆米花;在屏幕上,一個(gè)來(lái)自“速度與激情”的壞人將他咆哮的高性能高速賽車(chē)撞到一輛高度不穩(wěn)定的油輪上,這輛油輪在一場(chǎng)巨大的死亡和大屠殺火球中爆炸。

現(xiàn)在,想想同樣的場(chǎng)景,但沒(méi)有大規(guī)模的火球爆炸。 你幾乎可以感受到世界各地觀眾的集體失望。

就像好萊塢大片一樣,你的游戲需要特效來(lái)提升興奮程度。 這些特殊效果以所謂的粒子系統(tǒng)(particle systems)的形式出現(xiàn)。 您可以使用粒子系統(tǒng)來(lái)實(shí)現(xiàn)多種效果,從移動(dòng)星空,燃燒火箭助推器,到雨雪,到金屬火花 - 甚至是大型爆炸火球!

現(xiàn)在是時(shí)候看看如何將這些整潔的特效添加到Geometry Fighter中。


Particle Systems - 粒子系統(tǒng)

SceneKit中,SCNParticleSystem管理場(chǎng)景圖中粒子的創(chuàng)建,動(dòng)畫(huà)和移除。

粒子本質(zhì)上是一個(gè)小圖像精靈。粒子系統(tǒng)不會(huì)將單個(gè)粒子添加到場(chǎng)景圖本身中,因此您無(wú)法直接訪問(wèn)每個(gè)粒子;粒子系統(tǒng)管理粒子,包括它們的外觀,大小和位置。

但是,您可以通過(guò)修改粒子系統(tǒng)上的各種屬性來(lái)影響粒子系統(tǒng),例如:

  • Appearance - 外觀:系統(tǒng)的每個(gè)粒子都可以渲染為單個(gè)圖像或動(dòng)畫(huà)圖像序列。您可以調(diào)整生成的粒子的大小,色調(diào)顏色,混合模式和其他渲染參數(shù)。
  • Life Span - 壽命:系統(tǒng)使用粒子發(fā)射器(particle emitter),它產(chǎn)生每個(gè)單獨(dú)的粒子。粒子的壽命決定了它在場(chǎng)景中保持可見(jiàn)的時(shí)間。
  • Emitter behavior - 發(fā)射器行為:您可以控制發(fā)射器的各種參數(shù),例如粒子生成的位置和生成率。
  • Variation - 變化:在粒子系統(tǒng)中引入變體可以使其看起來(lái)更多或更少,隨機(jī)。
  • Movement - 移動(dòng):您可以調(diào)整粒子在生成后的移動(dòng)方式。粒子使用簡(jiǎn)化的物理模擬來(lái)加速性能,但粒子仍然可以與物理引擎管理的對(duì)象進(jìn)行交互。

1. Creating a Trail Particle System - 創(chuàng)建跟蹤粒子系統(tǒng)

在將粒子系統(tǒng)添加到游戲世界之前,您需要一個(gè)組來(lái)容納此粒子系統(tǒng)以保持項(xiàng)目的有序性。 右鍵單擊GeometryFighter組并選擇New Group,如下所示:

將此新組命名為Particles。 右鍵單擊該組,然后選擇New File。 選擇iOS/Resource/SceneKit Particle System,然后單擊Next繼續(xù):

在下一個(gè)屏幕上,選擇Particle system templateFire,然后單擊Next。 將文件另存為Trail.scnp,然后單擊Create。 完成后,您應(yīng)該在場(chǎng)景中看到以下內(nèi)容:

以下是上面注釋的編輯器各個(gè)部分的快速概述:

  • 1) Center stage - 中心面板:中心擁有您的粒子系統(tǒng)的直觀表示。您可以使用它來(lái)了解最終結(jié)果的樣子。
  • 2) Gesture controls - 手勢(shì)控件:您可以使用手勢(shì)來(lái)操作相機(jī)視圖;它類(lèi)似于你在場(chǎng)景中移動(dòng)相機(jī)的方式。
  • 3) Pause/Play button - 暫停/播放按鈕:您可以暫停粒子系統(tǒng)模擬并更詳細(xì)地檢查它。暫停時(shí),停按鈕變?yōu)椴シ虐粹o,您可以使用該按鈕恢復(fù)模擬。
  • 4) Restart button - 重啟按鈕:這使您可以從頭開(kāi)始重新啟動(dòng)粒子模擬。
  • 5) Camera reset button - 相機(jī)重置按鈕:使用此按鈕將相機(jī)視圖重置為默認(rèn)位置。
  • 6) Color button - 顏色按鈕:這可讓您為編輯器設(shè)置合適的背景顏色;例如,在黑色背景下看雪花更容易。
  • 7) Particle system properties - 粒子系統(tǒng)屬性:選擇Attributes Inspector會(huì)顯示一系列屬性,您將在下一節(jié)中了解這些屬性。

2. Configuring the Trail Particle System - 配置跟蹤粒子系統(tǒng)

在本節(jié)中,您將深入了解編輯器右側(cè)的粒子系統(tǒng)屬性。 在瀏覽每個(gè)部分時(shí),將屏幕截圖中每個(gè)設(shè)置的值復(fù)制到您自己的粒子系統(tǒng)中。

在更改每個(gè)屬性時(shí),請(qǐng)密切關(guān)注粒子系統(tǒng)編輯器;您將看到每個(gè)參數(shù)如何影響粒子系統(tǒng)的行為。 稍后,您將在游戲中使用此粒子效果來(lái)創(chuàng)建從生成的對(duì)象落下的粒子痕跡。

3. Emitter Attributes - 發(fā)射器屬性

粒子發(fā)射器是所有粒子產(chǎn)生的原點(diǎn)。 以下是發(fā)射器屬性:

  • Birth rate - 出生率:控制粒子的排放率。將其設(shè)置為25,指示粒子引擎以每秒25個(gè)粒子的速率生成新粒子。
  • Warmup duration - 預(yù)熱持續(xù)時(shí)間:模擬在渲染粒子之前運(yùn)行的秒數(shù)。這可以用于在開(kāi)始時(shí)顯示充滿(mǎn)粒子的屏幕,而不是等待粒子填滿(mǎn)屏幕。將其設(shè)置為0,以便可以從一開(kāi)始就查看模擬。
  • Location - 位置:相對(duì)于形狀的位置,發(fā)射器產(chǎn)生其粒子的位置。將其設(shè)置為Vertex,這意味著粒子將使用幾何頂點(diǎn)作為生成位置。
  • Emission space - 發(fā)射空間:發(fā)射粒子所在的空間。將其設(shè)置為World Space,以便將發(fā)射的粒子發(fā)射到世界空間,而不是對(duì)象節(jié)點(diǎn)本身的局部空間。
  • Direction mode - 方向模式:控制衍生粒子的傳播方式;你可以將它們?nèi)恳苿?dòng)到一個(gè)恒定的方向,讓它們從形狀表面徑向向外移動(dòng),或者只是隨機(jī)移動(dòng)它們。將其設(shè)置為常量,使所有發(fā)射的粒子保持恒定方向。
  • Direction - 方向:指定方向模式恒定時(shí)使用的初始方向向量。將此向量設(shè)置為(x:0,y:0,z:0),將方向設(shè)置為空。
  • Spreading angle - 擴(kuò)散角度:隨機(jī)化產(chǎn)生的粒子的發(fā)射角度。將其設(shè)置為0°,從而精確地在先前設(shè)定的方向上發(fā)射粒子。
  • Initial angle - 初始角度:發(fā)射粒子的初始角度。將其設(shè)置為0°,因?yàn)檫@與零方向矢量無(wú)關(guān)。
  • Shape - 形狀:發(fā)射粒子的形狀。將形狀設(shè)置為球體(Sphere),因此使用球體形狀作為幾何體。
  • Shape radius - 形狀半徑:此屬性的存在取決于您使用的形狀;對(duì)于球形發(fā)射器,這決定了球體的大小。將其設(shè)置為0.2,它定義了一個(gè)足夠大的球體,以滿(mǎn)足您的需要。

注意:請(qǐng)注意,某些屬性有兩個(gè)輸入?yún)^(qū)域,其中一個(gè)區(qū)域旁邊有一個(gè)Δ=符號(hào)(請(qǐng)參閱Birth Rate and Initial angle)。第一個(gè)輸入?yún)^(qū)域包含基值,Δ=輸入?yún)^(qū)域包含delta值。每次生成粒子時(shí),它都使用基值加上范圍內(nèi)的隨機(jī)值(-delta值,+ delta值)。這允許您為這些屬性獲得一些隨機(jī)方差。

4. Simulation Attributes - 模擬屬性

模擬屬性管理粒子在其生命周期內(nèi)的運(yùn)動(dòng)。 這使您無(wú)需使用物理引擎即可管理其移動(dòng):

  • Life span - 壽命:以秒為單位指定粒子的壽命。將此值設(shè)置為1,以便單個(gè)粒子僅存在一秒鐘。
  • Linear velocity - 線(xiàn)速度:指定發(fā)射粒子的線(xiàn)速度。將此值設(shè)置為0,這樣粒子就會(huì)產(chǎn)生沒(méi)有方向或速度的粒子。
  • Angular velocity - 角速度:指定發(fā)射粒子的角速度。將其設(shè)置為0,這樣粒子就不會(huì)旋轉(zhuǎn)。
  • Acceleration - 加速度:指定應(yīng)用于發(fā)射粒子的力矢量。將其設(shè)置為(x:0,y:-5,z:0) - 這是向下矢量 - 一旦產(chǎn)生,以模擬粒子上的軟重力效應(yīng)。
  • Speed factor - 速度系數(shù):設(shè)置粒子模擬速度的乘數(shù)。將其設(shè)置為1可以正常速度運(yùn)行模擬。
  • Stretch factor - 拉伸因子:在運(yùn)動(dòng)方向上拉伸粒子的乘數(shù)。將其設(shè)置為0以不拉伸粒子圖像。

5. Image Attributes - 圖像屬性

圖像屬性控制粒子的視覺(jué)方面。它們還控制著這些粒子的外觀在其生命周期中如何變化:

  • Image - 圖像:指定將用于渲染每個(gè)粒子的圖像。選擇CircleParticle.png圖像,為粒子賦予其主要形狀。
  • Color - 顏色:設(shè)置指定圖像的色調(diào)。將顏色設(shè)置為白色,為粒子系統(tǒng)提供白色的基色。
  • Animate color - 動(dòng)畫(huà)顏色:使粒子在其生命周期內(nèi)改變顏色。取消選中此項(xiàng),因?yàn)榱W宇伾静粫?huì)改變。
  • Color variation - 顏色變化:為粒子顏色添加一點(diǎn)隨機(jī)性。您可以將其設(shè)置為(h:0,s:0,b:0,a:0),因?yàn)榱W宇伾粫?huì)變化。
  • Size - 大小:指定粒子的大小。將此值設(shè)置為0.1,以便發(fā)射的粒子尺寸較小。

6. Image Sequence Attributes - 圖像序列屬性

要為粒子創(chuàng)建動(dòng)畫(huà)圖像,可以將動(dòng)畫(huà)的每個(gè)幀排列到單個(gè)圖像上的網(wǎng)格中(如游戲中的精靈表)。然后,您只需將該網(wǎng)格圖像用作粒子發(fā)射器的圖像。使用圖像序列屬性可以控制粒子的基本動(dòng)畫(huà)屬性:

  • Initial frame - 初始幀:設(shè)置動(dòng)畫(huà)序列的第一個(gè)從零開(kāi)始的幀。 第0幀對(duì)應(yīng)于網(wǎng)格中的左上圖像。 您正在使用單幀圖像,因此將其設(shè)置為0。
  • Frame rate - 幀速率:以每秒幀數(shù)控制動(dòng)畫(huà)的速率。 將其設(shè)置為0,因?yàn)檫@僅適用于使用包含多個(gè)幀的圖像。
  • Animation - 動(dòng)畫(huà):指定動(dòng)畫(huà)序列的行為。 重復(fù)循環(huán)動(dòng)畫(huà),Clamp只播放一次,Auto Reverse從開(kāi)始到結(jié)束播放,然后再播放。 你可以將它保留在Repeat上,因?yàn)檫@在使用單幀圖像時(shí)無(wú)關(guān)緊要。
  • Dimensions - 尺寸:指定動(dòng)畫(huà)網(wǎng)格中的行數(shù)和列數(shù)。 將其設(shè)置為(Rows: 1, Columns: 1),因?yàn)槟褂玫氖菃螏瑘D像。

7. Rendering Attributes - 渲染屬性

渲染屬性定義渲染階段如何處理粒子:

  • Blending - 混合:在將粒子繪制到場(chǎng)景中時(shí)指定渲染器的混合模式。 將其設(shè)置為Alpha,它將使用圖像Alpha通道信息進(jìn)行透明。
  • Orientation - 方向:控制粒子的旋轉(zhuǎn)。 將此設(shè)置為Billboard screen-aligned,這將使扁平粒子始終面向攝像機(jī)視圖,因此您不會(huì)注意到粒子確實(shí)是平面圖像。
  • Sorting - 排序:設(shè)置粒子的渲染順序。 此屬性與混合模式一起使用,并影響混合的應(yīng)用方式。 將其設(shè)置為None,以便粒子系統(tǒng)不會(huì)使用排序。
  • Lighting - 光照:控制SceneKit是否將光照應(yīng)用于粒子。 取消選中此選項(xiàng),粒子系統(tǒng)將忽略場(chǎng)景中的任何燈光。

8. Physics Attributes - 物理屬性

物理屬性允許您指定粒子在物理模擬中的行為方式:

  • Affected by gravity - 受重力影響:使場(chǎng)景的重力影響粒子。 取消選中此項(xiàng),因?yàn)槟幌MW酉到y(tǒng)參與物理模擬。
  • Affected by physics fields - 受物理場(chǎng)影響:導(dǎo)致場(chǎng)景中的物理場(chǎng)影響粒子。 取消選中此項(xiàng),因?yàn)槟幌M锢韴?chǎng)對(duì)粒子產(chǎn)生影響。
  • Die on Collision - 死于碰撞:讓場(chǎng)景中的物理體碰撞并破壞粒子。 取消選中此項(xiàng),因?yàn)槟幌M谂c場(chǎng)景中的節(jié)點(diǎn)對(duì)象發(fā)生碰撞時(shí)刪除粒子。
  • Physics Properties - 物理屬性:在物理模擬過(guò)程中控制粒子物理行為的基本物理屬性。 您可以將所有這些保留為默認(rèn)值,因?yàn)榱W酉到y(tǒng)不會(huì)使用它。

9. Life Cycle Attributes - 生命周期屬性

生命周期屬性可讓您控制粒子系統(tǒng)的整個(gè)生命周期:

  • Emission duration - 發(fā)射持續(xù)時(shí)間:控制發(fā)射器發(fā)射新粒子的時(shí)間長(zhǎng)度。 將其設(shè)置為1,這將激活粒子發(fā)射器,總長(zhǎng)度為1秒。
  • Idle duration - 空閑持續(xù)時(shí)間:循環(huán)粒子系統(tǒng)在指定的發(fā)射持續(xù)時(shí)間內(nèi)發(fā)射粒子,然后在指定的空閑持續(xù)時(shí)間內(nèi)空閑,之后循環(huán)重復(fù)。 將其設(shè)置為0,這樣粒子系統(tǒng)將只發(fā)射一次。
  • Looping - 循環(huán):指定粒子系統(tǒng)是否發(fā)射一次粒子,如爆炸,或連續(xù)發(fā)射,如火山。 將其設(shè)置為Loops continuously,以便發(fā)射器在再次從場(chǎng)景中移除之前盡可能長(zhǎng)時(shí)間地發(fā)射。

對(duì)于單個(gè)粒子系統(tǒng),需要考慮很多屬性,但這可以讓您獲得很多控制以獲得您正在尋找的特別的特效。

如果您努力將屏幕截圖中的值復(fù)制到粒子系統(tǒng),您將擁有一個(gè)代表以下效果的系統(tǒng):

如果您的不是這樣,請(qǐng)嘗試旋轉(zhuǎn)相機(jī)。 它也可能有助于將背景顏色更改為深藍(lán)色,就像您在此處看到的那樣,可以更容易地看到粒子系統(tǒng)。

現(xiàn)在終于可以為游戲添加炫酷粒子效果了。 將以下內(nèi)容添加到GameViewController.swift類(lèi):

// 1
func createTrail(color: UIColor, geometry: SCNGeometry) -> 
  SCNParticleSystem {
  // 2
  let trail = SCNParticleSystem(named: "Trail.scnp", inDirectory: nil)!
  // 3
  trail.particleColor = color
  // 4
  trail.emitterShape = geometry
  // 5
  return trail
}

以下是上面發(fā)生的事情:

  • 1) 這定義了createTrail(_:geometry :),它接受colorgeometry參數(shù)來(lái)設(shè)置粒子系統(tǒng)。
  • 2) 這將從您之前創(chuàng)建的文件加載粒子系統(tǒng)。
  • 3) 在這里,您可以根據(jù)傳入的參數(shù)修改粒子的色調(diào)顏色。
  • 4) 這使用geometry參數(shù)指定發(fā)射器的形狀。
  • 5) 最后,這將返回新創(chuàng)建的粒子系統(tǒng)。

此方法可幫助您創(chuàng)建SCNParticleSystem的實(shí)例,但仍需要將粒子系統(tǒng)添加到生成的形狀對(duì)象。

請(qǐng)注意,createTrail(_:geometry :)接受一個(gè)顏色參數(shù)并使用它來(lái)為粒子著色。 您將粒子系統(tǒng)的顏色設(shè)置為與形狀的顏色相同。

spawnShape()中找到在其中設(shè)置形狀的材質(zhì)漫反射內(nèi)容的那一行,然后將其拆分,使隨機(jī)顏色存儲(chǔ)在常量中,如下所示:

let color = UIColor.random()
geometry.materials.first?.diffuse.contents = color

接下來(lái),在將力強(qiáng)加到geometryNode的物理體之后,在spawnShape()中進(jìn)一步向下添加以下行:

let trailEmitter = createTrail(color: color, geometry: geometry)
geometryNode.addParticleSystem(trailEmitter)

這使用createTrail(_:geometry :)創(chuàng)建粒子系統(tǒng)并將其附加到geometryNode

構(gòu)建并運(yùn)行,看看你的辛勤工作!

它看起來(lái)很棒 !


Heads-up Displays

在這個(gè)簡(jiǎn)短的部分中,您將使用Game Utils快速添加一個(gè)小小的抬頭顯示器來(lái)顯示您的玩家的剩余生命,最佳分?jǐn)?shù)和當(dāng)前分?jǐn)?shù)。 幕后代碼使用SpriteKit標(biāo)簽,并使用標(biāo)簽的輸出作為平面的紋理。 這是一種強(qiáng)大的技術(shù)!

將以下新屬性添加到gamewnController.swift,就在spawnTime下面:

var game = GameHelper.sharedInstance

這使您可以快速訪問(wèn)GameHelper共享實(shí)例,該實(shí)例包含一組方法來(lái)為您完成繁重的工作。

將以下方法添加到GameViewController的底部,在createTrail()下面:

func setupHUD() {
  game.hudNode.position = SCNVector3(x: 0.0, y: 10.0, z: 0.0)
  scnScene.rootNode.addChildNode(game.hudNode)
}

在這里,您可以使用幫助程序庫(kù)中的game.hudNode。 您設(shè)置HUD節(jié)點(diǎn)的位置并將其添加到場(chǎng)景中。

接下來(lái),您需要從某個(gè)地方調(diào)用setupHUD()。 將以下行添加到viewDidLoad()的底部:

setupHUD()

現(xiàn)在你有一個(gè)抬頭顯示器,你需要保持它是最新的。 將以下調(diào)用game.updateHUD()添加到到renderer(_: updateAtTime:)的底部。

game.updateHUD()

構(gòu)建并運(yùn)行,您將在屏幕頂部看到您的顯示,如下所示:

你的游戲現(xiàn)在有一個(gè)漂亮的小HUD,有生命計(jì)數(shù)器,高分和當(dāng)前分?jǐn)?shù)。

好的,抬頭顯示很好,但現(xiàn)在是時(shí)候?yàn)槟愕挠螒蛱砑右恍┗?dòng)了。


Touch Handling - 觸摸處理

通常情況下,在您的應(yīng)用中啟用觸摸并不像人們希望的那樣簡(jiǎn)單。

第一步是了解觸摸處理在3D中的工作原理。 下圖顯示了場(chǎng)景側(cè)視圖中的觸摸點(diǎn)以及SceneKit如何將該觸摸點(diǎn)轉(zhuǎn)換為3D場(chǎng)景以確定您正在觸摸的對(duì)象:

那么您采取了哪些步驟來(lái)處理用戶(hù)的觸摸事件?

  • Get touch location - 獲取觸摸位置:首先,您需要在屏幕上獲取用戶(hù)觸摸的位置。
  • Convert to view coordinates - 轉(zhuǎn)換為視圖坐標(biāo):之后,您需要將該觸摸位置轉(zhuǎn)換為相對(duì)于呈現(xiàn)場(chǎng)景的SCNView實(shí)例的位置。
  • Fire a ray for a hit test - 為命中測(cè)試射出一條光線(xiàn):一旦你建立了一個(gè)相對(duì)于視圖的觸摸位置,SceneKit就可以通過(guò)向你的場(chǎng)景發(fā)射一條光線(xiàn)(不是,不是那個(gè)Ray!)來(lái)為你執(zhí)行命中測(cè)試并返回一個(gè) 與光線(xiàn)相交的對(duì)象列表。

1. Naming Nodes - 命名節(jié)點(diǎn)

在激活觸摸死亡之前,您需要一種方法來(lái)識(shí)別每個(gè)衍生對(duì)象。 最簡(jiǎn)單的方法是給他們起名字。

將粒子系統(tǒng)添加到geometryNode后立即將以下內(nèi)容添加到spawnShape()

if color == UIColor.black {
  geometryNode.name = "BAD"
} else {
  geometryNode.name = "GOOD"
}

秉承古老西方電影黑帽惡魔的精神,你將綽號(hào)BAD分配給黑色物體,并將GOOD分配給所有其他物體。

2. Adding Touch Handling - 添加觸摸處理

接下來(lái),您需要編寫(xiě)一個(gè)方法,以便在檢測(cè)到用戶(hù)已觸發(fā)特定節(jié)點(diǎn)時(shí)稍后調(diào)用該方法。

將以下方法添加到GameViewController的底部,在setupHUD()下面:

func handleTouchFor(node: SCNNode) {
  if node.name == "GOOD" {
    game.score += 1
    node.removeFromParentNode()
  } else if node.name == "BAD" {
    game.lives -= 1
    node.removeFromParentNode()
  }
}

該方法檢查被觸摸節(jié)點(diǎn)的名字;良好的節(jié)點(diǎn)會(huì)增加分?jǐn)?shù),而糟糕的(黑色)節(jié)點(diǎn)會(huì)將生命數(shù)量減少一個(gè)。 在任何一種情況下,您都會(huì)從屏幕中刪除節(jié)點(diǎn),因?yàn)樗驯讳N(xiāo)毀。

3. Using the Touch Handler - 使用觸控處理程序

要捕獲用戶(hù)的觸摸,您將使用touchesBegan(_:withEvent :),每次玩家觸摸屏幕時(shí)都會(huì)調(diào)用它。

要實(shí)現(xiàn)您自己的版本,請(qǐng)?jiān)?code>GameViewController中handleTouchFor(_ :)下面添加以下內(nèi)容:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  // 1
  let touch = touches.first!
  // 2
  let location = touch.location(in: scnView)
  // 3
  let hitResults = scnView.hitTest(location, options: nil)
  // 4
  if let result = hitResults.first {
    // 5
    handleTouchFor(node: result.node)
  }
}

下面進(jìn)行細(xì)分:

  • 1) 抓住第一個(gè)可用的touch。 如果玩家使用多個(gè)手指,則可以有多個(gè)。
  • 2) 將觸摸位置轉(zhuǎn)換為相對(duì)于scnView坐標(biāo)的位置。
  • 3) hitTest(_:options :)為您提供了一個(gè)SCNHitTestResult對(duì)象數(shù)組,這些對(duì)象表示從用戶(hù)觸摸的視圖內(nèi)的點(diǎn)開(kāi)始并遠(yuǎn)離相機(jī)的光線(xiàn)的任何交叉點(diǎn)。
  • 4) 檢查命中測(cè)試的第一個(gè)結(jié)果。
  • 5) 最后,您將第一個(gè)結(jié)果節(jié)點(diǎn)傳遞給您的觸摸處理程序,這將增加您的分?jǐn)?shù) - 或者讓您失去生命!

最后一步。 您不再需要攝像頭控制,因此請(qǐng)更改setupView()中的行,如下所示:

scnView.allowsCameraControl = false

構(gòu)建并運(yùn)行,準(zhǔn)備好釋放你的手指!

點(diǎn)擊產(chǎn)生的物體,使它們分解在稀薄的空氣中。


Challenge - 挑戰(zhàn)

是時(shí)間到很酷的因素 - 什么比爆炸更酷? 絕對(duì)沒(méi)有,對(duì)吧?

這將帶您接受本教程的挑戰(zhàn),即創(chuàng)建另一個(gè)粒子系統(tǒng)并將其命名為Explode.scnp。 看看你是否可以找出要修改的屬性以使這些粒子爆炸。

效果看起來(lái)應(yīng)該與此類(lèi)似:

您可以使用以下圖像作為粒子系統(tǒng)的起點(diǎn):


Shaping Particle Explosions - 塑造粒子爆炸

現(xiàn)在您已經(jīng)創(chuàng)建了爆炸粒子系統(tǒng),您需要添加一些代碼來(lái)使這些節(jié)點(diǎn)爆炸。 您將使用一些特殊屬性來(lái)使爆炸與您觸摸的任何節(jié)點(diǎn)具有相同的形狀。

將以下內(nèi)容添加到GameViewController的底部,在touchesBegan(_:withEvent)下面:

// 1
func createExplosion(geometry: SCNGeometry, position: SCNVector3,
  rotation: SCNVector4) {
  // 2
  let explosion =
    SCNParticleSystem(named: "Explode.scnp", inDirectory:
  nil)!
  explosion.emitterShape = geometry
  explosion.birthLocation = .surface
  // 3
  let rotationMatrix =
    SCNMatrix4MakeRotation(rotation.w, rotation.x,
      rotation.y, rotation.z)
  let translationMatrix =
    SCNMatrix4MakeTranslation(position.x, position.y, 
      position.z)
  let transformMatrix =
    SCNMatrix4Mult(rotationMatrix, translationMatrix)
  // 4
  scnScene.addParticleSystem(explosion, transform: transformMatrix)
}

以下是上述代碼的細(xì)分:

  • 1) createExplosion(_:position:rotation :)有三個(gè)參數(shù):geometry定義粒子效果的形狀,而positionrotation幫助將爆炸放入場(chǎng)景中。
  • 2) 這會(huì)加載Explode.scnp并使用它來(lái)創(chuàng)建一個(gè)發(fā)射器。 發(fā)射器使用geometry作為emitterShape,因此粒子將從形狀的表面發(fā)射。
  • 3) 輸入矩陣!不要被這三條線(xiàn)嚇到;它們只是為addParticleSystem(_:withTransform :)提供了一個(gè)組合的旋轉(zhuǎn)和位置(或轉(zhuǎn)換)轉(zhuǎn)換矩陣。
  • 4) 最后,在scnScene上調(diào)用addParticleSystem(_:wtihTransform)將爆炸添加到場(chǎng)景中。

你是如此接近復(fù)制那些偉大的好萊塢爆炸! 在handleTouchFor(_ :)中兩次添加以下行 - 一次到“good”if塊,一次到“bad”else塊,就在從父節(jié)點(diǎn)移除節(jié)點(diǎn)之前:

createExplosion(geometry: node.geometry!,
  position: node.presentation.position,
    rotation: node.presentation.rotation)

這使用presentation屬性來(lái)檢索節(jié)點(diǎn)的positionrotation參數(shù)。 然后使用這些參數(shù)調(diào)用createExplosion(_:position:rotation :)

注意:您正在使用presentation,因?yàn)槲锢砟M當(dāng)前正在移動(dòng)節(jié)點(diǎn)。

構(gòu)建并運(yùn)行,點(diǎn)擊,讓這些節(jié)點(diǎn)爆炸!

注意:您可以在projects / challenge / GeometryFighter文件夾下找到此挑戰(zhàn)的項(xiàng)目。


Adding Juice

你的游戲尚未完成;還有很大的改進(jìn)空間,對(duì)吧?要將游戲推向更高級(jí)別,您必須添加一些稱(chēng)為juice的東西。juice會(huì)給你的游戲帶來(lái)一些特別的東西,只是為了讓它在其余部分中脫穎而出。

這里有一些想法肯定會(huì)讓事情變得更好:

  • Game state management - 游戲狀態(tài)管理:通過(guò)基本的游戲狀態(tài)管理,您將能夠根據(jù)TapToPlayPlayingGameOver等游戲狀態(tài)控制某些游戲機(jī)制。
  • Splash screens - 啟動(dòng)畫(huà)面:使用漂亮的濺射屏幕。它們?yōu)橥婕姨峁┊?dāng)前游戲狀態(tài)的視覺(jué)線(xiàn)索。
  • Sound effects - 聲音效果:添加炫酷的聲音效果,為玩家提供與游戲元素良好互動(dòng)的重要音頻反饋。
  • Camera shakes - 相機(jī)震動(dòng):真正的大爆炸產(chǎn)生了非常大的沖擊波。添加搖動(dòng)相機(jī)效果,為您的游戲增添一些額外的東西。

后記

本篇主要講述了基于SceneKit的簡(jiǎn)單游戲示例的實(shí)現(xiàn),感興趣的給個(gè)贊或者關(guān)注~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容