Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. iOS
Code

SpriteKit Dari Dasar: Teknik dan Optimalisasi Lanjutan

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called SpriteKit From Scratch.
SpriteKit From Scratch: Visual and Audio Effects

Indonesian (Bahasa Indonesia) translation by Andy Nur (you can also view the original English article)

Pengantar

Pada tutorial ini, tahapan kelima dan terakhir dari seri SpriteKit Dari Dasar, kita melihat beberapa teknik lanjutan yang dapat kamu gunakan untuk mengoptimalkan game berbasis SpriteKit-mu untuk meningkatkan kinerja dan pengalaman pengguna.

Tutorial ini mengharuskanmu menjalankan Xcode 7.3 atau yang lebih tinggi, yang mencakup Swift 2.2 dan SDK iOS 9.3, tvOS 9.2, dan OS X 10.11.4. Untuk mengikutinya, kamu bisa menggunakan proyek yang kamu buat pada tutorial sebelumnya atau mengunduh salinan baru dari GitHub.

Grafik yang digunakan untuk game dalam seri ini dapat ditemukan di GraphicRiver. GraphicRiver adalah sumber yang bagus untuk menemukan karya seni dan grafis untuk game-mu.

1. Tekstur Atlas

Untuk mengoptimalkan penggunaan memori game-mu, SpriteKit menyediakan fungsionalitas tekstur atlas dalam bentuk class SKTextureAtlas. Atlas ini secara efektif menggabungkan tekstur yang kamu tentukan ke dalam tekstur tunggal dan besar yang memakan lebih sedikit memori daripada tekstur individual mereka sendiri.

Beruntung, Xcode bisa membuat tekstur atlas sangat mudah untukmu. Hal ini dilakukan dalam katalog aset yang sama yang digunakan untuk gambar dan sumber lain di game-mu. Buka proyekmu dan arahkan ke katalog aset Assets.xcassets. Di bagian bawah sidebar kiri, klik tombol + dan pilih opsi New Sprite Atlas.

Create a New Sprite Atlas

Hasilnya, folder baru ditambahkan ke katalog aset. Klik folder sekali untuk memilihnya dan klik lagi untuk mengganti namanya. Nama itu Obstacles. Selanjutnya, drag Obstacle 1 dan Obstacle 2 ke dalam folder ini. Kamu juga dapat menghapus aset Sprite kosong yang dihasilkan Xcode jika kamu mau, tetapi itu tidak diperlukan. Setelah selesai, tekstur atlas Obstacles yang kamu perluas akan terlihat seperti ini:

Obstacles Texture Atlas

Sekarang saatnya menggunakan tekstur atlas dalam kode. Buka MainScene.swift dan tambahkan properti berikut ke class MainScene. Kita menginisialisasi tekstur atlas dengan menggunakan nama yang kita masukkan dalam katalog aset kita.

Meski tidak diperlukan, kamu bisa memasukkan data tekstur atlas ke dalam memori sebelum ini digunakan. Hal ini memungkinkan game-mu untuk menghilangkan jeda yang mungkin terjadi saat memuat tekstur atlas dan mengambil tekstur pertama darinya. Pramuat tekstur atlas dilakukan dengan metode tunggal dan kamu juga dapat menjalankan blok kode khusus setelah pemuatan selesai.

Di class MainScene, tambahkan kode berikut di akhir metode didMoveToView(_:):

Untuk mengambil tekstur dari tekstur atlas, kamu menggunakan metode textureNamed(_:) dengan nama yang kamu tentukan dalam katalog aset sebagai parameter. Mari perbarui metode spawnObstacle(_:) di class MainScene untuk menggunakan tekstur atlas yang kita buat beberapa saat yang lalu. Kita mengambil tekstur dari tekstur atlas dan menggunakannya untuk membuat node sprite.

Perhatikan bahwa, jika permainanmu memanfaatkan On-Demand Resources (ODR), kamu dapat dengan mudah menentukan satu atau beberapa tag untuk setiap tekstur atlas. Setelah kamu berhasil mengakses tag sumber daya yang benar dengan API ODR, kamu kemudian dapat menggunakan tekstur atlas-mu seperti yang kita lakukan pada metode spawnObstacle(_:). Kamu dapat membaca lebih lanjut tentang On-Demand Resources di tutorial saya yang lain.

