iMedre

SKPhysicsBody Sınıfı Nedir ? Sprite Kit Derinlikleri #36

Merhaba bu yazıda Sprite Kit Kütüphanesinden SKPhysicsBody sınıfını anlatacağım. Keyifli okumalar.

SKPhysicsBody Nedir?

Bir düğüme fizik simülasyonu ekleyen bir nesne.

Genel Bakış

Düğüme fizik simülasyonu eklemek için SKNode nesnesinin PhysicsBody özelliğine bir SKPhysicsBody nesnesi atayın. Bir sahne yeni bir kareyi işlediğinde, olaydaki düğümlere bağlı fizik gövdelerinde fizik hesaplamaları yapar. Bu hesaplamalar yerçekimi, sürtünme ve diğer cisimlerle çarpışmaları içerir. Kendi kuvvetlerini ve dürtülerini de bir bedene uygulayabilirsiniz. Sahne bu hesaplamaları tamamladıktan sonra, düğüm nesnelerinin konumlarını ve yönlerini günceller.

SpriteKit, iki tür fizik gövdesini, hacme dayalı gövdeleri ve kenar tabanlı gövdeleri destekler. Fizik gövdesi oluşturduğunuzda, onun türü, boyutu ve şekli, çağırdığınız yapıcı yöntemiyle belirlenir. Kenar tabanlı bir cismin kütlesi veya hacmi yoktur ve sistemdeki kuvvetler veya impulslardan etkilenmez. Kenar tabanlı gövdeler, fizik simülasyonunuzda hacimsiz sınırları veya boşlukları temsil etmek için kullanılır. Buna karşılık, hacim bazlı gövdeler, kütle ve hacim olan nesneleri temsil etmek için kullanılır. İsDynamic özelliği, hacim temelli bir cismin yerçekimi, sürtünme, diğer nesnelerle çarpışmalardan ve doğrudan nesneye uyguladığınız güçlerden veya dürtülerden etkilenip etkilenmediğini kontrol eder.

SKPhysicsBody sınıfı, sahne tarafından simüle edildiğinde vücudun fiziksel özelliklerini tanımlar. Hacim temelli cisimler için en önemli özellik kütle özelliğidir. Hacim bazlı bir cismin homojen bir yoğunluğa sahip olduğu kabul edilir. Kütle özelliğini doğrudan ayarlayabilir veya vücudun yoğunluk özelliğini ayarlayabilir ve fizik kütlesinin kendi kütlesini hesaplamasını sağlayabilirsiniz. Sprite Kitindeki tüm değerler Uluslararası Birimler Sistemi (SI birimleri) kullanılarak belirtilmiştir. Oyununuz tutarlı değerler kullandığı sürece gerçek kuvvetler ve kütle değerleri önemli değildir.

Fiziği kullanan bir oyun tasarladığınızda, sahnede görünen farklı fizik nesneleri kategorilerini tanımlarsınız. En fazla 32 farklı fizik kütlesi kategorisi tanımlarsınız ve istediğiniz kadar bu kategorilerden birine bir beden atanabilir. Kendi kategorilerini ilan etmenin yanı sıra, bir fizik kütlesi de hangi vücut kategorilerinin etkileşime gireceğini açıklar. Çarpışmalarla ve Kişilerle Çalışma konusuna bakın. Hangi fizik alan düğümlerinin (SKFieldNode) fizik kütlesini etkileyebileceğini bildiren benzer bir mekanizma kullanırsınız.

Dinamik tabanlı bir gövde için, vücudun güçlerden veya çarpışmalardan nasıl etkilendiğini dinamik olarak kontrol edebilirsiniz.

Fizik Bedenlerinde Tüm Fizik Simüle Edilmiştir

