自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

iOS 10平臺SpriteKit新特性之Tile Maps(下)

譯文
移動開發(fā) iOS
蘋果公司在WWDC 2016大會上向人們展示了一大批新的好東西。其中之一就是SpriteKit Tile Editor。這款工具易于上手,而且看起來速度特別快。

使用鄰接組

鄰接組能夠?qū)崿F(xiàn)在繪制瓦片時定義應(yīng)繪制什么樣的邊緣圖像。例如,如果你正在創(chuàng)建一個小島,你會擁有以草為中心的瓦片,而邊緣瓦片會是延伸到海洋中的海灘。當你繪制時,中心草瓦片鋪開,而邊緣部分將自動圍繞它們展開。

有兩種方法來平鋪邊緣瓦片。你可以使用單色瓦片,它們從一個表面轉(zhuǎn)型到另一個,請參考來自kenney.nl網(wǎng)站的如下圖像:

另一種方法是使用透明邊緣,就像下圖所示的這一組:

如果你使用透明邊緣,你必須把瓦片地圖節(jié)點分層。這樣一來,背景會通過透明度顯示。前面,你已經(jīng)繪制了水背景?,F(xiàn)在,我們要添加另一個陸地層。

再返回到文件Tiles.sks來編輯你的瓦片集合。按住Ctrl鍵同時點擊Ground Tiles,然后從菜單中選擇New\8-Way Adjacency Group。

將new tile group重命名為Grass。當你選擇Grass瓦片組時,你會看到一個網(wǎng)格中充滿了瓦片。

當然,這些內(nèi)容對于剛開始的新手來說可能看起來有些困惑,但是所有這些一會兒時間后就會變得清晰明了。

現(xiàn)在,請使用grass篩選媒體庫,你會看到屏幕上顯示出所有與草相關(guān)的瓦片圖像。

將瓦片拖到網(wǎng)格中的相關(guān)位置。我已經(jīng)根據(jù)其在網(wǎng)格中的位置命名了每一個圖像。為中心背景添加三個變體部分,就像你以前那樣操作就行了。這一次,選擇GrassCenter1變體并把Placement Weight參數(shù)更改為10。通過這種方式,當你繪制時你會得到更多的普通瓦片。

當你將圖像拖動到目標位置時,你可能會犯錯誤。我自己就經(jīng)?;煜锹浜瓦吘壨咂?。不過,不用過于擔心。只需把正確的圖像拖到錯誤的圖像上方,然后從彈出式菜單中選擇“Replace tile variant texture”命令即可。請注意,如果你選擇另一個選項,你可以通過這種方式添加對應(yīng)瓦片的變體。

當你完成后,記得要按Command + S命令保存該瓦片集。你的最終網(wǎng)格應(yīng)該看起來像上面的圖片那樣。

現(xiàn)在,在項目導(dǎo)航器中打開文件GameScene.sks。

[注意]如果由于某種原因,你想要用你剛添加的新瓦片改變背景水瓦片,那么,很遺憾:目前還不支持這種更改;所以,你需要完全重新繪制它們。你可以刪除瓦片地圖節(jié)點再添加一個新的,或者再建立另一個瓦片集,然后再把節(jié)點的瓦片集更改到原來那個。

接下來,把一個新的瓦片地圖節(jié)點拖至場景中,并將節(jié)點的名稱更改為 landBackground。你會需要這個數(shù)據(jù)的,因為以后你還要在代碼中引用該節(jié)點。現(xiàn)在,把地圖的大小更改為32列X24行。同時,確保位置中的X坐標和 Y坐標都設(shè)置為0且X和Y縮放比例都設(shè)置為1。

現(xiàn)在,雙擊場景編輯器來編輯瓦片地圖。

從工具欄上單擊命令“Select Tile”。新的Grass瓦片組將顯示在下拉列表框中,還有其他兩個瓦片組。

選擇最右邊的瓦片組Grass,單擊工具欄上的畫筆工具開始繪畫。

你會看到邊緣部分是如何神奇地包圍住你畫的內(nèi)容的!

還記得Tiles.sks中那令人困惑的網(wǎng)格嗎?下面給出瓦片的繪制方式:

好了,點擊Done命令,并在屬性檢查器中取消勾選Enable Automapping項。

雙擊場景編輯器中的landBackground節(jié)點再次編輯瓦片地圖。當你點擊下拉菜單中的Select Tile命令時將顯示所有可用的瓦片?,F(xiàn)在,你可以用你所選的瓦片在網(wǎng)格中繪制單個正方形了。

當你畫完后單擊Done命令。現(xiàn)在,構(gòu)建并運行你的應(yīng)用程序來欣賞一下你新創(chuàng)建的新背景吧。

新的SpriteKit瓦片類

除了使用場景編輯器以可視化方式創(chuàng)建瓦片地圖外,你還可以在代碼中創(chuàng)建瓦片地圖。那么,你可能在想:“既然可以使用場景編輯器為什么還要這樣做呢?”

假設(shè)您需要識別具體的瓦片,例如水瓦片,該怎么辦呢?在本教程中,汽車速度的減慢是由水瓦片導(dǎo)致的。在代碼中你可以實現(xiàn)這一判斷!

另一個原因是隨機性。在本教程中,玩家將收集鴨子和氣罐。如果你使用編輯器繪制這些東西,那么在每一場游戲中它們都將留在原地。如果您在代碼中添加它們,您可以隨機地控制它們的位置。

回顧到目前為止你所做的,您創(chuàng)建的每一項其實都有一個相應(yīng)的新的SpriteKit類。

在文件GameScene.sks中,它們是:

SKTileMapNode:對應(yīng)于你放置在場景編輯器中的節(jié)點。

SKTileSet:對應(yīng)于您在屬性檢查器中為瓦片地圖節(jié)點分配的瓦片集。

打開文件Tiles.sks,在這個文件中你使用了:

SKTileSet:樹結(jié)構(gòu)頂部的項,本教程中命名為Ground Tiles。

SKTileGroup:瓦片集中的瓦片組。在本教程中,它們對應(yīng)于Water Tile、Grass Tile和Grass。

SKTileGroupRule:定義每個瓦片的鄰接規(guī)則。例如,左上角瓦片、 中心瓦片或右邊緣瓦片。

現(xiàn)在,點擊Grass組并選擇Center規(guī)則。

SKTileDefinition:每條規(guī)則都有一組瓦片定義。這些都是瓦片的變體。例如,中心瓦片具有三個SKTileDefinition變體,在繪畫時可隨機使用它們。

然后,選擇屏幕底部的一個中心變體。于是,在屬性檢查器中,你會看到每個 SKTileDefinition變體可用的所有屬性。

如果你創(chuàng)建了動畫瓦片,那么你會看到每一幀的信息,而且你能夠控制幀速率。設(shè)想一下你的水瓦片拍打著草瓦片的情形吧。

對應(yīng)于每個變體的屬性檢查器也是你可以提供這些變體的用戶數(shù)據(jù)的地方。以后當你想要確定某對象是一只鴨子還是一種氣罐時,這將很有用。

編程控制瓦片

***,我們需要編寫一些代碼。

當汽車在水瓦片上行駛時其速度應(yīng)顯著放緩。有兩種方法可以實現(xiàn)這一目的。

您可以將一個布爾型用戶數(shù)據(jù)isWater添加到所有的水瓦片上,然后在代碼中檢查用戶數(shù)據(jù)?;蛘?,因為在單獨的圖層上創(chuàng)建了水,你可以使用landBackground瓦片地圖節(jié)點中的透明度來測試查看是否汽車的位置下部的瓦片為空。

打開文件GameScene.swift,將landBackground屬性添加到GameScene:

var landBackground:SKTileMapNode!

接下來,把如下代碼添加到方法loadSceneNodes中:

  1. guard let landBackground = childNode(withName: "landBackground"
  2.  
  3. as? SKTileMapNode else { 
  4.  
  5. fatalError("Background node not loaded"
  6.  
  7.  
  8. self.landBackground = landBackground 

在此,我們把瓦片地圖節(jié)點加載到了landBackground屬性中。

現(xiàn)在,再在方法update(_:)中添加如下代碼:

  1. let position = car.position 
  2.  
  3. let column = landBackground.tileColumnIndex(fromPosition: position) 
  4.  
  5. let row = landBackground.tileRowIndex(fromPosition: position) 

方法update(_:)每幀都會執(zhí)行;這是一個檢測小車位置的好地方。在這里,你把小車的位置數(shù)據(jù)轉(zhuǎn)換成行列數(shù)據(jù)。就是通過這種方式提取瓦片地圖中的實際瓦片數(shù)據(jù)的。

接下來把如下代碼添加到方法update(_:)后面:

let tile = landBackground.tileDefinition(atColumn: column, row: row)

tile現(xiàn)在包含在指定行列位置的瓦片的SKTileDefinition信息。

***,把如下代碼添加到方法update(_:)后面:

  1. if tile == nil { 
  2.  
  3. maxSpeed = waterMaxSpeed 
  4.  
  5. print("water"
  6.  
  7. else { 
  8.  
  9. maxSpeed = landMaxSpeed 
  10.  
  11. print("grass"
  12.  

如果沒有瓦片繪制,則小車的***速度將被減小到合適的值。你可以使用landBackground的透明度屬性來決定這個值。本游戲中,透明的瓦片被認定是水。

***,重新構(gòu)建與運行程序,結(jié)果如下:

小車的***速度將比其在水中時減小多了。當然,你可以通過控制臺輸出來進一步確定這個結(jié)論。

收集對象

現(xiàn)在,我們來使用前面創(chuàng)建的對象創(chuàng)建一個瓦片地圖,以便汽車收集之用。

首先,我們隨機地把橡膠鴨子和氣罐充滿整個瓦片地圖。只是注意一點:鴨子自然要放到水瓦片處,而氣罐置于草瓦片上。

接下來,為對象創(chuàng)建新的瓦片集。運行命令“File\New\File”并選擇 “iOS\Resource\SpriteKit Tile Set”模板,然后單擊“Next”按鈕。把瓦片集命名為ObjectTiles并單擊命令“Create”。

打開文件ObjectTiles.sks,更改瓦片集名稱為ObjectTiles。

接下來,把“new tile group”更改為Duck,然后把rubberduck圖像從媒體庫拖到圖塊上。

現(xiàn)在,選擇鴨瓦片,注意到對應(yīng)瓦片位于底部。在屬性檢查器中,單擊User Data下的+(你可能需要在檢查器上向下滾動一段距離)。然后,雙擊userData1,將其更改為duck。至于是什么類型是沒關(guān)系的,因為我們只是檢查一下是否存在此值,所以可以保留其為一個整數(shù)類型吧。

接下來,按住Ctrl鍵的同時點擊瓦片集列表中的“Object Tiles”并選擇“New\Single Tile Group”。把此組重命名為“GasCan”并把圖像gascan拖動到瓦片上。

然后,選擇氣罐瓦片,并像以前一樣添加用戶數(shù)據(jù),并命名該用戶數(shù)據(jù)為gascan。

[注意]在一開始時,我想在代碼中創(chuàng)建瓦片地圖結(jié)點并使用命名的瓦片集填充它,但是在寫作本文時,我還無法使用名稱initializer來檢索SKTileSet。因此,目前情況下,僅是使用瓦片集名字在場景編輯器中創(chuàng)建了一個空的瓦片地圖結(jié)點。

現(xiàn)在,打開文件GameScene.sks,并把一個tile map node添加到場景中。然后在屬性檢查器中命名為objects,同時設(shè)置其X和Y坐標都為0,Map Size為32X24。

對瓦片集方面,從下拉菜單中選擇“Object Tiles”,你會注意到Tile Size會被自動設(shè)置大小,參考下圖。

 

接下來,打開文件GameScene.swift,添加如下新屬性:

var objectsTileMap:SKTileMapNode!

然后,在方法loadSceneNodes()中添加如下代碼:

  1. guard let objectsTileMap = childNode(withName: "objects"
  2.  
  3. as? SKTileMapNode else { 
  4.  
  5. fatalError("Objects node not loaded"
  6.  
  7.  
  8. self.objectsTileMap = objectsTileMap 

這將加載瓦片地圖結(jié)點,于是你可以通過Objects瓦片集來訪問它。

接下來,在方法loadSceneNodes()后面,添加一個新的方法,如下:

  1. func setupObjects() { 
  2.  
  3. // 1 
  4.  
  5. let tileSet = objectsTileMap.tileSet 
  6.  
  7. // 2 
  8.  
  9. let tileGroups = tileSet.tileGroups 
  10.  
  11. // 3 
  12.  
  13. guard let duckTile = tileGroups.first(where: {$0.name == "Duck"}) else { 
  14.  
  15. fatalError("No Duck tile definition found"
  16.  
  17.  
  18. guard let gascanTile = tileGroups.first(where: {$0.name == "Gas Can"}) else { 
  19.  
  20. fatalError("No Gas Can tile definition found"
  21.  
  22.  
  23. // 4 
  24.  
  25. let numberOfObjects = 64 
  26.  
  27. let columns = UInt32(objectsTileMap.numberOfColumns) 
  28.  
  29. let rows = UInt32(objectsTileMap.numberOfRows) 
  30.  

至今,你已經(jīng)設(shè)置了需要隨機放置對象的所有屬性。大致思路如下:

1.從場景編輯器的瓦片地圖結(jié)點中檢索瓦片集。

2.從瓦片集中檢索瓦片組列表。

3.從瓦片組數(shù)組的瓦片中檢索瓦片定義。其中,tileGroups.first(where:)是Swift 3中提供的一個新方法,用于查找一個對象數(shù)組中的***次出現(xiàn)。

4.建立往地圖上放置對象所需要的常量。在此,可以把numberOfObjects的值修改為某個合適的值。

現(xiàn)在,在上面同一個方法中,繼續(xù)添加如下代碼:

  1. // 5 
  2.  
  3. for _ in 1...numberOfObjects { 
  4.  
  5. // 6 
  6.  
  7. let column = Int(arc4random_uniform(columns)) 
  8.  
  9. let row = Int(arc4random_uniform(rows)) 
  10.  
  11. let groundTile = landBackground.tileDefinition(atColumn: column, row: row) 
  12.  
  13. // 7 
  14.  
  15. let tile = groundTile == nil ? duckTile : gascanTile 
  16.  
  17. // 8 
  18.  
  19. objectsTileMap.setTileGroup(tile, forColumn: column, row: row) 
  20.  

這段代碼的大致邏輯如下:

5.以循環(huán)方式放置64個對象。

6.隨機選擇一列和一行。

7.如果選擇的瓦片是單色,則選擇了氣罐;否則,選擇的是鴨子。這將確保鴨子在水中,而氣罐在草上。

8.把鴨子或者氣罐放在瓦片上,放到選擇的行列處。

現(xiàn)在,在didMove(to:)方法的***調(diào)用下面的新方法:

setupObjects()

現(xiàn)在,重新構(gòu)建和運行一下工程。你會注意到背景中的水中布滿了鴨子,而草上放著氣罐。請參考下圖。

***一件事是編寫代碼來把所有鴨子摘起來放到小車上。這些代碼類似于你之前已經(jīng)寫過的檢測你是否位于水瓦片上,當然不包括你使用用戶數(shù)據(jù)來控制鴨子和氣體那一部分。

返回到文件GameScene.swift,然后在GameScene的頂部添加兩個屬性:

  1. lazy var duckSound:SKAction = { 
  2.  
  3. return SKAction.playSoundFileNamed("Duck.wav", waitForCompletion: false
  4.  
  5. }() 
  6.  
  7. lazy var gascanSound:SKAction = { 
  8.  
  9. return SKAction.playSoundFileNamed("Gas.wav", waitForCompletion: false
  10.  
  11. }() 

在此,你創(chuàng)建了兩個動作來控制當物體收集時播放聲音。這些聲音數(shù)據(jù)也包含在示例工程中。

現(xiàn)在,在方法update(_:)的***添加如下代碼:

  1. let objectTile = objectsTileMap.tileDefinition(atColumn: column, row: row) 
  2.  
  3. if let _ = objectTile?.userData?.value(forKey: "gascan") { 
  4.  
  5. run(gascanSound) 
  6.  
  7. objectsTileMap.setTileGroup(nil, forColumn: column, row: row) 
  8.  
  9.  
  10. if let _ = objectTile?.userData?.value(forKey: "duck") { 
  11.  
  12. run(duckSound) 
  13.  
  14. objectsTileMap.setTileGroup(nil, forColumn: column, row: row) 
  15.  

在這里,我們檢查用戶數(shù)據(jù)以確定它是否包含gascan或duck。然后,播放相應(yīng)的聲音并將瓦片組設(shè)置為零。這將從視圖中刪除瓦片。

再次構(gòu)建和運行一下應(yīng)用程序吧,再試試收集氣罐和鴨子!這比實現(xiàn)精靈碰撞簡單多了吧!

小結(jié)

通過本文,你應(yīng)當學(xué)會了如何使用Tile Map Editor。這真是SpriteKit系列工具家族中***的補充。

本文游戲***版本的下載地址是https://cdn1.raywenderlich.com/wp-content/uploads/2016/06/RDRescue-Finished.zip。想更多地了解有關(guān)細節(jié),你不妨觀看一下蘋果WWDC 2016大會的有關(guān)視頻(https://developer.apple.com/videos/play/wwdc2016/610/)。

責(zé)任編輯:趙立京 來源: 51CTO
相關(guān)推薦

2016-07-13 14:11:19

iOS 10平臺

2017-02-06 11:17:31

iOSiOS 10.3新特性

2016-08-08 14:20:00

IOS10蘋果系統(tǒng)WIFI

2012-06-13 10:26:21

iOS 6

2019-03-05 15:03:09

Android Q安卓系統(tǒng)功能

2022-05-05 15:16:13

iOSStoreKit 2API

2016-09-09 14:50:34

iOS 10移動應(yīng)用特性

2015-10-16 14:27:29

iOS9collectionV特性

2012-03-24 21:02:41

iOS

2009-08-03 18:34:43

TuplizersNHibernate

2017-01-09 16:25:55

Android Shortcuts系統(tǒng)

2013-05-20 10:25:45

vSphere 5.1vMotion

2018-09-19 16:15:18

MySQL直方圖數(shù)據(jù)庫

2015-07-06 09:46:21

AeroGearAndroid推送

2015-08-27 16:15:26

Windwos 10特性

2011-07-07 17:23:31

iOS

2011-03-24 09:22:36

Java 7JDBC4

2011-05-20 09:43:23

JDK7

2024-04-24 10:31:20

PostgreSQL數(shù)據(jù)庫

2017-12-11 16:32:07

JavaJDK 10語言
點贊
收藏

51CTO技術(shù)棧公眾號