# 2D Spaceship Thruster Movement - Turning

I have a spacecraft (shown in the image) built out of ‘blocks’ / 3D planes. It is drawn within a 3D space, but I’m ignoring the Y axis for now and keeping things on a “2D” XZ axis.

The ship has a number of thruster blocks (represented in blue); each of which should fire depending on user input (does the user want to go forward? or turn left? etc).

Although the image doesn’t show it, each thruster is oriented in a logical direction; i.e the thrusters labelled A & E point left, B & F point right, thrusters G & H point down, thrusters C & D point up.

Thrusters are placed arbitrarily around the ship. There is no actual 'Thruster A' or 'Thruster B'; I'm just using the spacecraft in the above image as an example.

I already have the following which works for forward/backward thrust and strafing (in pseudo code):

foreach(thruster in ship.thrusters) {

// Forward thrust
if(keyPressed W) && thruster.direction == ShipLocalSOUTH) {

thruster.fire();
}

// Backward thrust
if(keyPressed S) && thruster.direction == ShipLocalNORTH) {

thruster.fire();
}

// Strafe Left
if(keyPressed Q) && thruster.direction == ShipLocalEAST) {

thruster.fire();
}

// Strafe right
if(keyPressed E) && thruster.direction == ShipLocalWEST) {

thruster.fire();
}

// Turn left
if(keyPressed A && ??) {

// ??
}

// Turn right
if(keyPressed D && ??) {

//??
}
}

class Thruster {

private thrusterPower = 10;

public void fire() {

}
}


My problem lies in determining which thrusters to fire to turn the ship.

I’ve done a lot of googling on this and have found quite a lot of info already. I.e:

Using Torque and Thrusters to Move and Rotate a Player-Designed Spaceship

However my maths/trig skills are - to be blunt - crap and so I’m hoping to get a somewhat simpler explanation or even some code to help me understand and solve this problem. I'm not aiming for superbly accurate physics, just something that is fun to play.

• You want to fire thrusters in pairs about the centre of mass. So to rotate clockwise A and F would fire. G and D together would also rotate clockwise – Richard Tingle Nov 24 '15 at 21:00
• Thanks, I should have been more clear; thrusters can be placed arbitrarily about the spacecraft and in any number, there isn't actually a specific 'Thruster A' or 'Thruster B'. So while I myself understand which thrusters would need to fire in any given arrangement, I need my code to understand that too :) – whoshotdk Nov 24 '15 at 21:06
• Ahhh, that makes sense! You can definately calculate what axis a thruster will cause rotation about. But with arbitrary trusters it will be very difficult to isolate rotation from translation. I think the axis is going to be the cross product of the thust vector and vector from the centre of mass to the thuster (the sign of the resulting vector determining which direction round the axis the rotation is). You could fire all thrusters whose rotation axes are close to the requested axes. Is this just for the graphics or will these engines have a real effect. – Richard Tingle Nov 24 '15 at 21:13
• Some of the tutorials I found on the net speak of using the cross product as you say. I've no idea how to implement that along with the 'IsKeyPressed(A)' check. This is for actually moving the GameObject, not just for graphics. Thanks for your help. – whoshotdk Nov 24 '15 at 21:29
• What you need to do, is scan your created ship for thrusters, and then initialize each thruster based on its position relative to the ship. You would assign them Properties that will determine what direction it will make your ship go (what button to assign the thruster to fire off to). – jgallant Nov 24 '15 at 21:42

If you know the center, you have to find out if the thruster is above or below and left or right of your center.

public class Thruster : MonoBehaviour {

public Transform center;
public ThrusterType type;

public bool IsBelowCenterAxis {
get {
return transform.localPosition.z<center.localPosition.z;
}
}

public bool IsLeftOfCenterAxis {
get {
return transform.localPosition.x<center.localPosition.x;
}
}

public bool IsAboveCenterAxis {
get {
return transform.localPosition.z>center.localPosition.z;
}
}

public bool IsRightOfCenterAxis {
get {
return transform.localPosition.x>center.localPosition.x;
}
}

public void fire() {

}

}


and then :

if(Input.GetKey(KeyCode.A) &&
((thruster.type == ThrusterType.LEFT && thruster.IsBelowCenterAxis) ||
(thruster.type == ThrusterType.RIGHT && thruster.IsAboveCenterAxis) ||
(thruster.type == ThrusterType.UP && thruster.IsLeftOfCenterAxis) ||
(thruster.type == ThrusterType.DOWN && thruster.IsRightOfCenterAxis))) {

thruster.fire();
}

if(Input.GetKey(KeyCode.D) &&
((thruster.type == ThrusterType.RIGHT && thruster.IsBelowCenterAxis) ||
(thruster.type == ThrusterType.LEFT && thruster.IsAboveCenterAxis) ||
(thruster.type == ThrusterType.DOWN && thruster.IsLeftOfCenterAxis) ||
(thruster.type == ThrusterType.UP && thruster.IsRightOfCenterAxis))) {

thruster.fire();
}


Now you just need to know the force with which to fire, but that's a different question.

• I haven't seen this technique before but it works very well! I'll be editing my answer with updated code soon. – whoshotdk Nov 24 '15 at 23:13
• Glad it works for you, I also added an edit, as there was a little error with the center axis checks, just replace !IsBelowCenterAxis with IsAboveCenterAxis. The reason is, if center x or z equals thruster x or z (depending on rotation direction) there is no force pushing. – ElDuderino Nov 25 '15 at 10:31