# How do I simulate vehicle movement in a non-gravity environment (e.g., space)?

As a series of small experiments, I've began to tinker with game development, specifically using SpriteKit and Swift. I'm looking to simulate a body moving through a non-gravity environment, specifically space.

My vehicle starts in the middle of the screen and begins to travel horizontal with a constant force vector of (100, 0). When the user touches a new location, I would like for the vehicle to alter course and head to the location of the touch. In addition, I would like to simulate the vehicle "turning" in space. You can imagine that the turn wouldn't be immediate but would resemble something like a car drifting around a corner. This is such an example. I've got a crude version of it working, but there are weird quirks that I'm beginning to wonder if I'm approaching this correctly.

This is what I have so far:

Vehicle construction:

ship = SKShapeNode(rectOfSize: CGSizeMake(40, 20))
ship.fillColor = UIColor.redColor()
ship.strokeColor = UIColor.clearColor()
ship.position = getMiddle()

ship.physicsBody = SKPhysicsBody(rectangleOfSize: ship.frame.size)
ship.physicsBody?.affectedByGravity = false
ship.physicsBody?.velocity = CGVectorMake(Constants.VELOCITY, 0)
ship.physicsBody?.applyForce(CGVectorMake(Constants.VELOCITY, 0))
ship.physicsBody?.dynamic = true



When the user touches, I simply record the touch location as touchLoc.

In update:

if needUpdate {
let shipLoc = ship.position

// Find deltas
let dx = shipLoc.x - touchLoc.x
let dy = shipLoc.y - touchLoc.y

// How much does the ship need to rotate?
let angle = atan2(dy, dx) + CGFloat(M_PI)
let rotate = SKAction.rotateToAngle(angle, duration: 0.1, shortestUnitArc: true)
ship.runAction(rotate)

/*
* The deltas are used to create the new velocity vector, if the delta values are too
* low, it could cause slow down in the ship velocity, so try to "normalize" the deltas
* into something more similar to the starting velocity so the ship maintains a good speed
*/
let len = sqrt(pow(dx, 2) + pow(dy, 2))
let normalFactor = Constants.VELOCITY / len
let ndx = dx * normalFactor
let ndy = dy * normalFactor

// Our enhanced vector
let toVector = CGVectorMake(-ndx, -ndy)

let curVelocity = ship.physicsBody!.velocity
var newX = curVelocity.dx
var newY = curVelocity.dy

/*
* This section is used to simulate the "drifting turn". Instead of turning sharply, add
* some fudge factor (TURN_DELAY = 1) to make the turn gradual
*/
if curVelocity.dx > toVector.dx {
newX -= Constants.TURN_DELAY
} else {
newX += Constants.TURN_DELAY
}

if curVelocity.dy > toVector.dy {
newY -= Constants.TURN_DELAY
} else {
newY += Constants.TURN_DELAY
}

// Set the new velocity vector
ship.physicsBody?.velocity = CGVectorMake(newX, newY)

/*
* Kind of convoluted, but this is to check to see if the ship is within a specified range of the
* touch location (UPDATE_PADDING = 3). If the ship is, stop trying to run this update function (at least
* until the next touch) because the ship will constantly try to target the touch location
*/
if (-UPDATE_PADDING ... UPDATE_PADDING ~= (shipLoc.x - touchLoc.x)) &&
(-UPDATE_PADDING ... UPDATE_PADDING ~= (shipLoc.y - touchLoc.y)) {
print("Stopping. Touched \(touchLoc.x), \(touchLoc.y). Ship: \(shipLoc.x), \(shipLoc.y)")
needUpdate = false
}
}


Here is a quick video demonstrating how it currently works. As you can see, as the touches happen closer to the vehicle weird things happen. This leads me to believe I'm going about this all wrong. Any advice, suggestions, or resources would be greatly appreciated. Thanks.

• Maybe it will be useful for you: I've made a small test of what it could be for a space ship here. It looks like this. And it was done for this answer. – Alexandre Vaillancourt Feb 21 '16 at 4:13
• That looks pretty good to me -- touch close to the spaceship, and it makes drastic manoeuvres. Sounds about right. – ashes999 Feb 21 '16 at 4:30