ApplyImpulse оказывает экспоненциальное влияние на то, насколько сильно он толкает объект

В этом простом физическом моделировании есть немного странного поведения. ApplyImpulse применяется каждые 5 секунд, но каждый раз, когда это происходит, коробка поднимается еще выше, даже если для applyImpulse используется то же значение. Примерно через 20 секунд коробка взлетает очень высоко.

К коробке прикреплена небольшая красная коробка, где и применяется импульс.

ФОТОГРАФИИ СЪЕМКИ:

ЭТО КОД:

import SpriteKit

enum collisionType: UInt32 {
    case obj = 0b1 //1
    case bottom = 0b10 //2
}

var cam: SKCameraNode?
var screenSize = CGSize()

class GameScene: SKScene, SKPhysicsContactDelegate {

    let obj = SKSpriteNode(color: .white, size: CGSize(width: 50, height: 50))
    var camBottom = SKSpriteNode()
    let block = SKSpriteNode(color: .red, size: CGSize(width: 25, height: 25))

Затем в override func didMove(to view: SKView):

    screenSize = self.size
    camBottom = SKSpriteNode(color: .gray, size: CGSize(width: ((3/2) * screenSize.width), height: 200))
    physicsWorld.contactDelegate = self

    cam = SKCameraNode()
    self.camera = cam
    addChild(cam!)

    camBottom.position.y = -screenSize.height/2 + camBottom.size.height/2
    camBottom.zPosition = -1
    addChild(camBottom)
    camBottom.addPhysicsBody(category: .bottom, collision: nil, contact: .obj, isDynamic: false, gravity: false, rotation: false)
    camBottom.physicsBody?.restitution = 0.0
    camBottom.physicsBody?.isResting = true
    camBottom.physicsBody?.friction = 1.0

    addChild(obj)
    block.position = CGPoint(x: -30, y: -obj.size.height/2)
    obj.addChild(block)

    obj.physicsBody = SKPhysicsBody(bodies: [SKPhysicsBody(rectangleOf: obj.size, center: obj.position), SKPhysicsBody(rectangleOf: block.size, center: block.position)])
    obj.physicsBody?.categoryBitMask = collisionType.obj.rawValue
    obj.physicsBody?.collisionBitMask = collisionType.bottom.rawValue
    obj.physicsBody?.contactTestBitMask = collisionType.bottom.rawValue
    obj.physicsBody?.affectedByGravity = true
    obj.physicsBody?.allowsRotation = true

    runAutomation()

    let wait = SKAction.wait(forDuration: 0.01)
    let act = SKAction.run {
        self.updateCam()
    }
    run(SKAction.repeatForever(SKAction.sequence([wait, act])))

.addPhysicsBody это расширение, определенное в новом Swift-файле, это:

extension SKSpriteNode {
func addPhysicsBody(category: collisionType, collision: collisionType?, contact: collisionType?, isDynamic: Bool, gravity: Bool, rotation: Bool) {
    self.physicsBody = SKPhysicsBody(rectangleOf: self.size)
    self.physicsBody?.categoryBitMask = category.rawValue
    if collision != nil {
        self.physicsBody?.collisionBitMask = (collision?.rawValue)!
    } else {
        self.physicsBody?.collisionBitMask = 0
    }
    if contact != nil {
        self.physicsBody?.contactTestBitMask = (contact?.rawValue)!
    } else {
        self.physicsBody?.contactTestBitMask = 0
    }
    self.physicsBody?.isDynamic = isDynamic
    self.physicsBody?.affectedByGravity = gravity
    self.physicsBody?.allowsRotation = rotation
}
}

Тогда функции, определенные в GameScene:

func updateCam() {
    let val: CGFloat = 15
    let xDist = (obj.position.x - (camera?.position.x)!)/val
    let yDist = (obj.position.y - (camera?.position.y)!)/val
    camera?.position.x += xDist
    camera?.position.y += yDist
}

func runAutomation() {
    let wait = SKAction.wait(forDuration: 5.0)
    let act = SKAction.run {
        print("Before", self.obj.physicsBody?.velocity)
        self.obj.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 30), at: self.block.position)
        print("After", self.obj.physicsBody?.velocity)
    }
    run(SKAction.repeatForever(SKAction.sequence([wait, act])))
}

override func update(_ currentTime: TimeInterval) {
    // Called before each frame is rendered
    camBottom.position.x = (camera?.position.x)!
}

Это очень странно, я не уверен, намеренно ли это. Тем не менее, как я могу сделать так, чтобы при каждом применении импульса коробка взлетала примерно на одно и то же расстояние? Какой правильный метод?

Спасибо

1 ответ

Похоже, что вы применяете импульс из позиции self.block.

self.obj.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 30), at: self.block.position)

В какой-то момент ваш объект не находится в том же положении, как раньше. Таким образом, он будет применять тот же импульс, но с другой позиции. Может ты хочешь self.obj.position вместо self.block.position или просто использовать

self.obj.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 30))

Чтобы позволить ему прыгать выше, вы установили для dy более высокое значение.

Другие вопросы по тегам