PDA

View Full Version : Ship movement

Sogekihei
04-01-2005, 12:54 PM
I've posted this in the maths section too but I thought I might have more luck posting it here.

Basically, I'm working on a game in which the player flies a ship around over a landscape. I have x,y and z coords stored for the ship, aswell as x,y and z rotations which are carried out via glRotatef each frame.

My problem is that I can't get the ship to steer properly. I have the up arrow key decreasing the z-coord of the ship (making it move forwards) and "z" and "x" keys to rotate the ship ACW and CW respectively. In my draw loop for the ship, if I rotate then translate to the x,y and z coords, the ship is rotated around the main origin making it appear to move sideways when it gets further away from the origin. If I switch rotate and translate around, it draws the rotatated ship at it's coordinates, but the ship still moves on the universal axes (i.e. it carries on moving forwards relative to the origin and so appears to just rotate on the spot as it moves, the rotation having no effect on it's direction).

Here's a screen of it so far:

http://www.arkangel-software.co.uk/Assets/Images/Ship3.jpg

I'm really stuck with this so any help would be greatly appreciated =)

Thanks,
Steve

dorbie
04-01-2005, 02:24 PM
Here is something I did a few years ago, read the start of this, the concepts apply to your problem even if it's a scene graph oriented presentation.

http://www.sgi.com/products/software/performer/brew/aqua.html

zukko
04-01-2005, 02:43 PM
hi, imho you should use gluLookAt() instead of glRotatef and glTranslatef, theres a tutorial on how to make a good camera class at www.morrowland.com (http://www.morrowland.com)

Sogekihei
04-01-2005, 03:11 PM
Thanks for the help guys, still can't get it to work tho =( I've written a camera class already using the principles from that tutorial. I changed my model class so that it is transformed in the same way but it's still rotating around the world origin even with gllookat =(

this is my main loop:

- Set camera to be behind ship
- Orientate the camera using glLookAt
- pushmatrix, draw model, popmatrix, repeat
- take user input for next frame

in my model class i have the same functionality and data structures as the camera class, and the rotate/move functions are called in the main loop as above. I've been on all day with this and I really appreciate any help.

Thanks again

dorbie
04-01-2005, 04:08 PM
Nothing in your loop even mentions ship motion simulation.

You say you set up the camera behind the ship but how do you determine where the ship is?

glulookat is not the issue, the issue is ship dynamics and orientation, especially if the view is tethered outside the ship looking at it with a glulookat.

See my tutorial, and note the distinction between ship positional update, and positioning the camera relative to the ship.

04-01-2005, 08:22 PM
Assuming that the vertical axis is y and the ship is moving in the x-z plane, then what you need to do is to calculate the new heading based on your steering command. This will involve using sines and cosines. So if you rotated your ship by theta ccw, then the movement in the x and z will be given as

xstep=-sin(theta)*(longitudinal movement step of ship)
zstep=cos(theta)*(longitudinal movement step of ship)

You will need to store the position of the ship continuously and add the xstep, zstep to the current position everytime you go through your loop.

Sogekihei
04-02-2005, 01:25 AM
sorry, I was just trying to keep the loop simple. Like i said, the ship has the same data structures as the camera class (i.e. it has an up vector, a position and a direction/heading vector. so far, when the player presses the "up" arrown key the user input part of my loop calls the move function of the ship, which looks something like this..

// Moves the model forwards or backwards
void model::moveModel(float speed)
{
vector3D vVector = mDir - mPos; // Set up view vector

// Moves model (pos speed = forwards, neg speed = backwards)
mPos.x = mPos.x + vVector.x * speed;
mPos.z = mPos.z + vVector.z * speed;
mDir.x = mDir.x + vVector.x * speed;
mDir.z = mDir.z + vVector.z * speed;

}

mPos is the position of the ship and mDir is its direction. thanks again for the help guys.

zukko
04-02-2005, 04:48 AM

Sogekihei
04-02-2005, 12:20 PM
Yeah I read the tutorial, cheers, but I still can't seem to get it to work. Like i say, I already have a camera class which works on those principles. The model class works the same way too, but again no luck =(

Sogekihei
04-02-2005, 12:21 PM
Sorry, I should also mention that my camera class works fine. It does everythnig its supposed to. It's just the model movement/rotation which is the problem.

zukko
04-02-2005, 04:19 PM
mmm could you post an executable? so we could what is happening

redarrow
04-03-2005, 12:01 AM
Here's how I move in my game its a FPS with jetpack's so it should be similar to what you'd need for a ship:

As a note: I'm programming in C under Linux

G_PLAYER is a typedef struct containing the player's current X,Y,Z and some other info.
PLAYER->ANGLE is the vertical heading of the player.
PLAYER->ROTATION is the horizontal heading of the player.
The PLAYER_FLYING bitmask simply determines if the player is flying (i.e. Jetpack fired up)

RADDEG is just a #define (0.017453292) I figured out to get degrees instead of radians from sin & cos - Probably not the best way to do it.

My coding might not be all perfect but it works flawlessly - I'm able to control full 3D flight with this.
I have 3 other routines as well: travel backwards, strafe left or right they're not much differnt from this.

void lod_gplayer_travel_forwards(G_PLAYER *PLAYER, GLdouble distance)
{
GLdouble temp;

if ((PLAYER->DOING & PLAYER_FLYING) == PLAYER_FLYING) temp = (GLdouble)cos((double)(PLAYER->ANGLE * RADDEG));
else temp = 1;

PLAYER->X -= (distance * (temp * (GLdouble)sin( (double)(PLAYER->ROTATION * RADDEG))));
PLAYER->Z += (distance * (temp * (GLdouble)cos( (double)(PLAYER->ROTATION * RADDEG))));
if ((PLAYER->DOING & PLAYER_FLYING) == PLAYER_FLYING)
PLAYER->Y -= (distance * (GLdouble)sin((double)(PLAYER->ANGLE * RADDEG)));
}

Hope this helps

Sogekihei
04-03-2005, 03:01 AM
Thanks for the help redarrow, I'll give it a go. I think I might have tried it already but I'm probably doing something wrong. I've uploaded the executable as it is at the minute (in a very bad way I must warn you, the camera's even moving in the oppisite direction of the ship) along with the main source and the source for the ship and the camera.

Thanks again for all the help =)

Sogekihei
04-03-2005, 11:59 AM
Still can't get this thing to work =(

zukko
04-03-2005, 12:22 PM
Hi, you have to change some minus signs in your code, i couldnt check your code, but while using the exe, if you give the ship a 180 degrees turn then it will move correctly front and back

Sogekihei
04-03-2005, 01:13 PM
Thanks for the advice Zukko but I managed to fix that. The problem is still the rotation tho. the ship is moving around the world origin, not it's own local origin. This means that as it moves away from the world origin it apprears to strafe rather than rotate. What I really want it to do it to rotate on it's local origin and for it to move forwards relative to itself, not the world coordinates (i.e. to not move sideways etc. after rotation)

zukko
04-03-2005, 07:10 PM
i couldnt get to compile your code, im missing some includes, will check the code later

Sogekihei
04-04-2005, 12:52 AM
Yeah, I only uploaded the code with problems. There's a load of other files like enumerations, matrix class and other stuff which I thought was irrelevant. I can upload the whole lot if it'll help.

Sogekihei
04-04-2005, 01:20 AM
Righty, I've uploaded the whole project...