我有一个 Skier 类型的播放器节点,我想通过触摸和拖动围绕 x 轴移动,类似于 this tutorial .我将我的播放器节点添加到场景中,它有一个 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
}
}
游戏场景:
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)
}
}
最佳答案
我发现我做错了什么。当我为 Skier 类设置我的物理体时,我像这样分配了一个可选的物理体:
self.physicsBody? = SKPhysicsBody(rectangleOf: size)
所以物理体实际上并没有分配给 sprite。我通过将其更改为此来修复它:
self.physicsBody = SKPhysicsBody(rectangleOf: playerSize)
现在它完美运行了。话虽这么说,对于任何其他试图通过手指拖动在场景中移动 Sprite 来实现类似效果的人来说,我最终想出了一个更简单的解决方案。我的 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 方法。更简单、更容易。
关于ios - SpriteKit applyImpulse 不影响 Sprite ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54780380/