SKPhysicsBody nesnesi, sistemdeki bir fizik gövdesi için şekil ve simülasyon parametrelerini tanımlar. Sahne fiziği simüle ettiğinde, sahne ağacına bağlı tüm fizik kütleleri için hesaplamalar yapar. Bu nedenle, bir SKPhysicsBody nesnesi oluşturursunuz, özelliklerini yapılandırır ve ardından bir düğümün fizikBody özelliğine atarsınız.

Üç tür fizik kütlesi vardır:

  • Dinamik bir hacim, sistemdeki kuvvetler ve çarpışmalardan etkilenebilecek hacim ve kütle ile fiziksel bir nesneyi simüle eder. Sahnede hareket etmesi ve birbiriyle çarpışması gereken öğeleri göstermek için dinamik birimler kullanın.
  • Statik hacim dinamik hacme benzer, ancak hızı göz ardı edilir ve kuvvetler veya çarpışmalardan etkilenmez. Bununla birlikte, hala bir hacmi olduğu için, diğer nesneler bundan çıkabilir ya da onunla etkileşime girebilir. Sahnede yer kaplayan öğeleri göstermek için statik birimler kullanın, ancak bu simülasyon tarafından taşınmamalıdır. Örneğin, bir labirentin duvarlarını temsil etmek için statik hacimler kullanabilirsiniz. Statik ve dinamik hacimleri ayrı varlıklar olarak düşünmek yararlı olsa da, pratikte bunlar, herhangi bir hacim tabanlı fizik kütlesine uygulayabileceğiniz iki farklı moddur. Bu, bir vücut için efektleri seçici olarak etkinleştirebileceğiniz veya devre dışı bırakabileceğiniz için yararlı olabilir.
  • Kenar, statik hacimsiz bir gövdedir. Kenarlar hiçbir zaman simülasyon tarafından taşınmaz ve kütleleri önemli değildir. Kenarlar, bir sahne içindeki negatif alanı (başka bir varlığın içi boş bir nokta gibi) veya çapraz, görünmez şekilde ince bir sınırı temsil etmek için kullanılır. Örneğin, kenarlarınız sahnenin sınırlarını temsil etmek için sıklıkla kullanılır. Bir kenar ve hacim arasındaki ana fark, bir kenarın kendi sınırları içinde hareket etmesine izin verirken, bir hacim katı bir nesne olarak kabul edilir. Kenarlar başka yollarla taşınırsa, yalnızca diğer kenarlarla değil, birimlerle etkileşime girer.

SpriteKit, bir dokudaki alfa kanalından oluşturulan rasgele yollara ve şekillere dayalı birkaç standart şekil, şekil sağlar. Şekil 1 mevcut şekilleri göstermektedir.

let spaceShipTexture = SKTexture(imageNamed: "spaceShip.png")
   
// Spaceship 1: circular physics body
let circularSpaceShip = SKSpriteNode(texture: spaceShipTexture)
circularSpaceShip.physicsBody = SKPhysicsBody(circleOfRadius: max(circularSpaceShip.size.width / 2,
                                                                  circularSpaceShip.size.height / 2))
   
// Spaceship 2: rectangular physics body
let rectangularSpaceShip = SKSpriteNode(texture: spaceShipTexture)
rectangularSpaceShip.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: circularSpaceShip.size.width,
                                                                     height: circularSpaceShip.size.height))
   
// Spaceship 3: polygonal physics body
let polygonalSpaceShip = SKSpriteNode(texture: spaceShipTexture)
let path = CGMutablePath()
path.addLines(between: [CGPoint(x: -5, y: 37), CGPoint(x: 5, y: 37), CGPoint(x: 10, y: 20),
                        CGPoint(x: 56, y: -5), CGPoint(x: 37, y: -35), CGPoint(x: 15, y: -30),
                        CGPoint(x: 12, y: -37), CGPoint(x: -12, y: -37), CGPoint(x: -15, y: -30),
                        CGPoint(x: -37, y: -35), CGPoint(x: -56, y: -5), CGPoint(x: -10, y: 20),
                        CGPoint(x: -5, y: 37)])
