In this simple physics simulation there is a bit of odd behaviour. The applyImpulse is applied every 5 seconds, but each time this happens the box shoots up even higher, even though the same value is used for the applyImpulse. After about 20 seconds, the box is shooting up very high.
The box has a small red box attached to it, which is where the impulse is applied.
PHOTOS CAPTURED:
THIS IS THE CODE:
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))
Then in 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 is an extension defined in a new Swift file, it is this:
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
}
}
Then the functions defined in the 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)!
}
It is very odd, I'm not sure if it is intentional. Nevertheless, how can I make it so that each time the impulse is applied, the box flies up about the same distance? What is the correct method?
Thank you


It looks like you are applying the impulse from the self.block.position with
At some point your object is not on the same position like before. So it will apply the same impulse but from another position. Maybe you want
self.obj.positioninstead ofself.block.positionor just useTo let it jump higher you have set the dy to a higher value.