我正在尝试一起使用MapKit
和SpriteKit
,但我遇到了一个很大的问题。
我在我的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
}
}
我非常坚持这一点,非常感谢任何帮助! 提前谢谢!
答案 0 :(得分:0)
您的问题是视图控制器中的UIView层次结构,
以下是您的项目的样子:
控制器
--SKView
---- SKScene
--MKMapView
您需要将层次结构更改为
控制器
--MKMapView
--SKView
---- SKSceneView
我建议您在故事板中执行此操作,以便您可以将设计和代码分开。
更改层次结构后,需要在GameScene中执行以下操作:
view.allowsTransparency = true
view.backgroundColor = .clear
backgroundColor = .clear
这将为您提供一个没有背景颜色的视图和场景,这意味着您的地图将显示在其下方。
现在,如果您希望触摸事件触及MKMapView
而非SKView
,则需要在userInteractionEnabled
上停用MKMapView
,或将触摸事件传递给来自SKView
。