2. Menyimpan dan Memuat Adegan

SpriteKit juga menawarkan kemampuan untuk menyimpan dan memuat adegan dengan mudah ke dan dari penyimpanan tetap. Hal ini memungkinkan pemain untuk berhenti dari game-mu, memilikinya kembali di lain waktu, dan masih sampai pada titik yang sama dalam game-mu seperti sebelumnya.

Penyimpan dan pemuat game-mu ditangani oleh protokol NSCoding, yang telah disesuaikan dengan class SKScene. Implementasi SpriteKit terhadap metode yang dibutuhkan oleh protokol ini secara otomatis memungkinkan semua detail pada adeganmu untuk disimpan dan dimuat dengan sangat mudah. Jika kamu mau, kamu juga dapat mengganti metode ini untuk menyimpan beberapa data khusus bersamaan dengan adeganmu.

Karena game kita sangat mendasar, kita akan menggunakan nilai Bool sederhana untuk menunjukkan apakah mobil tersebut telah jatuh. Ini menunjukkan kepadamu bagaimana cara menyimpan dan memuat data khusus yang terkait dengan sebuah adegan. Tambahkan dua metode berikut dari protokol NSCoding ke class MainScene.

Jika kamu tidak terbiasa dengan protokol NSCoding, metode encodeWithCoder(_:) menangani penyimpanan adeganmu dan penginisialisasi dengan parameter NSCoder tunggal menangani pemuatan.

Selanjutnya, tambahkan metode berikut ke class MainScene. Metode saveScene() menciptakan representasi NSData dari adegan tersebut, menggunakan class NSKeyedArchiver. Untuk menjaganya agar tetap sederhana, kita menyimpan data di NSUserDefaults.

Selanjutnya, ganti implementasi didBeginContactMethod(_:) di class MainScene dengan yang berikut ini:

Perubahan pertama yang dilakukan pada metode ini adalah mengubah categoryBitMask node pemain daripada menghapusnya dari seluruh adegan. Ini memastikan bahwa setelah memuat ulang adegan, node pemain masih ada, meskipun tidak terlihat, namun tabrakan duplikat tersebut tidak terdeteksi. Perubahan lain yang dilakukan adalah memanggil metode saveScene() yang telah kita definisikan sebelumnya begitu logika ledakan khusus dijalankan.

Akhirnya, buka ViewController.swift dan ganti metode viewDidLoad() dengan implementasi sebagai berikut:

Saat memuat adegan, pertama-tama kita periksa untuk melihat apakah ada data tersimpan di NSUserDefault standar. Jika demikian, kita ambil data ini dan membuat ulang objek MainScene menggunakan class NSKeyedUnarchiver. Jika tidak, kita mengambil URL untuk file adegan yang kita buat di Xcode dan memuat data darinya dengan cara yang sama.

Jalankan aplikasimu dan ikuti rintangan dengan mobilmu. Pada tahap ini, kamu tidak melihat perbedaannya. Jalankan aplikasimu lagi, dan kamu seharusnya melihat bahwa adeganmu telah dipulihkan persis seperti saat kamu menabrak mobil.

3. Animasi Perulangan

Sebelum setiap frame game-mu di render, SpriteKit menjalankan serangkaian proses dalam urutan tertentu. Kelompok proses ini disebut sebagai animasi perulangan. Proses ini memperhitungkan aksi, properti fisik, dan batasan yang telah kamu tambahkan ke dalam adeganmu.

Jika, untuk alasan apapun, kamu perlu menjalankan kode khusus di antara salah satu proses ini, kamu dapat mengganti beberapa metode spesifik di subclass SKScene kamu atau menentukan delegasi yang sesuai dengan protokol SKSceneDelegate. Perhatikan bahwa, jika kamu menetapkan delegasi ke lokasimu, implementasi class dari metode berikut tidak dipanggil.

Proses animasi perulangan adalah sebagai berikut:

Langkah 1

Adegan memanggil metode update(_:). Metode ini memiliki parameter NSTimeInterval tunggal, yang memberimu waktu sistem saat ini. Interval waktu ini bisa berguna karena memungkinkanmu menghitung waktu yang dibutuhkan untuk me-render frame sebelumnya.

Jika nilainya lebih besar dari 1/60 detik, game-mu tidak berjalan dengan mulus pada 60 frame per detik (FPS) yang ditargetkan SpriteKit. Ini berarti bahwa kamu mungkin perlu mengubah beberapa aspek dari adeganmu (misalnya partikel, sejumlah node) untuk mengurangi kompleksitasnya.

Langkah 2

Adegan mengeksekusi dan menghitung aksi yang telah kamu tambahkan ke node-mu dan memposisikannya sesuai dengan itu.

Langkah 3

Adegan memanggil metode didEvaluateActions() nya. Di sinilah kamu dapat melakukan logika khusus sebelum SpriteKit berlanjut dengan animasi perulangan.

Langkah 4

Adegan melakukan simulasi fisik dan mengubah adeganmu sesuai dengan itu.

Langkah 5

Adegan memanggil metode didSimulatePhysics(), yang kamu dapat ganti dengan metode didEvaluateActions().

Langkah 6

Adegan menerapkan batasan yang telah kamu tambahkan ke node-mu.

Langkah 7

Adegan memanggil metode didApplyConstraints(), yang tersedia untuk kamu timpa.

Langkah 8

Adegan memanggil metode didFinishUpdate(), yang kamu juga bisa timpa. Ini adalah metode akhirmu yang dapat mengubah adeganmu sebelum tampil agar frame itu selesai.

Langkah 9

Akhirnya, adegan me-render konten dan memperbarui yang mengandung SKView yang sesuai.

Hal ini penting untuk dicatat bahwa, jika kamu menggunakan sebuah objek SKSceneDelegate daripada sebuah subclass khusus, masing-masing metode memperoleh parameter tambahan dan sedikit merubah namanya. Parameter tambahan adalah objek SKScene, yang memungkinkanmu untuk menentukan adegan dengan metode yang sedang dijalankan dalam kaitannya dengan itu. Metode-metode yang didefinisikan oleh protokol SKSceneDelegate diberi nama sebagai berikut:

  • update(_:forScene:)
  • didEvaluateActionsForScene(_:)
  • didSimulatePhysicsForScene(_:)
  • didApplyConstraintsForScene(_:)
  • didFinishUpdateForScene(_:)

Bahkan jika kamu tidak menggunakan metode ini untuk membuat perubahan ke adeganmu, mereka masih dapat sangat berguna untuk debugging. Jika game-mu secara konsisten tertinggal dan laju frame-nya menurun pada saat tertentu dalam game-mu, kamu bisa menggantikan kombinasi dari metode di atas dan menemukan interval waktu antara masing-masing yang dipanggil. Hal ini memungkinkanmu untuk secara akurat menemukan apakah itu secara khusus berupa aksi, fisik, batasan, atau grafis-mu yang terlalu rumit untuk permainanmu untuk menjalankannya pada 60 FPS.

4. Praktik Terbaik Kinerja

Gambaran Bertumpuk

Ketika me-render adegan, SpriteKit, secara default, berjalan melalui node dalam array children adeganmu dan menarik mereka pada layar dalam urutan yang sama seperti dalam array. Proses ini juga diulang dan dilingkarkan untuk setiap turunan node yang mungkin dimiliki oleh node tertentu.

Menghitung melalui node anak secara individual berarti SpriteKit mengeksekusi sebuah panggilan gambar untuk setiap node. Sementara untuk adegan sederhana, metode rendering ini tidak mempengaruhi kinerja secara signifikan, karena adeganmu mendapatkan lebih banyak simpul proses ini menjadi sangat tidak efisien.

Untuk membuat render lebih efisien, kamu dapat mengatur node dalam adeganmu ke lapisan yang berbeda. Hal ini dilakukan melalui properti zPosition dari class SKNode. Semakin tinggi sebuah node zPosition adalah, "lebih dekat" ke layar, yang berarti bahwa ia dituliskan di atas node lain pada adeganmu. Demikian juga, node dengan zPosition terendah dalam sebuah adegan ditampilkan di "belakang" dan dapat tumpang tindih dengan node lain.

Setelah mengatur node menjadi lapisan, kamu dapat mengatur properti ignoreSiblingOrder objek SKView menjadi true. Ini menghasilkan SpriteKit dengan menggunakan nilai zPosition untuk membuat adegan daripada urutan array children. Proses ini jauh lebih efisien karena setiap node dengan zPosition adalah tertumpuk bersama menjadi satu gambar menarik daripada memiliki satu untuk setiap node.

Hal ini penting untuk dicatat bahwa nilai zPosition dari sebuah node bisa negatif jika diperlukan. Node dalam adeganmu masih di-render dalam rangka meningkatkan zPosition.

Menghindari Animasi Khusus

Kedua class SKAction dan SKConstraint berisi sejumlah besar aturan-aturan yang dapat kamu tambahkan ke adegan untuk membuat animasi. Menjadi bagian dari framework SpriteKit, mereka dioptimalkan sebanyak mungkin dan bisa juga cocok dengan animasi SpriteKit.

Beragam array aksi dan batasan yang disediakan kepadamu memungkinkan hampir setiap kemungkinan animasi yang kamu inginkan. Untuk alasan ini, sebaiknya kamu selalu menggunakan aksi dan batasan pada adeganmu untuk membuat animasi daripada melakukan logika khusus di tempat lain dalam kodemu.

Dalam beberapa kasus, terutama jika kamu perlu menganimasi sekelompok node yang cukup besar, field gaya fisik bahkan mungkin bisa menghasilkan hasil yang kamu inginkan. Force Field bahkan lebih efisien karena mereka dihitung bersama sisa SpriteKit's fisika simulasi.

Bit Mask

Adeganmu dapat dioptimalkan lebih dengan menggunakan hanya sedikit bit mask untuk node dalam adegan. Selain menjadi penting untuk deteksi tabrakan fisik, bit mask juga menentukan seberapa teratur simulasi fiisk dan pencahayaan mempengaruhi node dalam sebuah adegan.

Untuk setiap pasangan node dalam sebuah adegan, terlepas dari apakah mereka pernah akan bertabrakan, SpriteKit memantau di mana mereka relatif satu sama lain. Ini berarti, jika dibiarkan dengan mask default dengan semua bit diaktifkan, SpriteKit mencatat setiap node berada di tempatmu dibandingkan dengan setiap node lainnya. Kamu sangat dapat menyederhanakan SpriteKit's simulasi fisik dengan mendefinisikan bit mask sehingga hanya hubungan antara node yang dapat berpotensi tabrakan yang dilacak.

Demikian juga, cahaya di SpriteKit hanya mempengaruhi sebuah node jika logika AND kategori bit mask nya adalah nilai bukan nol. Dengan mengubah kategori ini, sehingga hanya node terpenting dalam adegan yang dipengaruhi oleh cahaya tertentu, kamu dapat sangat mengurangi kompleksitas dari adegan.

Kesimpulan

Kamu harus sekarang tahu bagaimana kamu dapat lebih mengoptimalkan permainan SpriteKit-mu dengan menggunakan teknik yang lebih maju, seperti tekstur atlas, gambar bertumpuk dan bit mask yang dioptimalkan. Kamu juga seharus merasa nyaman dengan penyimpanan dan pemuatan adegan untuk memberi para pemain pengalaman keseluruhan yang lebih baik.

Sepanjang seri ini, kita telah melihat melalui banyak fitur dan fungsionalitas dari framework SpriteKit di iOS, tvOS, dan OS X. Ada topik yang lebih maju di luar cakupan seri ini, seperti kustom OpenGL ES dan Metal shader serta field fisik dan sendi.

Jika kamu ingin mempelajari lebih lanjut tentang topik ini, sebaiknya mulai dengan Referensi Framework SpriteKit dan bacalah di kelas yang relevan.

Seperti biasa, pastikan untuk meninggalkan komentar dan umpan balik pada komentar di bawah ini.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.