Asteroids Game movement Problem
I have just started learning c++,opengl,maths. I am trying to copy the Asteroids game as a practical application of everything im learning. So far i can draw the ship (simple wireframe) and rotate it. My problem is i cant get it to move in the direction it is facing. I know it has something to do with sin,cos or vectors. Can someone show me a little routine to do it. Here is my code so far. BTW please dont laugh. Ive only been learning for 3 weeks.
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glfw.h> //this is api wrapper similar to GLUT
#include <math.h>
struct {
float xpos;
float ypos;
float zrot;
float speed;
int lives;
} ship;
void DrawScene( void )
{
glClearColor(0.0f,0.0f,0.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D(0,640,0,480);
glColor3f(1.0f,1.0f,1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(ship.xpos,ship.ypos,0.0f);
glRotatef(ship.zrot,0.0f,0.0f,1.0f);
glBegin(GL_LINE_LOOP);
glVertex2f(0.0,8.0);
glVertex2f(8.0,-10.0);
glVertex2f(0.0,-4.0);
glVertex2f(-8.0,-10.0);
glEnd();
}
int main( void )
{
int running = GL_TRUE;
// Initialize GLF
glfwInit();
// Open an OpenGL window
if( !glfwOpenWindow( 640,480, 4,4,4,4,0,0,GLFW_FULLSCREEN ) )
{
glfwTerminate();
return 0;
}
ship.xpos=320.0f;
ship.ypos=240.0f;
ship.zrot=0.0f;
ship.speed=0.0f;
// Main loo
while( running )
{
DrawScene();
if (glfwGetKey ( GLFW_KEY_LEFT ))
{
ship.zrot+=1.0;
}
else if (glfwGetKey ( GLFW_KEY_RIGHT ))
{
ship.zrot-=1.0;
}
else if (glfwGetKey ( GLFW_KEY_UP))
{
ship.speed++;
if (ship.speed >5.0)
{
ship.speed=5.0;
}
ship.xpos+=sin(ship.zrot)*ship.speed; //this is wrong i know
ship.ypos+=cos(ship.zrot)*ship.speed;
}
else if (glfwGetKey ( GLFW_KEY_DOWN))
{
}
ship.speed--;
if (ship.speed <0.0)
{
ship.speed=0.0;
}
// Swap front and back rendering buffers
glfwSwapBuffers();
// Check if ESC key was pressed or window
// was closed
running = !glfwGetKey( GLFW_KEY_ESC ) && glfwGetWindowParam( GLFW_OPENED );
}
// Close window and terminate GLFW
glfwTerminate();
// Exit program
return 0;
}
From the looks of it, your rotation is stored in degrees (since you pass it to glRotatef). The sin and cos functions take an angle in radians, so you need to multiply the angle by pi/180 before passing it to sin or cos.
That should let you fly the ship in the direction it is pointing. What it won''t do is let the ship slide sideways like it should do in Asteroids. For that you need to replace the speed variable with a velocity vector. I don''t have any handy code for that, but any good book/website on maths or physics should have plenty of info on vectors and kinematics.
That should let you fly the ship in the direction it is pointing. What it won''t do is let the ship slide sideways like it should do in Asteroids. For that you need to replace the speed variable with a velocity vector. I don''t have any handy code for that, but any good book/website on maths or physics should have plenty of info on vectors and kinematics.
I haven''t read all of your code, and I haven''t ever tried this, but I think the following way could work :
1. translate your ship to the last known position at which the rotation-degree changed.
2. Rotate your ship the right amount of degrees.
3. Translate your ship again, the distance it should have travelled since the last rotation.
1. translate your ship to the last known position at which the rotation-degree changed.
2. Rotate your ship the right amount of degrees.
3. Translate your ship again, the distance it should have travelled since the last rotation.
Newbie programmers think programming is hard.Amature programmers think programming is easy.Professional programmers know programming is hard.
ok thx for replies, I can now move the ship in the direction it is pointing and it continues in that direction while I rotate it again. However when apply thrust again the change in direction is immediate and its using the maximum speed allowed which looks odd to say the least. Can u explain what u meant by velocity vectors. I know it needs to change direction in a more realistic way like the ship has inertia. Doesnt anyone know how to do this? Its one of the earliest games ever made. this is the code nowship.
This is part of code which is changed;
xpos=320.0f;
ship.ypos=240.0f;
ship.zrot=0.0f;
ship.speed=0.0f;
ship.xytrans=0.0f;
// Main loo
while( running )
{
DrawScene();
if (glfwGetKey ( GLFW_KEY_LEFT ))
{
ship.zrot+=1.0;
if (ship.zrot==0)
{
ship.zrot=360;
}
}
else if (glfwGetKey ( GLFW_KEY_RIGHT ))
{
ship.zrot-=1.0;
if (ship.zrot==360)
{
ship.zrot=0;
}
}
else if (glfwGetKey ( GLFW_KEY_UP))
{
ship.speed+=0.2;
ship.xytrans=ship.zrot;
if (ship.speed >2.0)
{
ship.speed=2.0;
}
}
else if (glfwGetKey ( GLFW_KEY_DOWN))
{
}
if (ship.xpos<0)
{
ship.xpos=639;
}
else if (ship.xpos>640)
{
ship.xpos=1;
}
if (ship.ypos<0)
{
ship.ypos=479;
}
else if (ship.ypos>479)
{
ship.ypos=1;
}
ship.xpos+=sin(-ship.xytrans*PI/180)*ship.speed;
ship.ypos+=cos(-ship.xytrans*PI/180)*ship.speed;
// Swap front and back rendering buffers
glfwSwapBuffers();
// Check if ESC key was pressed or window
// was closed
running = !glfwGetKey( GLFW_KEY_ESC ) && glfwGetWindowParam( GLFW_OPENED );
}
// Close window and terminate GLFW
glfwTerminate();
// Exit program
return 0;
}
This is part of code which is changed;
xpos=320.0f;
ship.ypos=240.0f;
ship.zrot=0.0f;
ship.speed=0.0f;
ship.xytrans=0.0f;
// Main loo
while( running )
{
DrawScene();
if (glfwGetKey ( GLFW_KEY_LEFT ))
{
ship.zrot+=1.0;
if (ship.zrot==0)
{
ship.zrot=360;
}
}
else if (glfwGetKey ( GLFW_KEY_RIGHT ))
{
ship.zrot-=1.0;
if (ship.zrot==360)
{
ship.zrot=0;
}
}
else if (glfwGetKey ( GLFW_KEY_UP))
{
ship.speed+=0.2;
ship.xytrans=ship.zrot;
if (ship.speed >2.0)
{
ship.speed=2.0;
}
}
else if (glfwGetKey ( GLFW_KEY_DOWN))
{
}
if (ship.xpos<0)
{
ship.xpos=639;
}
else if (ship.xpos>640)
{
ship.xpos=1;
}
if (ship.ypos<0)
{
ship.ypos=479;
}
else if (ship.ypos>479)
{
ship.ypos=1;
}
ship.xpos+=sin(-ship.xytrans*PI/180)*ship.speed;
ship.ypos+=cos(-ship.xytrans*PI/180)*ship.speed;
// Swap front and back rendering buffers
glfwSwapBuffers();
// Check if ESC key was pressed or window
// was closed
running = !glfwGetKey( GLFW_KEY_ESC ) && glfwGetWindowParam( GLFW_OPENED );
}
// Close window and terminate GLFW
glfwTerminate();
// Exit program
return 0;
}
I don''t know if you''ve studied kinematics and the equations of uniform acceleration (S,U,V,A,T) before. If you haven''t, a quick search on google turned up The Physics Classroom which gives the equations. There are also links down the side of the page to information about vectors, acceleration etc. Look up "Vector math" in google if you need more info on that. I could try and explain it myself, but I''m sure the sites out there already make a much better job of it than I ever could.
Once you know all about vectors, its time to put them into your game. First you need some way to store a vector. For asteroids, all you need is a pair of floats (maybe in a struct) - one for the x component and one for the y. The ship has a thruster at the back, which accelerates the ship forwards. The direction of the acceleration changes as the ship turns, but for you can just use a fixed magnitude for now.
When the player presses forwards, you work out the acceleration vector. You know its size and the direction it acts in, so you can use sin and cos to get the x and y components. If the player isn''t pressing forwards, the x and y components of the acceleration are both 0.
Since you are using frames as your time unit, the "time" is just 1. Using the current velocity of the ship, the acceleration and the time passed you can work out the new velocity of the ship. Basically you do this:
each frame. Now you have the current velocity of the ship, you use that to work out where it is now:
And that gives you the new position. When you aren''t pressing forward, there is no acceleration, the velocity is unchanged and the ship keeps moving at the same rate, and in the same direction. Pressing forward changes the velocity by a fixed amount each frame, changing the way the object moves.
Once you know all about vectors, its time to put them into your game. First you need some way to store a vector. For asteroids, all you need is a pair of floats (maybe in a struct) - one for the x component and one for the y. The ship has a thruster at the back, which accelerates the ship forwards. The direction of the acceleration changes as the ship turns, but for you can just use a fixed magnitude for now.
When the player presses forwards, you work out the acceleration vector. You know its size and the direction it acts in, so you can use sin and cos to get the x and y components. If the player isn''t pressing forwards, the x and y components of the acceleration are both 0.
Since you are using frames as your time unit, the "time" is just 1. Using the current velocity of the ship, the acceleration and the time passed you can work out the new velocity of the ship. Basically you do this:
v = u + a * tnewvel.x = oldvel.x + acc.x * 1; // Similarly for y
each frame. Now you have the current velocity of the ship, you use that to work out where it is now:
newpos.x = oldpos.x + newvel.x * 1; // Similarly for y
And that gives you the new position. When you aren''t pressing forward, there is no acceleration, the velocity is unchanged and the ship keeps moving at the same rate, and in the same direction. Pressing forward changes the velocity by a fixed amount each frame, changing the way the object moves.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement