提问人:Bike Smith 提问时间:10/30/2023 最后编辑:Bike Smith 更新时间:11/6/2023 访问量:74
当两个 SK 节点相交时标记
flag when two sk nodes intersect
问:
在我的 swift 代码中,在一个名为 stick 的节点周围移动的左右按钮下方。我希望用户点击使摇杆与边界相交的按钮。debug 部分将打印 “flag”。我知道在 uikit 中有一个相交命令,但我不知道 sprite kit。蓝绿色是界限
import SpriteKit
import GameplayKit
class GameScene: SKScene , SKPhysicsContactDelegate {
var stick: SKSpriteNode!
var leftButton: SKSpriteNode!
var rightButton: SKSpriteNode!
var bounds: SKSpriteNode!
var objectThatHandlesContactLogic: ContactDetectionLogic!
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self // << from the previous step
backgroundColor = SKColor.white
objectThatHandlesContactLogic = ContactDetectionLogic()
physicsWorld.contactDelegate = objectThatHandlesContactLogic
// Create left and right buttons
leftButton = SKSpriteNode(color: .blue, size: CGSize(width: 100, height: 50))
leftButton.position = CGPoint(x: size.width * 0.2, y: size.height * 0.1)
addChild(leftButton)
rightButton = SKSpriteNode(color: .red, size: CGSize(width: 100, height: 50))
rightButton.position = CGPoint(x: size.width * -0.1, y: size.height * 0.1)
addChild(rightButton)
// Create and position the stick
physicsWorld.contactDelegate = self // << from the previous step
backgroundColor = SKColor.white
// Create and position the stick
let stickSize = CGSize(width: 160, height: 20)
stick = SKSpriteNode(color: .brown, size: stickSize)
stick.position = CGPoint(x: size.width * -0.2, y: size.height * -0.1)
addChild(stick)
// Add physics body to stick
stick.physicsBody = SKPhysicsBody(rectangleOf: stickSize)
stick.physicsBody!.categoryBitMask = 0b0000 // Means the stick doesn't belong to any category (all zeros)
stick.physicsBody!.collisionBitMask = 0b0000 // Means the stick collides with no category, i.e., doesn't collide with anything (all zeros)
stick.physicsBody!.contactTestBitMask = 0b0001 // Means the stick will only collide with nodes belonging to category 0001 (in binary. This also happens to mean category "1" in decimal)
stick.physicsBody!.affectedByGravity = false // since you dont want it falling off of the screen
// Create and position the bounds box
let boundsSize = CGSize(width: 150, height: 300)
bounds = SKSpriteNode(color: .systemTeal, size: boundsSize)
bounds.position = CGPoint(x: size.width * -0.4, y: size.height * -0.2)
addChild(bounds)
// add physics body to bounds
bounds.physicsBody = SKPhysicsBody(rectangleOf: boundsSize)
bounds.physicsBody!.collisionBitMask = 0b0000 // Means bounds collides with no category (all zeros)
bounds.physicsBody!.categoryBitMask = 0b0001 // Means the bounds belongs to category 0001 (in binary. Which again, translates to "1" in decimal), which if you remember, is what we set the stick to collide with
// the default value for bounds.physicsBody!.contactBitMask
// is already 0b0000 so no need to set it explicitly here.
// (You could do it for consistency sake if you'd like but it
// wouldn't matter since you're setting it to the same value it
// already is)
bounds.physicsBody!.affectedByGravity = false // since you dont want it falling off of the screen
// ...blah blah blah all the other code
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
if leftButton.contains(location) {
// Rotate the stick counterclockwise
let rotateAction = SKAction.rotate(byAngle: CGFloat(Double.pi / 4), duration: 1.0)
stick.run(rotateAction)
print("hit Left")
}
if rightButton.contains(location) {
// Rotate the stick clockwise
let rotateAction = SKAction.rotate(byAngle: -CGFloat(Double.pi / 4), duration: 1.0)
stick.run(rotateAction)
}
}
}
}
class ContactDetectionLogic: NSObject, SKPhysicsContactDelegate { // << Make sure you also add NSObject
// if you add this function, this function will be called when a contact between two nodes begins
func didBegin(_ contact: SKPhysicsContact) {
print("flag")
}
}
在这种情况下,我不认为相交是一种选择。
答:
0赞
rayaantaneja
10/30/2023
#1
步骤1:
SpriteKit 有一个检测系统,可以告诉您两个节点何时相互接触。通过将接触检测回调符合类,可以将该类添加到该类。SKPhysicsContactDelegate
例如。
class ContactDetectionLogic: NSObject, SKPhysicsContactDelegate { // << Make sure you also add NSObject
// if you add this function, this function will be called when a contact between two nodes begins
func didBegin(_ contact: SKPhysicsContact) {
print("flag")
}
}
您甚至可以使自己的协议符合此协议!(我通常这样做,我认为这是非常典型的做法)GameScene
class GameScene: SKScene, SKPhysicsContactDelegate { // << Here we add the conformance
// ...blah blah blah all the other code
func didBegin(_ contact: SKPhysicsContact) {
print("flag")
}
}
步骤2:
确定哪个对象将接收回调后,请确保将此对象分配给 .delegate
physicsWorld
例如:
var objectThatHandlesContactLogic: ContactDetectionLogic!
override func didMove(to view: SKView) {
objectThatHandlesContactLogic = ContactDetectionLogic()
physicsWorld.delegate = objectThatHandlesContactLogic
backgroundColor = SKColor.white
// ...blah blah blah all the other code
}
或者,如果你使场景本身符合协议(这同样是更典型的做法),你会这样做:
override func didMove(to view: SKView) {
physicsWorld.delegate = self // This is also much cleaner imo
backgroundColor = SKColor.white
// ...blah blah blah all the other code
}
步骤3:
添加委托后,您必须配置哪些接触的节点将触发它们。在你的例子中,它是棍子和边界,所以你这样做,我们为每个它们添加物理体:
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self // << from the previous step
backgroundColor = SKColor.white
// Create and position the stick
let stickSize = CGSize(width: 160, height: 20)
stick = SKSpriteNode(color: .brown, size: stickSize)
stick.position = CGPoint(x: size.width * -0.2, y: size.height * -0.1)
addChild(stick)
// Add physics body to stick
stick.physicsBody = SKPhysicsBody(rectangleOf: stickSize)
stick.physicsBody!.categoryBitMask = 0b0000 // Means the stick doesn't belong to any category (all zeros)
stick.physicsBody!.collisionBitMask = 0b0000 // Means the stick collides with no category, i.e., doesn't collide with anything (all zeros)
stick.physicsBody!.contactTestBitMask = 0b0001 // Means the stick will only collide with nodes belonging to category 0001 (in binary. This also happens to mean category "1" in decimal)
stick.physicsBody!.affectedByGravity = false // since you dont want it falling off of the screen
// Create and position the bounds box
let boundsSize = CGSize(width: 150, height: 300)
bounds = SKSpriteNode(color: .systemTeal, size: boundsSize)
bounds.position = CGPoint(x: size.width * -0.4, y: size.height * -0.2)
addChild(bounds)
// add physics body to bounds
bounds.physicsBody = SKPhysicsBody(rectangleOf: boundsSize)
bounds.physicsBody!.collisionBitMask = 0b0000 // Means bounds collides with no category (all zeros)
bounds.physicsBody!.categoryBitMask = 0b0001 // Means the bounds belongs to category 0001 (in binary. Which again, translates to "1" in decimal), which if you remember, is what we set the stick to collide with
// the default value for bounds.physicsBody!.contactBitMask
// is already 0b0000 so no need to set it explicitly here.
// (You could do it for consistency sake if you'd like but it
// wouldn't matter since you're setting it to the same value it
// already is)
bounds.physicsBody!.affectedByGravity = false // since you dont want it falling off of the screen
// ...blah blah blah all the other code
}
现在,每当联系开始时,您都应该得到一个打印件,上面写着“标志”。
希望这有帮助!如果您对联系系统的工作原理有疑问,请发表评论,我会回答他们
评论
0赞
Bike Smith
10/31/2023
在课堂上 contactDectectionLogic 它希望我添加 10 个资金,比如 func 执行。我该怎么办?
0赞
rayaantaneja
10/31/2023
哦,对不起,我打错了字。加。您的自定义类应该是 basic 的子类。很抱歉,我现在正在更新我的答案。让它知道你是否让它工作ContactDetectionLogic: NSObject, SKPhysicsContactDelegate
NSObject
0赞
Bike Smith
11/2/2023
当代码在第一秒内编译完成时,stick 和 bounds 都会直接在屏幕外动画,有什么方法可以阻止这种情况?
0赞
rayaantaneja
11/2/2023
我刚刚意识到你可能没有禁用它们的重力。因此,将每个物理体中的属性设置为affectedByGravity
false
0赞
rayaantaneja
11/2/2023
我再次更新了我的答案。非常抱歉给您带来麻烦,但它现在可以 100% 工作
评论