>我试图在SKShapeNode实例和屏幕边缘之间创建冲突,但由于某种原因,ShapeNode仍然超出了屏幕的限制。我已经实现了我认为应该处理碰撞的代码,但我是 SpriteKit 的新手,所以我不完全确定。下面是一段代码:
//
// GameScene.swift
// SpriteKitTest
//
// Created by 580380 on 3/10/16.
// Copyright (c) 2016 580380. All rights reserved.
//
import SpriteKit
import UIKit
import CoreMotion
class GameScene: SKScene {
//MARK: - Global variables
let motionManager = CMMotionManager()
var circleNode = SKShapeNode()
var destX : CGFloat = 0.0
var destY : CGFloat = 0.0
enum Collision :UInt32 {
case ball = 1
case wall = 2
}
//MARK: - Sprite kit functionality
override func didMoveToView(view: SKView) {
backgroundColor = UIColor.whiteColor()
createCircleNode()
moveCircleNode()
self.addChild(circleNode)
}
//Setup and configuring the SKShapeNode object
private func createCircleNode() {
circleNode.path = UIBezierPath(arcCenter: CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)), radius: 20, startAngle: 0, endAngle: CGFloat(2*M_PI), clockwise: true).CGPath
circleNode.fillColor = UIColor.redColor()
circleNode.strokeColor = UIColor.blueColor()
circleNode.lineWidth = 1
}
private func moveCircleNode() {
circleNode.physicsBody = SKPhysicsBody()
circleNode.physicsBody?.dynamic = true
circleNode.physicsBody?.affectedByGravity = false
if motionManager.accelerometerAvailable {
motionManager.accelerometerUpdateInterval = 0.1
motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.mainQueue(), withHandler: { (data, error) -> Void in
self.destX = self.circleNode.position.x + CGFloat(data!.acceleration.x*100)
self.destY = self.circleNode.position.y + CGFloat(data!.acceleration.y*200)
})
}
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody!.dynamic = true
self.physicsBody!.affectedByGravity = false
self.physicsBody!.categoryBitMask = Collision.wall.rawValue
self.physicsBody!.collisionBitMask = Collision.ball.rawValue
}
override func update(currentTime: NSTimeInterval) {
let destXAction = SKAction.moveToX(destX, duration: 0.1)
let destYAction = SKAction.moveToY(destY, duration: 0.1)
self.circleNode.runAction(destXAction)
self.circleNode.runAction(destYAction)
}
}
知道我可能在哪里出错吗?
这里的主要问题是游戏场景从未真正设置其大小。
在GameViewController
将行scene.size = skView.bounds.size
添加到 let skView = self.view as! SKView
下。
这将正确设置场景的大小,所以现在你的球应该与屏幕边缘碰撞。但是,当您设置circleNode
路径时,您实现它的方式将圆圈偏移了屏幕大小的一半。
如果您希望圆圈出现在屏幕中间,更好的解决方案是 circleNode = SKShapeNode(circleOfRadius: 20)
而不是 circleNode.path = UIBezierPath(arcCenter: CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)), radius: 20, startAngle: 0, endAngle: CGFloat(2*M_PI), clockwise: true).CGPath
.然后将其设置为位于中心,并带有 circleNode.position = CGPointMake(frame.width/2, frame.height/2)
.
这应该可以解决您的整体问题,但是您可能会注意到球可能会从屏幕边缘消失。要解决此问题,请将更新方法更改为如下所示
func clamp(value: CGFloat, min: CGFloat, max: CGFloat) -> CGFloat {
if value > max {
return max
}
if value < min {
return min
}
return value
}
override func update(currentTime: NSTimeInterval) {
let ballRadius: CGFloat = 10
destX = clamp(destX, min: ballRadius, max: frame.width - ballRadius)
destY = clamp(destY, min: ballRadius, max: frame.height - ballRadius)
let destXAction = SKAction.moveToX(destX, duration: 0.1)
let destYAction = SKAction.moveToY(destY, duration: 0.1)
self.circleNode.runAction(destXAction)
self.circleNode.runAction(destYAction)
}
这将使球永远不要试图超出屏幕的范围。我还建议添加circleNode.physicsBody?.usesPreciseCollisionDetection = true
以便您的碰撞更准确。