path.closeSubpath()
polygonalSpaceShip.physicsBody = SKPhysicsBody(polygonFrom: path)
  
// Spaceship 4: physics body using texture’s alpha channel
let texturedSpaceShip = SKSpriteNode(texture: spaceShipTexture)
texturedSpaceShip.physicsBody = SKPhysicsBody(texture: spaceShipTexture,
                                              size: CGSize(width: circularSpaceShip.size.width,
                                                           height: circularSpaceShip.size.height))

Bir fizik bedeninin şekli performansı etkiler. Dairesel fizik gövdesi en iyi performansı sunar ve diğer fizik kütlelerine göre çok daha hızlı olabilir. Simülasyonunuz birçok fizik kütlesi içeriyorsa, dairesel cisimler en iyi çözümdür. Dikdörtgenden sonra çokgen şekiller, düşürülmüş hız ile çarpışma doğruluğunu artırır. Bir yapının alfa kanalı tarafından oluşturulan fizik cisimleri, en yüksek hesaplama maliyetinin pahasına en iyi sadakati sunar.

Fizik Bodies oluşturma

SKPhysicsBody sınıf yöntemlerinden birini çağırarak bir fizik gövdesi oluşturulur. Her sınıf yöntemi, birim tabanlı veya kenar tabanlı bir gövdenin oluşturulup oluşturulmadığını ve hangi biçime sahip olduğunu tanımlar.

Fizik Bodies Oluşturma ve Atama

Bir düğümün fizik bedeninin bulunduğu ve bir sahneye eklendiği anda, fizik simülasyonuna katılmaya başlar. Aşağıdaki kod, kıvrımlı zemin ve hareketli düğüm olan bir şekil düğümünü (roket gemisi) içeren basit bir sahnenin nasıl oluşturulacağını gösterir. Şekil düğümünün fizik gövdesi kendi yolundan oluşturulur ve düğüm başlangıcında sprite düğümünün fizik gövdesi, SpriteKit tarafından otomatik olarak oluşturulan dokudan oluşturulur. Zemin düğümünün isDynamic öğesi false değerine sahip olduğundan, yer çekiminden etkilenmez ve sabit kalır.

// Create the rocket ship node and physics body
let spriteNode = SKSpriteNode(imageNamed: "rocketShip")
spriteNode.position = CGPoint(x: 320, y: 320)
spriteNode.physicsBody = SKPhysicsBody(texture: spriteNode.texture!,
                                       size: spriteNode.texture!.size())
spriteNode.physicsBody?.usesPreciseCollisionDetection = true
     
// Create the ground node and physics body
var splinePoints = [CGPoint(x: 0, y: 500),
                    CGPoint(x: 100, y: 50),
                    CGPoint(x: 400, y: 110),
                    CGPoint(x: 640, y: 20)]
let ground = SKShapeNode(splinePoints: &splinePoints,
                         count: splinePoints.count)
ground.lineWidth = 5
ground.physicsBody = SKPhysicsBody(edgeChainFrom: ground.path!)
ground.physicsBody?.restitution = 0.75
ground.physicsBody?.isDynamic = false
     
// Add the two nodes to the scene
scene.addChild(spriteNode)
scene.addChild(ground)

Birkaç dakika boyunca koştuktan sonra, yukarıdaki kod Şekil 2’deki resme benzeyen bir sahne yaratır – hareketli düğüm, kıvrımlı zemin hattının vadilerinden birinde dinlenir:

 

Grafiksel Temsillerle Eşleşen Fiziksel Bir Şekil Kullanın

Çoğu durumda, bir fizik kütlesi, karşılık gelen düğümün görsel temsiline yakın şekilde yaklaşan bir büyüklüğe ve şekle sahip olmalıdır. Örneğin, Şekil 3’te, roket, bir daire ya da bir dikdörtgen tarafından iyi temsil edilmeyen dar bir şekle sahiptir. Hareketli grafiğin resmi ile eşleşecek şekilde dışbükey bir çokgen şekli seçilmiştir.

let sprite = SKSpriteNode(imageNamed: "Spaceship")
sprite.physicsBody = SKPhysicsBody(texture: sprite.texture!,
                                   size: sprite.texture!.size())

 

Fizik bedeniniz için bir şekil seçerken, aşırı hassas olmayın. Daha karmaşık şekiller düzgün bir şekilde simüle edilmek için daha fazla çalışma gerektirir. Birim tabanlı kuruluşlar için aşağıdaki yönergeleri kullanın:

  • Bir daire en verimli şeklidir (init (circleOfRadius: ))
  • Yol tabanlı bir çokgen en az etkili şeklidir ve hesaplama işi çokgenin karmaşıklığı ile ölçeklenir (init (polygonFrom: ))

Kenar tabanlı bir cisim, hacim temelli bir gövdeden daha hesaplıdır. Bunun nedeni, etkileşime girdiği bedenlerin açık bir kenarın her iki tarafında veya kapalı bir şeklin içinde veya dışında bulunması olabilir. Bu yönergeleri kullanın:

Çizgiler ve dikdörtgenler en verimli kenar tabanlı gövdelerdir (init (edgeFrom: to: ) ve init (edgeLoopFrom: ))

Kenar döngüleri ve kenar zincirleri en pahalı kenar tabanlı gövdelerdir ve hesaplama işi yolun karmaşıklığı ile ölçeklenir (init (edgeLoopFrom:) ve init (edgeChainFrom: )).

Sahnenin etrafında bir kenar döngü oluşturma

Aşağıdakiler, içeriği kaydırmak zorunda olmayan oyunlarda sıklıkla kullanılan kodu gösterir. Bu durumda oyun, oyun alanının içine geri dönmek için sahnenin sınırlarını zorlayan fizik bedenlerini istiyor:

func createSceneContents() {
    self.backgroundColor = .black
    self.scaleMode = .aspectFit
    self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
}

Bir Fizik Bedeninin Fiziksel Özelliklerini Yapılandırma

SKPhysicsBody sınıfı, fizik gövdesinin nasıl simüle edildiğini belirleyen özellikleri tanımlar. Bu özellikler, bedenin kuvvetlere nasıl tepki verdiğini, kendisinde yarattığı güçleri (sürtünmeyi simüle etmek) ve olay yerindeki çarpışmalara nasıl tepki verdiğini etkiler. Çoğu durumda, özellikler fiziksel etkileri simüle etmek için kullanılır.

Her bir bedenin, olay yerindeki kuvvetlere ve çarpışmalara nasıl tepki verdiğini belirleyen kendi mülkiyet değerleri de vardır. İşte en önemli özellikler:

  • Mass özelliği, kuvvetlerin bedeni nasıl etkilediğini ve bedenin bir çarpışmaya karıştığı zamanki momentumunu belirler.
  • Friction özelliği, vücudun yüzeyinin pürüzlülüğünü belirler. Bir cismin yüzey boyunca hareket eden diğer cisimlere uyguladığı sürtünme kuvvetini hesaplamak için kullanılır.
  • LinearDamping ve angularDamping özellikleri, dünya üzerinde hareket ederken vücuttaki sürtünmeyi hesaplamak için kullanılır. Örneğin, bu hava veya su sürtünmesini simüle etmek için kullanılabilir.
  • Restitution özelliği, bir çarpışma sırasında vücudun ne kadar enerji tuttuğunu belirler – onun sersemliği.

Simülasyonun vücudun kendisinde nasıl gerçekleştirildiğini belirlemek için diğer özellikler kullanılır:

  • İsDynamic özelliği, vücudun fizik alt sistemi tarafından simüle edilip edilmediğini belirler.
  • affectedByGravity özelliği, simülasyonun vücut üzerinde bir yerçekimi kuvveti uygulayıp uygulayamayacağını belirler. Fizik dünyası hakkında daha fazla bilgi için bkz. Fizik Dünyasını Yapılandırma.
  • AllowRotation özelliği, kuvvetlerin vücut üzerinde açısal hız kazandırabileceğini belirler.

Kütle bir Vücudun İvmeye Karşı Direncini Belirler

Sahnenizdeki her bir hacim tabanlı gövdede kütleyi ayarlamanız gerekir, böylece ona uygulanan kuvvetlere düzgün bir şekilde tepki verir.

Bir fizik kütlesinin kütlesi, alanı ve yoğunluk özellikleri birbiriyle ilişkilidir. İlk önce bir beden oluşturduğunuzda, vücudun alanı hesaplanır ve daha sonra hiçbir zaman değişmez. Diğer iki özellik aşağıdaki formülü temel alarak değerleri aynı zamanda değiştirir:

mass = density x area

Bir fizik gövdesini yapılandırdığınızda iki seçeneğiniz vardır:

  •  Vücudun kütle özelliğini ayarlayın. Yoğunluk özelliği otomatik olarak yeniden hesaplanır. Bu yaklaşım, her bir vücudun kütlesini hassas bir şekilde kontrol etmek istediğinizde en yararlıdır.
  •  Vücudun yoğunluk özelliğini ayarlayın. Toplu özellik daha sonra otomatik olarak yeniden hesaplanır. Bu yaklaşım, farklı boyutlarda oluşturulmuş benzer gövdelerin bir koleksiyonuna sahip olduğunuzda en yararlıdır. Örneğin, fizik bedenleriniz asteroitleri simüle etmek için kullanılıyorsa, tüm asteroitleri aynı yoğunluğa verebilir ve daha sonra her biri için uygun bir sınırlayıcı poligon belirtebilirsiniz. Her vücut, ekrandaki büyüklüğüne göre uygun bir kütleyi otomatik olarak hesaplar.

Vücudun Özellikleri Ne Zaman Ayarlanmalı?

Çoğunlukla, bir fizik bedenini bir kere yapılandırır ve asla değiştirmezsiniz. Örneğin, bir cismin kütlesinin oyun sırasında değişmesi olası değildir. Ancak, bunu yapmakla sınırlı değilsiniz. Bazı oyunlar, simülasyon çalışırken bile vücudun özelliklerini ayarlama yeteneğini gerektirebilir. İşte bunu yapabileceğiniz birkaç örnek:

  • Gerçekçi bir roket simülasyonunda, roket yakıtı itme uygulamak için harcar. Yakıt tükendiğinde, roketin kütlesi değişir. Bunu SpriteKit’te uygulamak için bir yakıt özelliği içeren bir roket sınıfı oluşturabilirsiniz. Roket bastığında, yakıt azalır ve karşılık gelen cismin kütlesi yeniden hesaplanır.
  • Sönümleme özellikleri genellikle vücudun özelliklerine ve içinden geçtiği ortama dayanır. Örneğin, bir vakum sönümleme kuvvetleri uygular ve su havadan daha fazla sönümleme gücü uygular. Oyununuz birden fazla ortamı simüle ederse ve bedenler bu ortamlar arasında hareket ederse, oyununuz yeni bir çevreye girdiğinde vücudun sönümleme özelliklerini güncelleyebilir.

Genellikle, bu değişiklikleri SKSceneDelegate yöntemlerini kullanarak sahne öncesi ve sonraki işlemin bir parçası olarak yaparsınız.

Dönen Fizik Bodie’leri

Fizikteki ortak bir görev, bedenleri birbirine bağlamaktır. Pinning, bir nesnenin konumunu kilitler ancak dönmesine izin verir – örneğin bir tekerleği bir araca sabitleme. SpriteKit, fizik gövdelerini sabitlemek için iki seçenek sunar – sabitlenmiş özelliği kullanarak ya da bir SKPhysicsJointPin eklemi oluşturarak.

