MKMapView涵盖SKSpriteNodes

时间:2017-09-07 04:02:55

标签: ios swift sprite-kit mapkit skscene

我正在尝试一起使用MapKitSpriteKit,但我遇到了一个很大的问题。

我在我的GameScene中设置了我的地图,因为我不希望场景覆盖它,但是当我尝试向视图添加SpriteNode时,它并没有显示。减少地图的alpha后,我可以看到精灵正在地图下面渲染。 更改zPosition没有帮助,因为我假设MKMapView之类的观点与SpriteKit个对象位于不同的层上。

基本上我想要完成的是将SpriteKit个元素放在MKMapView之上(如果可能的话,没有故事板 - 我试图以编程方式完成所有操作)。我花了好几个小时试图在互联网上找到答案,但没有成功。

这是我的GameScene

    import UIKit
    import SpriteKit
    import GameplayKit
    import MapKit
    import CoreLocation

    class GameScene: SKScene, MKMapViewDelegate, CLLocationManagerDelegate {

        let locationManager = CLLocationManager()

        var map = MKMapView()

        let healthBar = SKSpriteNode(imageNamed: "Square")
        let maxHealthBar = SKSpriteNode(imageNamed: "Square")

        var UID = String()
        var ref = DatabaseReference()

        static var username = String()
        static var health = Int()
        static var maxHealth = Int()

        var width = CGFloat()
        var right = CGFloat()
        var left = CGFloat()
        var top = CGFloat()
        var bot = CGFloat()
        var margin = CGFloat()
        var middleX = CGFloat()
        var middleY = CGFloat()

        var maxBarWidth = CGFloat()

        override func didMove(to view: SKView) {

            map.frame = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
            map.delegate = self
            map.showsScale = false
            map.showsPointsOfInterest = false
            map.showsUserLocation = true
            map.showsBuildings = true
            map.isZoomEnabled = false
            map.isScrollEnabled = false
            map.isPitchEnabled = false
            map.isRotateEnabled = false

            let region = MKCoordinateRegionMakeWithDistance((locationManager.location?.coordinate)!, 400, 400)

            map.setRegion(region, animated: false)

            print("region:", map.region)

            locationManager.requestWhenInUseAuthorization()

            if (CLLocationManager.locationServicesEnabled()) {

                locationManager.delegate = self
                locationManager.desiredAccuracy = kCLLocationAccuracyBest
                locationManager.startUpdatingLocation()

            }

            view.addSubview(map)

            width = frame.width
            right = frame.width
            left = frame.width - frame.width
            top = frame.height
            bot = frame.height - frame.height
            margin = frame.width / 75
            middleX = frame.width / 2
            middleY = frame.height / 2

            maxBarWidth = width - margin * 2
            let maxBarHeight = CGFloat(30)
            let healthBarWidth = width - margin * 2
            let barHeight = maxBarHeight * 0.75

            maxHealthBar.anchorPoint = CGPoint(x: 0.0, y: 0.5)
            maxHealthBar.position = CGPoint(x: middleX, y: top - margin - maxBarHeight / 2)
            maxHealthBar.size = CGSize(width: maxBarWidth, height: maxBarHeight)
            maxHealthBar.color = UIColor.black
            maxHealthBar.colorBlendFactor = 1.0
            maxHealthBar.zPosition = 1.1
            self.addChild(maxHealthBar)

            healthBar.anchorPoint = CGPoint(x: 0.0, y: 0.5)
            healthBar.position = CGPoint(x: middleX - healthBarWidth / 2, y: maxHealthBar.position.y)
            healthBar.size = CGSize(width: healthBarWidth, height: barHeight)
            healthBar.color = UIColor.red
            healthBar.colorBlendFactor = 1.0
            healthBar.zPosition = 1000000
            self.addChild(healthBar)

            print("parent", healthBar.parent)

        }

        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            for t in touches {
                let location = t.location(in: self)

                takeDamage(damage: 10)

            }
        }

        func takeDamage(damage: Int) {

            GameScene.health -= damage

            updateHealth()

        }

        func updateHealth() {

            let percentFull = CGFloat(GameScene.health / GameScene.maxHealth)
            let healthWidth = maxBarWidth * percentFull

            healthBar.size.width = healthWidth

        }

        func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
            map.setCenter((locationManager.location?.coordinate)!, animated: true)
        }

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

这是我的GameViewController

    import UIKit
    import SpriteKit
    import GameplayKit

    class GameViewController: UIViewController {

        override func viewDidLoad() {
            super.viewDidLoad()
        }

        override func viewWillLayoutSubviews() {
            super.viewWillLayoutSubviews()

            if (SignInScene.signInLoaded == false) {

                if let scene = GameScene(fileNamed: "GameScene") {
                    // Configure the view.
                    let skView = self.view as! SKView
                    skView.showsFPS = true
                    skView.showsNodeCount = true

                    /* Sprite Kit applies additional optimizations to improve rendering performance */
                    skView.ignoresSiblingOrder = true

                    /* Set the scale mode to scale to fit the window */
                    scene.size = skView.bounds.size
                    scene.scaleMode = .aspectFill

                    skView.presentScene(scene)
                }

            }

        }

        override var shouldAutorotate: Bool {
            return false
        }

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

        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Release any cached data, images, etc that aren't in use.
        }

        override var prefersStatusBarHidden: Bool {
            return false
        }
    }

我非常坚持这一点,非常感谢任何帮助! 提前谢谢!

1 个答案:

答案 0 :(得分:0)

您的问题是视图控制器中的UIView层次结构,

以下是您的项目的样子:

  

控制器
  --SKView
  ---- SKScene
  --MKMapView

您需要将层次结构更改为

  

控制器
  --MKMapView
  --SKView
  ---- SKSceneView

我建议您在故事板中执行此操作,以便您可以将设计和代码分开。

更改层次结构后,需要在GameScene中执行以下操作:

view.allowsTransparency = true
view.backgroundColor = .clear
backgroundColor = .clear

这将为您提供一个没有背景颜色的视图和场景,这意味着您的地图将显示在其下方。

现在,如果您希望触摸事件触及MKMapView而非SKView,则需要在userInteractionEnabled上停用MKMapView,或将触摸事件传递给来自SKView

的地图