この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
物理エンジン ジョイント
今回は、ペンギンが隣り合わせになったら、手をつなぐ処理を作ります。
コードは前回からの続きです。
まず、ペンギンを生成するときに、手の領域のノードを追加します。今回は、動かしたときに見分けやすいように白くしています。
func addPenguinBlock() -> SKSpriteNode! {
....................
....................
....................
// 手を追加する。
let handRight = SKSpriteNode(color: UIColor(white: 1, alpha: 0.5) , size: CGSizeMake(40, 40))
handRight.position = CGPointMake(-46, 0)
handRight.name = "hand"
handRight.zPosition = 1
penguin.addChild(handRight)
let handLeft = SKSpriteNode(color: UIColor(white: 1, alpha: 0.5) , size: CGSizeMake(40, 40))
handLeft.position = CGPointMake(46, 0)
handLeft.name = "hand"
handLeft.zPosition = 1
penguin.addChild(handLeft)
// ペンギンをレイヤーに追加する。
isLandLayer?.addChild(penguin)
return penguin
}
次に、フレームごとの物理演算の後に呼ばれる didSimulatePhysics メソッドで、手が他のペンギンの手と重なっているかどうかを判別して、重なっている手(接続可能な手)がある場合は星印を追加して、手を削除します。
override func didSimulatePhysics() {
let isLandLayer = childNodeWithName("scrollLayer")?.childNodeWithName("isLandLayer")
for child in isLandLayer!.children {
jointHand(child as SKNode)
}
}
func jointHand(penguin:SKNode) {
for child in penguin.children {
let penguinHand:SKNode = child as SKNode
let penguinHandPoint:CGPoint = penguin.convertPoint(penguinHand.position, toNode: self)
// 接続可能な手を取得する。
let jointHand = jointHandFromHand(penguinHand, penguinHandPoint:penguinHandPoint)
// 接続する手がある場合は接続する。
if jointHand != nil {
addJoint(penguinHand, jointHand: jointHand)
}
}
}
func jointHandFromHand(penguinHand:SKNode, penguinHandPoint:CGPoint) ->SKNode! {
var jointHand:SKNode!
var nodes = nodesAtPoint(penguinHandPoint)
for node in nodes {
let childNode:SKNode! = node as? SKNode
if childNode != nil {
if penguinHand.parent != childNode.parent {
if childNode.name? == "hand" {
jointHand = childNode
break
}
}
}
}
return jointHand
}
func addJoint(penguinHand:SKNode, jointHand:SKNode)
{
let penguinHandPoint:CGPoint = penguinHand.parent!.convertPoint(penguinHand.position, toNode: self)
let jointHandPoint:CGPoint = jointHand.parent!.convertPoint(jointHand.position, toNode: self)
// 2点の中点を取得する。
let jointPoint:CGPoint = CGPointMake((penguinHandPoint.x + jointHandPoint.x) / 2.0,
(penguinHandPoint.y + jointHandPoint.y) / 2.0)
// 中点でジョイントする。
let jointPin = SKPhysicsJointPin
.jointWithBodyA(penguinHand.parent!.physicsBody,
bodyB: jointHand.parent!.physicsBody,
anchor: jointPoint)
physicsWorld.addJoint(jointPin)
// ジョイントの星印を追加する。
var joint:SKSpriteNode = SKSpriteNode(texture:atlas.textureNamed("link"))
joint.position = convertPoint(jointPoint, toNode: penguinHand.parent!)
joint.xScale = 0.0
joint.yScale = 0.0
joint.zPosition = penguinHand.parent!.zPosition + 1
penguinHand.parent!.addChild(joint)
joint.runAction(SKAction.scaleTo(1.0, duration: 0.2))
// 接続したら手を削除する。
jointHand.removeFromParent()
penguinHand.removeFromParent()
}
手を接続しているところでは、SKPhysicsJointPin を使っています。
では、動かしてみます。
白い四角の部分が手の領域で、星印のところが手をつないでいるところです。
いまさらだけど、ペンギンって「手」じゃなくて「翼」だったかな?まあいいか。。
動きを見たい方は、ぜひ「つみペンギン」をダウンロードしてみてください。
次回へ続く。ではでは。