Skaction.Movebyx Not Setting Physicsbody.Velocity

SKAction.moveByX not setting physicsBody.velocity

Actions and physics are largely separate mechanisms in SpriteKit. Generally, if you're using physics to move a body, you shouldn't use move actions on it. If you want to move a body that's already using physics, use physics to move it -- apply a force or impulse, or set its velocity directly.

Conversely, when you use actions to move a body, or set its position directly, those changes don't go through the physics engine. If you want to find the speed of a node during a move action, you'll have to calculate it yourself by observing the change in its position between frames.

Swift: Set velocity for distance

I haven't worked with Sprite Kit before but I think your problem is that the linearDamping property of an SKPhysicsBody is set by default to 0.1, with a quick calculation (20*3-20*3*0.1 = 54) this sounds about right if the velocity if being damped every frame.

Here is the documentation for the property:

https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKPhysicsBody_Ref/index.html#//apple_ref/occ/instp/SKPhysicsBody/linearDamping

Edit: I thought I should check my answer at least so I wrote a quick (rough) program:

var dampingOccurancesPerSecond = 60.0 //Corresponds to frame rate
var numberOfSeconds = 3.0
var time = 0.0

@IBAction func test(sender: UIButton) {
let result = checkDistanceForVelocity(20, damping: 0.1, distanceTraveled: 0.0)
print(result)
}

func checkDistanceForVelocity(velocity: Double, damping: Double, distanceTraveled: Double) -> Double {

if time < numberOfSeconds {

time += 1/dampingOccurancesPerSecond

let newVelocity = velocity - (velocity * damping/dampingOccurancesPerSecond)

let newDistance = (distanceTraveled + velocity/dampingOccurancesPerSecond)

return checkDistanceForVelocity(newVelocity, damping: damping, distanceTraveled: newDistance)

}

return distanceTraveled

}

The small variations on your traveled distance is also likely due to small changes in your frame rate. When the dampingOccurancesPerSecond changes from 60 -> 50 the total distance traveled changes from 52.1203109538336 -> 51.8808576268828

Hope this helped!!

Can I move dynamic physics bodies using SKAction when only contact detection is needed?

  1. static means that the body isnt affected by physics. That doesnt mean it cant be manually repositioned or moved. So if something is set to static, it participates in the physics simulation, but it isnt affected by it. Think of a plane hitting a mountain. The plane is dynamic, the mountain is just going to sit there even though its participating in the physics. But you could still move that mountain around manually using a position or an action.

  2. Not totally understanding your question, but I'll give it a shot.

You can move physicsBody's manually (using position property or actions), but you need to ask yourself why you're doing that. You typically don't want to do it because they're bypassing the physics simulation. If you're forcing it to move around, what's the point of using a physics body in the first place.. right?

But if your physicsbody is something like a powerup that is totally static, and you just want it to move around in a circle using an action then thats fine. You probably just want to use contact detection for the bullet, powerup, etc without actually moving it around using physics. Nothing wrong with that.

Constant velocity while still being able to apply an impulse

The problem is that you're overwriting the velocity in the update method. So even though you added an impulse, it gets immediately overwritten by code in the update. Try overwriting just the dx part of the velocity.

override func update(currentTime: CFTimeInterval) {

updateSpritePosition()
mainSprite.physicsBody?.velocity = CGVectorMake(400, mainSprite.physicsBody?.velocity.dy)
}

Move SKSpriteNode until touches ended

i don't like to use SKActions for these types of things because they're really meant for one off simple animations.. However, it may be appropriate depending your game's requirements..

if you insist on using SKActions then instead of doing moveBy, why don't you just use moveTo utilizing touch location? The only thing you'd have to do is come up with a ratio based on the distance your sprite needs to travel so that your animation duration is correct. example:

let curPoint = self.sprite.position
let destinationPoint = touch.position

let diffPoint = CGPoint(
x: curPoint.x - destinationPoint.x,
y: curPoint.y - destinationPoint.y
)

let distance = sqrt(pow(diffPoint.x, 2) + pow(diffPoint.y, 2))

let durationRatio = distance / CGFloat(600)

let moveAction = SKAction.moveTo(point, duration: NSTimeInterval(durationRatio))

self.sprite.runAction(moveAction, withKey: "move")

then when you want to cancel the movement. in touchesEnded you do

self.sprite.removeActionForKey("move")

using physics velocity

let curPoint = CGPoint(x: 10, y: 10)
let destinationPoint = CGPoint(x: 100, y: 100)

let diffPoint = CGPoint(
x: curPoint.x - destinationPoint.x,
y: curPoint.y - destinationPoint.y
)

let distance = sqrt(pow(diffPoint.x, 2) + pow(diffPoint.y, 2))

let normalizedVector = CGPoint(
x: diffPoint.x / distance,
y: diffPoint.y / distance
)

let speed = CGFloat(100)

let velocity = CGVector(
dx: normalizedVector.x * speed,
dy: normalizedVector.y * speed
)

self.sprite.physicsBody!.velocity = velocity

in touchesEnded you do

self.sprite.physicsBody!.velocity = CGVector(dx: 0.0, dy: 0.0)

SpriteKit changing SKAction for one Node

Replace your if statement with the following code...

if (Faster) {
[self addActionToNode:Feind withDuration:4 andKey:@"faster"];
}
else {
[self addActionToNode:Feind withDuration:5 andKey:@"slower"];
}

This method adds an action (with a key) to a node. The key allows you to find the slower nodes so they can be updated when the game speeds up.

- (void) addActionToNode:(SKSpriteNode *)node withDuration:(NSTimeInterval)duration andKey:(NSString *)key
{
SKAction *move = [SKAction moveToX:-100 duration:duration];
SKAction *remove = [SKAction removeFromParent];
SKAction *action = [SKAction repeatActionForever:[SKAction sequence:@[move,remove]]];

[node runAction:action withKey:key];

if (!node.parent) {
[self addChild:node];
}
}

Call this to update the slower nodes when the game speeds up...

- (void) updateActions
{
for (SKSpriteNode *node in self.children) {
if ([node actionForKey:@"slower"]) {
[node removeAllActions];
[self addActionToNode:node withDuration:4 andKey:@"faster"];
}
}
}


Related Topics



Leave a reply



Submit