Aşağıdaki kod, daha basit bir yöntemi nasıl uygulayabileceğinizi gösterir: sabitlenmiş özelliği kullanarak. Kod, bir sarkaç görüntüsüne sahip bir hareketli düğüm oluşturur (bir orta çubukla birleştirilen farklı boyutlarda iki daire). Oluşturulan dokuya dayalı bir fizik gövdesi oluşturulur, sabitlenmiş kümesi doğruya ayarlanır ve düğüme atanır. Düğüm yatay olarak hizalamak için 90 derece döndürülür – böylece yer çekimi ağır ucunu yere doğru çeker.

let pinned = SKSpriteNode(imageNamed: "pendulum")
  
pinned.physicsBody = SKPhysicsBody(texture: pinned.texture!,
                                   size: pinned.size)
pinned.position = CGPoint(x: 320,
                          y: 320)
pinned.zRotation = CGFloat.pi / 2
pinned.physicsBody?.pinned = true
  
scene.addChild(pinned)

Düğümün fizik gövdesi sabitlendiğinden, yerinde kalır ancak merkezin etrafında döner.

Aşağıdaki kod, benzer bir sahneyi nasıl oluşturduğunuzu, ancak bir fizik eklemini nasıl kullandığınızı gösterir. Bu örnekte, sahneye bir statik bağlantı oluşturulup eklenir. Sprite düğümü, çapa düğümünün bir alt öğesi olarak eklenir ve SKPhysicsJointPin, ikisini birleştirir:

let anchor = SKNode()
  
anchor.position = CGPoint(x: 320,
                          y: 320)
anchor.zRotation = CGFloat.pi / 2
anchor.physicsBody = SKPhysicsBody()
anchor.physicsBody?.isDynamic = false
  
let jointed = SKSpriteNode(imageNamed: “pendulum”)
jointed.physicsBody = SKPhysicsBody(texture: pinned.texture!,
                                    size: pinned.size)
  
scene.addChild(anchor)
anchor.addChild(jointed)
  
let pinJoint = SKPhysicsJointPin.joint(withBodyA: anchor.physicsBody!,
                                       bodyB: jointed.physicsBody!,
                                       anchor: anchor.position)
scene.physicsWorld.add(pinJoint)

Ortaya çıkan sahneler aynı şekilde davranır.

İlk yaklaşımın avantajı basittir: daha az kod gerektirir ve rotasyonun hızını sınırlamanız veya kontrol etmeniz gerekmiyorsa tercih edilen çözümdür. Bununla birlikte, bir fizik eklemi kullanmak daha fazla işlevsellik sunar: çapa noktası üzerinde kontrolünüz vardır, rotasyon açılarını lowerAngleLimit ve upperAngleLimit ile sınırlayabilirsiniz ve rotasyon hızını rotationSpeed ile tanımlayabilirsiniz. Sürtünmeyi simüle etmek isterseniz, fizik gövdesinin angularDamping özelliği, eklemin sürtünmeTorque özelliğine benzer.

Diğer İlgili Fizik Sınıfları

Bir sahnenin fizikWorld özelliği, tüm sahneyi etkileyen fizik özelliklerini sağlayan SKPhysicsWorld nesnesine sahiptir.

Bir dizi fizik kütlesine kuvvet uygulamak veya hızlarını değiştirmek için alanları kullanabilirsiniz. SKFieldNode’a bakın.

Fizik bedenlerini eklemleri kullanarak birbirine bağlayabilirsiniz. SKPhysicsJoint’a bakın.

 

 

Erdem Özgür

Yorum Ekle

Bizleri Sosyal Medyadan Takip Edebilirsiniz

Utanmana gerek yok, bizimle iletişim kurabilirsin. İnsanlarla tanışmayı ve yeni arkadaşlar edinmeyi seviyoruz.