我正在使用 SpriteKit for iOS 应用程序和 Swift。
我制作了一个小的 SKShapeNode("ball") 和一个大的圆圈路径("room"),我希望 SKShapeNode 留在圆圈内。
这是我的代码:
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var isFingerOnBall = false
var ball: SKShapeNode!
var room: SKShapeNode!
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self)
if let body = physicsWorld.body(at: touchLocation) {
if body.node!.name == "ball" {
isFingerOnBall = true
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self)
if isFingerOnBall {
ball.position = touchLocation
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
isFingerOnBall = false
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func didMove(to view: SKView) {
self.physicsWorld.contactDelegate = self
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
let radius:CGFloat = 60
// BALL
ball = SKShapeNode(circleOfRadius: radius)
ball.name = "ball"
ball.fillColor = .red
ball.strokeColor = .clear
ball.position = CGPoint(x: 0, y: 150)
ball.physicsBody = SKPhysicsBody(circleOfRadius: radius)
ball.physicsBody?.isDynamic = true
scene?.addChild(ball)
// ROOM
room = SKShapeNode(circleOfRadius: radius * 5)
room.name = "room"
room.strokeColor = .white
room.lineWidth = 10
room.position = CGPoint(x: 0, y: 0)
room.physicsBody = SKPhysicsBody(edgeLoopFrom: room.path!)
room.physicsBody?.isDynamic = false
scene?.addChild(room)
}
}
我预计房间的 SKPhysicsBody 会限制球超出路径, OK image
但是当我的手指将球拖出圆圈(房间)时,它也熄灭了。 No good image
提前致谢。
最佳答案
有几种方法可以做到这一点,但我能想到的最简单的方法是用这个替换你的 didMove(to view: SKView) 方法:
override func didMove(to view: SKView) {
self.physicsWorld.contactDelegate = self
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
// BALL
let ball = SKShapeNode(circleOfRadius: 10)
ball.fillColor = .yellow
ball.strokeColor = .yellow
ball.lineWidth = 5
ball.physicsBody = SKPhysicsBody(circleOfRadius: 10)
ball.physicsBody?.isDynamic = true
ball.physicsBody?.affectedByGravity = true
ball.physicsBody?.categoryBitMask = 1
ball.physicsBody?.collisionBitMask = 2
ball.physicsBody?.contactTestBitMask = 0
addChild(ball)
// ROOM
let room = SKShapeNode(circleOfRadius: 200)
room.fillColor = .clear
room.strokeColor = .red
room.lineWidth = 5
room.physicsBody = SKPhysicsBody(edgeLoopFrom: room.path!)
room.physicsBody?.isDynamic = false
room.physicsBody?.affectedByGravity = false
room.physicsBody?.categoryBitMask = 2
room.physicsBody?.collisionBitMask = 0
room.physicsBody?.contactTestBitMask = 0
addChild(room)
}
基本上您只需要设置 PhysicsBody CategoryBitMask 和 Collision Bit mask。也不要分配固体物理体,注意使用“edgeFromLoop”来制作房间物理体。
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self)
if isFingerOnBall {
let roomRadius: CGFloat = 200
let hyp = sqrt(touchLocation.x * touchLocation.x + touchLocation.y * touchLocation.y)
if abs(hyp) > roomRadius {
ball.position = ball.position
} else {
ball.position = touchLocation
}
}
}
在这里,您将获得新接触点的斜边,并检查它是否大于房间的半径。如果是,则球的位置保持不变,如果不是,则照常更新球的位置。
希望这对您有所帮助,祝您玩得愉快
关于swift - 如何防止使用触摸位置处理的 SKShapeNode 超出圆形路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58681532/