SpriteKit 使用手势移动节点

问题描述 投票:0回答:1

我正在练习编写 SpriteKit 游戏。 我正在尝试使用 SpriteKit 编写合并游戏(https://plays.org/merge-the-gems/)。

现在我已经用棋盘创建了游戏场景,在棋盘上添加了宝石并创建了移动交互。

这是 Gem 节点的代码:

import SpriteKit

class Gem: SKSpriteNode {
    
    private var touchOffset: CGPoint = CGPoint.zero
    private var originalPosition: CGPoint = CGPoint.zero
    
    init(size: CGSize) {
        super.init(
            texture: nil,
            color: .red,
            size: size
        )
        let numberLabel: SKLabelNode = .init(text: name)
        
        physicsBody = SKPhysicsBody(rectangleOf: .init(width: size.width - 2, height: size.height))
        physicsBody?.affectedByGravity = true
        physicsBody?.restitution = 0
        physicsBody?.friction = 0
        physicsBody?.allowsRotation = false
        physicsBody?.categoryBitMask = 0b0001
        physicsBody?.collisionBitMask = 0b0001
        physicsBody?.contactTestBitMask = 0b0001
        
        physicsBody?.node?.zPosition = 1
        
        physicsBody?.isDynamic = true
        
        isUserInteractionEnabled = true
        
        addChild(numberLabel)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else { return }
        physicsBody?.affectedByGravity = false
        
        let location = touch.location(in: parent!)
        
        if contains(location) {
            
            touchOffset = CGPoint(x: position.x - location.x, y: position.y - location.y)
            originalPosition = position
        }
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else { return }
        
        let location = touch.location(in: parent!)
        
        var newPosition = CGPoint(x: location.x + touchOffset.x, y: location.y + touchOffset.y)
        
        newPosition.x = max(min(newPosition.x, (scene?.size.width ?? 0) - size.width / 2), size.width / 2)
        newPosition.y = max(min(newPosition.y, (scene?.size.height ?? 0) - size.height / 2), size.height / 2)
        
        
        position = newPosition
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        let column: Int = Int(position.x / size.width)
        
        position.x = (CGFloat(column) * size.width) + (size.width / 2)
        
        physicsBody?.affectedByGravity = true
    }
}

这是场景代码:

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {
    
    override init(size: CGSize) {
        super.init(size: size)
        setupScene()
        createGameBoard()
        isUserInteractionEnabled = true
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setupScene() {
        physicsWorld.gravity = CGVector(dx: 0, dy: -7)
        physicsWorld.contactDelegate = self
        
        let borderBody: SKPhysicsBody = .init(edgeLoopFrom: self.frame)
        borderBody.friction = 0
        borderBody.restitution = 0
        
        self.physicsBody = borderBody
    }
    
    func createGameBoard() {
        let gemWidth: CGFloat = size.width / 6.0
        let gemSize: CGSize = .init(width: gemWidth, height: gemWidth)
        
        for row in 0..<8 {
            for column in 0..<6 {
                let positionX: CGFloat = CGFloat(column) * gemWidth + gemWidth / 2
                let positionY: CGFloat = size.height - (CGFloat(row) * gemWidth + gemWidth / 2)
           
                let backgroundNode: SKSpriteNode = getBackgroundNode()
                backgroundNode.size = gemSize
                backgroundNode.position = CGPoint(x: positionX, y: positionY)
                
                addChild(backgroundNode)
                
                if row >= 6 {
                    let gem: Gem = .init(size: gemSize)
                    
                    gem.size = gemSize
                    gem.position = CGPoint(x: positionX, y: positionY)
                    
                    addChild(gem)
                    gems.append(gem)
                }
            }
        }
    }

    
    func getBackgroundNode() -> SKSpriteNode {
        let background: SKSpriteNode = .init(imageNamed: "Diamond/empty")
        background.isUserInteractionEnabled = false
        return background
    }
}

问题。 问题是我无法实现与示例中相同的行为,只有当没有其他宝石在路上时我才能移动宝石。现在它只是在推动其他宝石。我需要与上面的示例完全相同的移动行为。

当我用手势移动宝石时,我需要其他宝石作为“墙”,这样我就可以沿着它们的侧面滑动。

ios swift sprite-kit
1个回答
0
投票

请尝试以下:

// Inside Gem class

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    
    let location = touch.location(in: parent!)
    
    // Check for collisions with other gems before updating the position
    if !checkForGemCollision(at: location) {
        // Update the position if no collision is detected
        // ... (your existing code for updating position)
    }
}

func checkForGemCollision(at location: CGPoint) -> Bool {
    // Implement collision detection logic here
    // Check for collisions with other gems and return true if a collision is detected
    // Otherwise, return false
    // Example pseudocode:
    // for each gem in gems {
    //     if gem.frame.contains(location) {
    //         return true
    //     }
    // }
    return false
}

通过合并 checkForGemCollision 方法并实现碰撞检测逻辑,您可以确保宝石仅在没有其他宝石阻碍时才移动。 此外,请确保正确设置宝石的物理属性,以实现准确的碰撞检测和处理。

© www.soinside.com 2019 - 2024. All rights reserved.