Kontrol/Gerakan SpriteKit

Pada dasarnya saya mencoba memasukkan tombol gamescene X2 yang melakukan fungsi berikut:

1) Ketuk untuk terbang (ini berfungsi) 2) Ketuk untuk menembakkan proyektil dari posisi Pemain (saya tidak berfungsi).

Masalah saya adalah saat ini saya mengatur fungsi fly ketika disentuh di mana saja di layar. Saya sudah mencoba yang berikut ini:

Ini mengacu pada GameScene saya: Saya pikir untuk membaginya, saya memerlukan simpul di layar untuk mereferensikan fungsi ini. Ini tidak error di konsol tetapi tidak muncul di GameScene.

// Tombol untuk memicu pemotretan :

    let btnTest = SKSpriteNode(imageNamed: "Crater")
    btnTest.setScale(0.2)
    btnTest.name = "Button"
    btnTest.zPosition = 10
    btnTest.position = CGPoint(x: 100, y: 200)
    self.addChild(btnTest)

Selanjutnya di kelas Player saya memiliki rincian berikut ini:

var shooting = false

var shootAnimation = SKAction()
var noshootAnimation = SKAction()


   Init func: 

    self.run(noshootAnimation, withKey: "noshootAnimation")

    let projectile = SKSpriteNode(imageNamed: "Crater")
    projectile.position = CGPoint (x: 100, y: 50)
    projectile.zPosition = 20
    projectile.name = "projectile"


    // Assigning categories to Game objects:
    self.physicsBody?.categoryBitMask =
        PhysicsCategory.plane.rawValue
    self.physicsBody?.contactTestBitMask =
        PhysicsCategory.ground.rawValue 
    self.physicsBody?.collisionBitMask =
        PhysicsCategory.ground.rawValue

    self.physicsBody?.applyImpulse(CGVector(dx: 300, dy: 0))
    self.addChild(projectile)



      // Start the shoot animation, set shooting to true:
       func startShooting() {


       self.removeAction(forKey: "noshootAnimation")
       self.shooting = true

   }

   // Stop the shoot animation, set shooting to false:
   func stopShooting() {


       self.removeAction(forKey: "shootAnimation")
       self.shooting = false
   }

Muncul node di GameScene yang terlihat menjanjikan, akhirnya saya pindah ke bit kode terakhir di GameScene sebagai berikut:

                override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)            for touch in (touches) {

                    let location = touch.location(in: self)

                    let nodeTouched = atPoint(location)

                    if let gameSprite = nodeTouched as? GameSprite {

                    gameSprite.onTap()
                    }

                    // Check the HUD buttons which I have appearing when game is over…
                    if nodeTouched.name == "restartGame" {
                    // Transition to a new version of the GameScene
                    // To restart the Game
                        self.view?.presentScene(GameScene(size: self.size), transition: .crossFade(withDuration: 0.6))
                    }
                    else if nodeTouched.name == "returnToMenu"{
                    // Transition to the main menu scene
                        self.view?.presentScene(MenuScene(size: self.size), transition: . crossFade(withDuration: 0.6))

                    }
            }

                Player.startFly()
                player.startShooting()

                    }

            override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
                Player.stopFly()
                player.stopShooting()

            }

            override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
                Player.stopFly()
                player.stopShooting()

            }

            override func update(_ currentTime: TimeInterval) {

                player.update()         
}
}

Sayangnya tidak ada yang terjadi di GameScene dan node tidak menyala ketika layar ditekan, dengan kode di atas tetap ada, saya dapat mengubahnya untuk memungkinkan fungsi 'ketuk untuk terbang' + 'ketuk untuk menembak'. Saya masih tidak tahu cara agar tombol yang telah saya nyatakan di awal GameScene muncul di mana posisi gerakan/sentuhan saya dapat dilokalisasi ke simpul ini di layar, bukan ke seluruh layar yang saya miliki saat ini. .

Saya dapat mengatakan ini terdengar lebih sederhana di kepala saya daripada benar-benar membuat kode bersama.


person AJ James    schedule 25.05.2020    source sumber


Jawaban (1)


Pertama, kode di atas tidak memiliki panggilan untuk menjalankan animasi dengan kunci "shootAnimation" dan tidak ada panggilan untuk menjalankan kembali animasi yang tidak memotret ketika stopShooting() dan panggilan untuk menjalankan kembali animasi pemotretan di startShooting(). Metodenya harus mencakup hal-hal seperti yang ditunjukkan di bawah ini

func startShooting() {
    self.removeAction(forKey: "noshootAnimation")

    // Add this call
    self.run(shootAnimation)
    self.shooting = true
}

func stopShooting() {
    self.removeAction(forKey: "shootAnimation")

    // Add this call
    self.run(noshootAnimation)
    self.shooting = true
}

Kedua, animasi noshootAnimation dan shootAnimation adalah tindakan kosong: keduanya tidak akan melakukan apa pun jika diinisialisasi sebagai SKAction(). Tergantung pada apa yang Anda coba lakukan, ada sejumlah metode kelas SKAction yang akan membuat tindakan untuk Anda di sini.

Ketiga, SKNode mana pun (ingat bahwa sebuah adegan adalah subkelas SKNode) tidak akan menerima panggilan sentuh jika properti isUserInteractionEnabled node disetel ke false (yang merupakan default); sebaliknya, ia akan diperlakukan seolah-olah induknya menerima panggilan tersebut. Namun, jika isUserInteractionEnabled sebuah node adalah true, maka node itulah yang menerima panggilan UIResponder, bukan node induknya. Pastikan bahwa properti ini diatur ke true untuk adegan dan untuk setiap node yang perlu menerima sentuhan (Anda dapat melakukan ini di didMove(to:) dalam adegan atau di tempat lain).

Sekarang saya akan mengusulkan perbaikan. Saya sering menggunakan tombol di Spritekit, tetapi semuanya merupakan subkelas dari kelas tombol khusus (itu sendiri merupakan subkelas SKSpriteNode) yang menggunakan delegasi protokol untuk memperingatkan anggota tentang peristiwa sentuh. Skemanya terlihat seperti ini:

class Button: SKSpriteNode {
    weak var responder: ButtonResponder?
    // Custom code

    // MARK: UIResponder
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)

        // Respond here
        responder?.respond(to: self)
    }
}

protocol ButtonResponder: AnyObject {
    func respond(to button: Button)
}

class MyScene: SKScene, ButtonResponder {
    func respond(to button: Button) {
        // Do something on touch, but typically check the name

        switch button.name {
        case "myButton":
            // Do something specific
        default:
            break
        }
    }

    override func didMove(to view: SKView) {
        // Set the scene as a responder
        let buttonInScene = childNode(withName: "myButton") as! Button
        buttonInScene.responder = self
    }
}

Untuk mengetahui lebih lanjut tentang delegasi, lihat di sini. Semoga ini sedikit membantu.

EDIT: Konversi lokasi sentuh

Anda dapat mengonversi sentuhan menjadi simpul di layar dengan meneruskan referensi ke metode location(in:) dari UITouch alih-alih adegan seperti yang Anda lakukan di kode Anda

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)

    let yourNode = childNode(withName: "yourNode")!
    for touch in touches {
        let touchLocationToYourNode = touch.location(in: yourNode)
        // Do something
    }
}

Alternatifnya, gunakan metode convert(_:from:) dan convert(_:to:) SKNode

let nodeA = SKNode()
let nodeB = SKNode()

nodeA.xScale = 1.5
nodeA.yScale = 1.2
nodeA.position = .init(x: 100, y: 100)
nodeA.zRotation = .pi

let pointInNodeACoordinateSystem = CGPoint(x: 100, y: 100)
let thatSamePointInNodeBCoordinateSystem = nodeB.convert(pointInNodeACoordinateSystem, from: nodeA)
person Left as an exercise    schedule 25.05.2020
comment
Halo! Terima kasih atas waktunya mengulas postingan ini! Saya telah menerapkan sesuai proposal Anda di atas dengan pertimbangan, ini semua bekerja dengan sempurna!! Rasa frustrasi selama berjam-jam terpecahkan! Saya akhirnya memiliki fungsi tombol yang berfungsi selama GameScene, terima kasih atas panduan logisnya, ini pasti membantu pemahaman saya!! - person AJ James; 26.05.2020