繁体   English   中英

SpriteKit applyImpulse不影响Sprite

[英]SpriteKit applyImpulse not affecting sprite

我有一个类型为Skier的播放器节点,我想通过触摸和拖动来绕x轴移动,类似于本教程 我将播放器节点添加到场景中,并且它的物理主体将isDynamic设置为true,但是由于某些原因,当我触摸并拖动播放器时,它不会移动。 我究竟做错了什么? 这是我的GameScene和我的Skier课程:

滑雪者:

class Skier: SKSpriteNode {
    let playerTexture = SKTexture(imageNamed: "snowmanFancy_NE")
    let playerSize = CGSize(width: 24, height: 40)

    init () {
        super.init(texture: playerTexture, color: UIColor.clear, size: playerSize)
        self.name = "player"
        setPhysics()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setPhysics(){
        self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        self.physicsBody? = SKPhysicsBody(rectangleOf: size)
        self.physicsBody?.categoryBitMask = PhysicsCategory.player
        self.physicsBody?.contactTestBitMask = PhysicsCategory.tree | 
        PhysicsCategory.rock | PhysicsCategory.cabin | PhysicsCategory.snowman | 
        PhysicsCategory.marker
        self.physicsBody?.collisionBitMask = 0
        self.physicsBody?.allowsRotation = false
        self.physicsBody?.angularDamping = 0
        self.physicsBody?.isDynamic = true
    }
}

GameScene:

class GameScene: SKScene, SKPhysicsContactDelegate {
    var lastTouch: CGPoint? = nil

    var world = SKNode()
    var cam = SKCameraNode()

    var player = Skier()
    let playerDefaultYInset : CGFloat = 350

    var sceneVelocity = CGVector(dx: 0, dy: -170)
    var zPositionCounter: CGFloat = 0

    override func didMove(to view: SKView) {
        //Set up the scene
        self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        backgroundColor = SKColor.white

        //Add top-level world node to the scene
        self.addChild(world)

        self.physicsWorld.contactDelegate = self

        //Add player to scene
        spawnPlayer()
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        if let location = touch?.location(in: self) {
            lastTouch = location
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        if let location = touch?.location(in: self) {
            lastTouch = location
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        lastTouch = nil
    }

    override func update(_ currentTime: TimeInterval) {
        // Only add an impulse if there's a lastTouch stored
        if let touch = lastTouch {
            let impulseVector = CGVector(dx: touch.x - player.position.x, dy: 0)
            // If myShip starts moving too fast or too slow, you can multiply impulseVector by a constant or clamp its range
            player.physicsBody?.applyImpulse(impulseVector)
        }
    }

    func spawnPlayer() {
        player.position = CGPoint(x: 0, y: (-self.frame.height / 2) + playerDefaultYInset)
        player.zPosition = CGFloat(Int.min)
        world.addChild(player)
    }
}

我发现自己在做什么错。 当我为“滑雪者”课程设置物理身体时,我为该物理身体分配了以下可选内容:

self.physicsBody? = SKPhysicsBody(rectangleOf: size)

因此实际上并未将物理主体分配给该子画面。 我将其更改为:

self.physicsBody = SKPhysicsBody(rectangleOf: playerSize)

现在它可以完美运行了。 话虽这么说,对于任何其他尝试通过手指拖动精灵在场景中移动来达到类似效果的人,我最终都提出了一个简单得多的解决方案。 我的touchesMoved方法中有以下内容:

let touch = touches.first
    if let location = touch?.location(in: self) {
        let prev = touch?.previousLocation(in: self)
        let impulse = CGVector(dx: 0.02 * (location.x - (prev?.x)!), dy: 0)
        player.physicsBody?.applyImpulse(impulse)
}

它的工作原理完全不必担心更新,touchesBegan或touchesEnded方法。 变得越来越简单。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM