0

我正在尝试编写一个游戏,其中星星从 iphone 屏幕的顶部落到底部。我想在它们离开屏幕时删除我的星图。我尝试使用physicsContactDelegate,并使用edgeFromLoop(self.frame)在我的框架周围创建一个边缘,但从未调用过didBegin。

下面是我的 gameScene.swift 文件

import SpriteKit
import GameplayKit
import UIKit

class GameScene: SKScene, SKPhysicsContactDelegate {

    var entities = [GKEntity]()
    var graphs = [String : GKGraph]()

    private var lastUpdateTime : TimeInterval = 0

    struct PhysicsCategory {
      static let none: UInt32 = 0
      static let all : UInt32 = UInt32.max
      static let star: UInt32 = 0b1       // 1
      static let edge: UInt32 = 0b10      // 2
    }

    private var edge: SKPhysicsBody!

    override func sceneDidLoad() {

        self.lastUpdateTime = 0

        edge = SKPhysicsBody(edgeLoopFrom: self.frame)
        edge.categoryBitMask = PhysicsCategory.edge
        edge.contactTestBitMask = PhysicsCategory.star
        edge.collisionBitMask = PhysicsCategory.star
    }


    override func didMove(to view: SKView) {

        physicsWorld.contactDelegate = self

        run(SKAction.repeatForever(
            SKAction.sequence([
                SKAction.run(addStar),
                SKAction.wait(forDuration: 1.0)
            ])
      ))
    }

    func didBegin(_ contact: SKPhysicsContact) {

      print("didBegin called")
      // 1
      var firstBody: SKPhysicsBody
      var secondBody: SKPhysicsBody
      if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
      } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
      }

      if((firstBody.categoryBitMask & PhysicsCategory.star != 0) &&
          (secondBody.categoryBitMask & PhysicsCategory.edge != 0)){

          print("call destroyStar")
          if let star = firstBody.node as? SKSpriteNode {
              destroyStar(star: star)
          }
      }
    }

    func addStar(){

        let star = SKSpriteNode(imageNamed: "star")

        let scale = CGFloat.random(in: 0.1 ... 0.5)
        star.xScale = scale
        star.yScale = scale
        star.zPosition = 1.0

        star.physicsBody = SKPhysicsBody(rectangleOf: star.size)
        star.physicsBody?.linearDamping = 1.0
        star.physicsBody?.friction = 1.0

        star.physicsBody?.isDynamic = true // 2
        star.physicsBody?.categoryBitMask = PhysicsCategory.star // 3
        star.physicsBody?.contactTestBitMask = PhysicsCategory.edge // 4
        star.physicsBody?.collisionBitMask = PhysicsCategory.edge

        let actualX = CGFloat.random(in: (-1*size.width/2)+50 ... (size.width/2)-50)

        star.position = CGPoint(x: actualX, y: self.size.height)
        addChild(star)
    }

    override func update(_ currentTime: TimeInterval) {
        // Called before each frame is rendered

        // Initialize _lastUpdateTime if it has not already been
        if (self.lastUpdateTime == 0) {
            self.lastUpdateTime = currentTime
        }

        // Calculate time since last update
        let dt = currentTime - self.lastUpdateTime

        // Update entities
        for entity in self.entities {
            entity.update(deltaTime: dt)
        }

        self.lastUpdateTime = currentTime
    }

    func destroyStar(star: SKSpriteNode){

        print("star destroyed")
        star.removeFromParent()

    }
}

这是我的 GameViewController

import UIKit
import SpriteKit
import GameplayKit

class GameViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Load 'GameScene.sks' as a GKScene. This provides gameplay related content
        // including entities and graphs.
        if let scene = GKScene(fileNamed: "GameScene") {

            // Get the SKScene from the loaded GKScene
            if let sceneNode = scene.rootNode as! GameScene? {

                // Copy gameplay related content over to the scene
                sceneNode.entities = scene.entities
                sceneNode.graphs = scene.graphs

                // Set the scale mode to scale to fit the window
                sceneNode.scaleMode = .aspectFit

                // Present the scene
                if let view = self.view as! SKView? {
                    view.presentScene(sceneNode)

                    view.ignoresSiblingOrder = true

                    view.showsFPS = true
                    view.showsNodeCount = true
                }
            }
        }
    }

    override var shouldAutorotate: Bool {
        return true
    }

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        if UIDevice.current.userInterfaceIdiom == .phone {
            return .allButUpsideDown
        } else {
            return .all
        }
    }

    override var prefersStatusBarHidden: Bool {
        return true
    }
}

我是一个快速的初学者,我知道我的问题可能非常基本,但我非常感谢任何帮助!谢谢!

4

1 回答 1

1

您需要制作边缘和 SKNode(),然后将physicsBody 分配给边缘。

尝试这个。

let edge = SKNode()

override func didMove(to View: SKView) {
    edge.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
    edge.physicsBody.categoryBitMask = PhysicsCategory.edge
    edge.physicsBody.contactTestBitMask = PhysicsCategory.star
    edge.physicsBody.collisionBitMask = PhysicsCategory.star

    self.addChild(edge)
}
于 2020-07-19T20:42:11.743 回答