UIViewの座標とSKNodeの座標の違い


UIViewの座標とSKNodeの座標の違い

SpriteKitでゲームを作った際、UIKitと組み合わせてみた時に混乱したのでメモ

ビュー座標とシーン座標

MyPlayground.playground
import UIKit
import SpriteKit
import XCPlayground

let liveView = SKView(
    frame: CGRect(
        origin: CGPointZero,
        size: CGSize(width: 300, height: 300)
    )
)

XCPlaygroundPage.currentPage.liveView = liveView
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

// 今回適応してみるCGRect
let rect = CGRect(
    origin: CGPoint(x: 40, y: 20),
    size: CGSize(width: 80, height: 40)
)

// SKSceneを作って、Nodeを入れる
let skScene = SKScene(size: liveView.frame.size)
liveView.presentScene(skScene)

let node = SKShapeNode(rect: rect)
node.fillColor = UIColor.blueColor()
skScene.addChild(node)

// 同じCGRectのUIViewを入れるとどうなるの?
let uiView = UIView(frame: rect)
uiView.backgroundColor = UIColor.redColor()
liveView.addSubview(uiView)

UIViewとSKNodeに同じRectを適応しても、
originの原点位置とxy軸の方向が異なっているのがわかる

中心点

ちなみにそれぞれ中心点はframe.midX, frame.midYで分かる (get only)

MyPlayground.playground
CGPoint(x: uiView.frame.midX, y: uiView.frame.midY) // {x 80 y 40}
CGPoint(x: node.frame.midX, y: node.frame.midY) // {x 80 y 40}

SKNodeの場合は、positionを指定することで中心から描画することもできる

MyPlayground.playground
let center = CGPoint(x: liveView.frame.midX, y: liveView.frame.midY)
let node2 = SKShapeNode(rectOfSize: rect.size)
node2.position = center
node2.fillColor = UIColor.purpleColor()
skScene.addChild(node2)

座標の変換

ビュー座標とシーン座標はお互い変換することができる

convertPointToView

MyPlayground.playground
// シーン座標からビュー座標へ変換
let convertToViewOrigin = skScene.convertPointToView(uiView.frame.origin)
convertToViewOrigin     // x 40 y 280

let node3 = SKShapeNode(
    rect: CGRect(
        origin: convertToViewOrigin,
        size: rect.size
    )
)
node3.fillColor = UIColor.brownColor()
skScene.addChild(node3)

これにより、UIViewとoriginは一緒の位置になる
が、sizeによる描画方向はそれぞれ異なっているのに注意

convertPointFromView

MyPlayground.playground
// ビュー座標からシーン座標へ変換
let convertFromViewOrigin = skScene.convertPointFromView(node.frame.origin)
convertFromViewOrigin   // x 38.65 y 281.35

let uiView2 = UIView(frame:
    CGRect(
        origin: convertFromViewOrigin,
        size: rect.size
    )
)
uiView2.backgroundColor = UIColor.yellowColor()
liveView.addSubview(uiView2)

微妙に座標がズレて小数点が出ているのは、
SKNodeの枠線が入っている分も計算してくれるからのようだった


そもそもSpriteKitとUIKitごちゃまぜでゲーム作るのって変なのかな。
全部SKNodeでやる方がいいのかな。よくわからない。

説明しやすいように「ビュー座標」と「シーン座標」と名づけてますが、
正式な呼び方なのかわかんないので、あんまり信用しないでください。。。