11
votes

Let's say I have a SKSpriteNode that represents a car wheel, with a circular SKPhysicsBody successfully attached to it. The genre would be sideways scrolling 2d car driving game/simulator, obviously.

What I want is to calculate all the in-motor physics myself without resorting to the SpriteKit physics engine quite yet. I'd like to keep full control on how the mechanics of the motor, clutch, transmission etc. are calculated, all the way to the RPM of the drive wheel.

From that point onwards, though, I'd happily give control to the SpriteKit physics engine, that would then calculate what happens, when the revolving drive wheel touces the surface of the road. The car advances, slows down, accelerates and/or the wheels slip, whatever the case might be.

Calculating the mechanics to get the wheel RPM is no problem. I'm just not sure on how to go on from there.

I'm able to rotate the wheel simply by applying zRotation in the update: method, like this:

self.rearWheelInstance.zRotation += (self.theCar.wheelRPS/6.283 * timeSinceLastUpdate); // revolutions / 2pi = radians

This way I'm able to apply the exact RPM I've calculated earlier. The obvious downside is, SpriteKit's physics engine is totally oblivious about this rotation. For all that it knows, the wheel teleports from one phase to the next, so it doesn't create friction with the road surface or any other interaction with other SpriteKit physicsBodies, for that matter.

On the other hand, I can apply torque to the wheel:

[self.rearWheelInstance.physicsBody applyTorque: someTorque];

or angular impulse:

[self.rearWheelInstance.physicsBody applyAngularImpulse: someAngularImpulse];

This does revolve the wheel in a fashion that SpriteKit physics engine understands, thus making it interact with its surroundings correctly.

But unless I'm missing something obvious, this considers the wheel as a 'free rolling object' independent of crankshaft, transmission or drive axel RPM. In reality, though, the wheel doesn't have the 'choice' to roll at any other RPM than what is transmitted through the drivetrain to the axel (unless the transmission is on neutral, the clutch pedal is down or the clutch is slipping, but those are whole another stories).

So: 1) Am I able to somehow manipulate zRotation in a way that the SpriteKit physics engine 'understands' as revolving movement?

or

2) Do I have a clear flaw in my logic that indicates that this isn't what I'm supposed to be trying in the first place? If so, could you be so kind as to point me to the flaw(s) so that I could adopt a better practice instead?

2

2 Answers

9
votes

Simple answer, mixing 2d UI settings, like position and zRotation, with a dynamic physics system isn't going to have the results you want, as you noticed. As you state, you'll need to use the pieces of the physics simulation, like impulse and angular momentum.

The two pieces of the puzzle that may also help you are:

Physics Joints - these can do things like connect a wheel to an axel so that it can freely rotate, set limits on rotation, but still impart rotational forces on it.

Dynamically Adjusting Physics Properties - like increasing friction, angular dampening or adding negative acceleration to the axel as the user presses the brakes.

4
votes

After quite a few dead ends I noticed there is in fact a way to directly manipulate the rotation of the wheel (as opposed to applying torque or impact) in a way that affects the physics engine accordingly.

The trick is to manipulate the angularVelocity property of the physicsBody of the wheel, like so:

self.rearWheelInstance.physicsBody.angularVelocity = -self.theCar.wheelRadPS; 
// Wheel's angular velocity, radians per second 
// *-1 just to flip ccw rotation to cw rotation 

This way I'm in direct control of the drive wheels' revolving speed without losing their ability to interact with other bodies in the SpriteKit physics simulation. This helped me over this particular obstacle, I hope it helps someone else, too.