MKMapView覆盖SKSpriteNodes
我正在尝试使用MapKit
和SpriteKit
在一起,但我打了一个非常主要的墙。MKMapView覆盖SKSpriteNodes
我在我的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
}
}
我就这一个非常卡住,将不胜感激任何帮助! 在此先感谢!
你的问题是在你的视图控制器的UIView的层次结构,
这里是你的项目是什么样子:
控制器
--SKView
---- SKScene
- MKMapView
您需要将您的层次结构更改为
控制器
--MKMapView
--SKView
---- SKSceneView
我建议这样做您的故事板里面,这样就可以保持设计和代码分离。
你已经改变了你的层次结构后,你需要做以下在GameScene:
view.allowsTransparency = true
view.backgroundColor = .clear
backgroundColor = .clear
这会给你一个没有背景色,这意味着你的地图将下方显示的视图和场景它。
现在如果你想触摸事件打MKMapView
,而不是SKView
,那么你需要在你的MKMapView
禁用userInteractionEnabled
,或者从你的SKView
通过触摸事件的地图。
这可能是一个简单的问题,但我还没有使用过很多故事板......如何在故事板中获得SKView/SKSceneView? –
如果您使用默认模板,则已经有一个。他们为你做的 – Knight0fDragon
一个叫做视图?如果我试图按照上面建议的层次结构添加地图视图作为GameViewController的子项,它会删除其所有其他子项?我把它放在错误的地方? –
你真的应该试着保持设计和代码分离,如果你在你的小项目中养成了一种习惯,当你最终设计更大的应用程序时,你会发现它对你来说更容易。另外,当要求像SO这样的地方提供帮助时,它会变得更少显示代码,这意味着其他人可以更好地帮助你。 – Knight0fDragon
@ Knight0fDragon我会记住这一点 –