英文:
How to add a gesture recognizer for a SpriteKit scene in SwiftUI?
问题
添加手势识别器的旧方法不再有效,因为视图始终为nil。这是因为在SwiftUI中没有视图主动呈现SpriteView场景。
class GameScene: SKScene {
override func sceneDidLoad() {
let gestureSwipe = UISwipeGestureRecognizer()
gestureSwipe.addTarget(self, action: #selector(gestureActionHandleSwipe(_:)))
view?.addGestureRecognizer(gestureSwipe)
/// `view` 始终为nil
struct ContentView: View {
var body: some View {
SpriteView(scene: GameScene())
}
要呈现场景,您可以在SKView类上调用presentScene(:)方法或presentScene(:transition:)方法。如果场景当前未呈现,则此属性为nil。
https://developer.apple.com/documentation/spritekit/skscene/1519726-view
模拟拖动手势使用touchesMoved函数似乎很容易。然而,模拟像pinch这样的手势并不那么直接。
那么在SwiftUI中如何为SpriteKit场景添加手势识别器呢?
英文:
The old way of adding a gesture recognizer no longer works because the view is always nil. This is because there is no view actively presenting the SpriteView scene in SwiftUI.
class GameScene: SKScene {
override func sceneDidLoad() {
let gestureSwipe = UISwipeGestureRecognizer()
gestureSwipe.addTarget(self, action: #selector(gestureActionHandleSwipe(_:)))
view?.addGestureRecognizer(gestureSwipe)
/// `view` is always nil
struct ContentView: View {
var body: some View {
SpriteView(scene: GameScene())
}
> To present a scene, you call the presentScene( method or presentScene(:transition:) method on the SKView class. If the scene is not currently presented, this property holds nil.
https://developer.apple.com/documentation/spritekit/skscene/1519726-view
Simulating a drag gesture with the touchesMoved function seems easy. However, simulating a gesture like pinch is not as straightforward.
So how can we gesture recognizer for a SpriteKit scene in SwiftUI?
答案1
得分: 1
你将更容易在SwiftUI级别捕获手势,然后将其传递给你的GameScene状态变量。
class GameScene: SKScene {
func swipeLeft() {
print("left")
}
func swipeRight() {
print("right")
}
}
struct Gesture: View {
@State var gameScene = GameScene()
var body: some View {
SpriteView(scene: gameScene)
.gesture(DragGesture(minimumDistance: 20, coordinateSpace: .global)
.onEnded { value in
let horizontalAmount = value.translation.width
let verticalAmount = value.translation.height
if abs(horizontalAmount) > abs(verticalAmount) {
(value.translation.width < 0) ? gameScene.swipeLeft() : gameScene.swipeRight()
}
})
}
}
英文:
you will have better luck capturing the gesture at the SwiftUI level, then passing it to your GameScene state variable
class GameScene: SKScene {
func swipeLeft() {
print("left")
}
func swipeRight() {
print("right")
}
}
struct Gesture: View {
@State var gameScene = GameScene()
var body: some View {
SpriteView(scene: gameScene)
.gesture(DragGesture(minimumDistance: 20, coordinateSpace: .global)
.onEnded { value in
let horizontalAmount = value.translation.width
let verticalAmount = value.translation.height
if abs(horizontalAmount) > abs(verticalAmount) {
(value.translation.width < 0) ? gameScene.swipeLeft() : gameScene.swipeRight()
}
})
}
}
答案2
得分: 0
要在didMove(to:)
方法中向场景的视图添加手势识别器,请使用SKScene
的convertPoint(fromView:)
和SKNode
的convert(_:to:)
方法来获取所需坐标空间中的触摸点。
/// 在将场景呈现到视图之前,SpriteKit会调用didMove(to:)方法;
/// 这是设置场景内容的一好地方。
///
/// 您可以使用这个方法来实现场景即将被视图呈现时的任何自定义行为。
/// 例如,您可以使用这个方法来创建场景的内容。
/// https://developer.apple.com/documentation/spritekit/skscene/1519607-didmove
override func didMove(to view: SKView) {
/// https://stackoverflow.com/a/50623843/2226315
/// https://munirwanis.github.io/blog/2020/wwdc20-spritekit-swiftui/
let pinchGesture = UIPinchGestureRecognizer()
pinchGesture.addTarget(self, action: #selector(gestureHandlerPinch(_:)))
view.addGestureRecognizer(pinchGesture)
let gestureSwipe = UISwipeGestureRecognizer()
gestureSwipe.addTarget(self, action: #selector(gestureHandlerSwipe(_:)))
view.addGestureRecognizer(gestureSwipe)
}
英文:
To add a gesture recognizer to the scene's view in didMove(to:), use SKScene's convertPoint(fromView:) and SKNode's convert(_:to:) methods to obtain the touch in the required coordinate space.
/// SpriteKit calls the method didMove(to:) before it presents your scene
/// in a view; it’s a good place to do some initial setup of your scene’s contents.
///
/// You can use this method to implement any custom behavior for your scene
/// when it is about to be presented by a view. For example, you might use this method to create the scene’s contents.
/// https://developer.apple.com/documentation/spritekit/skscene/1519607-didmove
override func didMove(to view: SKView) {
/// https://stackoverflow.com/a/50623843/2226315
/// https://munirwanis.github.io/blog/2020/wwdc20-spritekit-swiftui/
let pinchGesture = UIPinchGestureRecognizer()
pinchGesture.addTarget(self, action: #selector(gestureHandlerPinch(_:)))
view.addGestureRecognizer(pinchGesture)
let gestureSwipe = UISwipeGestureRecognizer()
gestureSwipe.addTarget(self, action: #selector(gestureHandlerSwipe(_:)))
view.addGestureRecognizer(gestureSwipe)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论