Sign in to follow this  
phil67rpg

rendering space ships

Recommended Posts

phil67rpg    443

I have drawn two space ships to the screen, they move up and down and left and right. I want them to move independently of each other. Right now they work in tandem. I am confused on how to use the pushmatrix and popmatrix commands. here is my main rendering code.

void
 
 
draw_ship()
{
glClear(
 
GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 
glColor3f(0.0f,1.0f,0.0f);
glBegin(
 
GL_LINE_LOOP);
glVertex3f(-1.5f,-0.25f,0.0f);
glVertex3f(-1.75f,-0.5f,0.0f);
glVertex3f(-2.0f,-0.5f,0.0f);
glVertex3f(-1.5f,0.5f,0.0f);
glVertex3f(-1.0f,-0.5f,0.0f);
glVertex3f(-1.25f,-0.5f,0.0f);
glVertex3f(-1.5f,-0.25f,0.0f);
glEnd();
glColor3f(1.0f,0.0f,0.0f);
glBegin(
 
GL_LINE_LOOP);
glVertex3f(1.5f,-0.25f,0.0f);
glVertex3f(1.25f,-0.5f,0.0f);
glVertex3f(1.0f,-0.5f,0.0f);
glVertex3f(1.5f,0.5f,0.0f);
glVertex3f(2.0f,-0.5f,0.0f);
glVertex3f(1.75f,-0.5f,0.0f);
glVertex3f(1.5f,-0.25f,0.0f);
glEnd();
glColor3f(1.0f,0.0f,0.0f);
glPointSize(2.0f);
glBegin(
 
GL_POINTS);
glVertex3f(1.5f,up_two++,0.0f);
glEnd();
glColor3f(0.0f,1.0f,0.0f);
glPointSize(2.0f);
glBegin(
 
GL_POINTS);
glVertex3f(-1.5f,up++,0.0f);
glEnd();
 
glutSwapBuffers();
}

they also shoot bullets.

 

Share this post


Link to post
Share on other sites
marcClintDion    435

glPushMatrix();

Translate(ship_01_Position[0], ship_01_Position[1], ship_01_Position[2]);

glColor3f(0.0f,1.0f,0.0f); glBegin(GL_LINE_LOOP); glVertex3f(-1.5f,-0.25f,0.0f); glVertex3f(-1.75f,-0.5f,0.0f); glVertex3f(-2.0f,-0.5f,0.0f); glVertex3f(-1.5f,0.5f,0.0f); glVertex3f(-1.0f,-0.5f,0.0f); glVertex3f(-1.25f,-0.5f,0.0f); glVertex3f(-1.5f,-0.25f,0.0f); glEnd();

glPopMatrix();

//----------------------------------------------------------------------------------

glPushMatrix();

Translate(ship_02_Position[0], ship_02_Position[1], ship_02_Position[2]);

glColor3f(1.0f,0.0f,0.0f); glBegin(GL_LINE_LOOP); glVertex3f(1.5f,-0.25f,0.0f); glVertex3f(1.25f,-0.5f,0.0f); glVertex3f(1.0f,-0.5f,0.0f); glVertex3f(1.5f,0.5f,0.0f); glVertex3f(2.0f,-0.5f,0.0f); glVertex3f(1.75f,-0.5f,0.0f); glVertex3f(1.5f,-0.25f,0.0f); glEnd();

glPopMatrix();

//----------------------------------------------------------------------------------

Share this post


Link to post
Share on other sites
marcClintDion    435

I don't see any code at all that would move the spaceships, there are movement variables for the bullets but nothing else unless I'm having a brain fart.  I presume that there is a translation call before the draw_ship() function. If you post the whole Render function it will make it easier for someone to walk you through it. The way you have that function set up with the calls to glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); and SwapBuffers, it makes it seem as if that IS the render function.  If this is the case, how are you getting any motion for the ships at all? You mentioned that you are having issues with PushMatrix and PopMatrix but they aren't even in the code you posted.

Share this post


Link to post
Share on other sites
phil67rpg    443

here is my movement code

void
 
 
ship_left_two()
{
glTranslatef(-1.5f,0.0f,0.0f);
glRotatef(angle,0.0f,0.0f,1.0f);
glTranslatef(1.5f,0.0f,0.0f);
}
void
 
 
ship_right_two()
{
glTranslatef(-1.5f,0.0f,0.0f);
glRotatef(-angle,0.0f,0.0f,1.0f);
glTranslatef(1.5f,0.0f,0.0f);
}
void
 
 
ship_up_two()
{
glTranslatef(0.0f,0.1f,0.0f);
}
void
 
 
ship_down_two()
{
glTranslatef(0.0f,-0.1f,0.0f);
}
void
 
 
ship_up()
{
glTranslatef(0.0f,0.1f,0.0f);
}
void
 
 
ship_down()
{
glTranslatef(0.0f,-0.1f,0.0f);
}
void
 
 
ship_left()
{
glTranslatef(1.5f,0.0f,0.0f);
glRotatef(angle,0.0f,0.0f,1.0f);
glTranslatef(-1.5f,0.0f,0.0f);
}
void
 
 
ship_right()
{
glTranslatef(1.5f,0.0f,0.0f);
glRotatef(-angle,0.0f,0.0f,1.0f);
glTranslatef(-1.5f,0.0f,0.0f);
}
void
 
 
bullet()
{
up+=0.1f;
 
 
if(up >= 10.0f)
{
up=0.5f;
}
}
void
 
 
bullet_two()
{
up_two+=0.1f;
 
 
if(up_two >= 10.0f)
{
up_two=0.5f;
}
}
void
 
 
update(int value)
{
angle+=0.1f;
 
 
if(angle > 360.0f)
{
angle-=360;
}
glutPostRedisplay();
glutTimerFunc(25,update,0);
}

Share this post


Link to post
Share on other sites
phil67rpg    443

well I have implemented the above code and it all works well except that when I rotate the ship it still moves up and down but does not move in the direction the ship is oriented.

in other words it does not follow its own nose. thanks for all the help. let me if you need additional code.

Share this post


Link to post
Share on other sites
marcClintDion    435

For the old 2D art games to implement this there would be sprites for all possible directions. For instance, if you move to the right, the current ship picture would be swapped with a picture of a ship facing right.  If the ship moved up, the character would be swapped with a picture of a ship facing up. 

You have some decisions to make now.  Since you are using a flat plane and pasting the image of a ship on to it, you are technically using the old 2D art style.  Unless your ship is mirrored along it's length, the same way a rocket is, then you are going to have some problems.  If you rotate around the z-axis then your ship will be upside down when you change between left and right, at least for one direction anyways.  If you rotate about the 'y'-axis to change from left to right, you will have to make sure back-face culling is off so it won't be invisible when it's backwards.  Also by this method, the ship will appear to shrink, then disappear, then grow back to it's original size if you have a transition between left and right. This would look the same as if you have a picture of a ship drawn on two sides of a piece of paper, then you hold it in front of your face and rotate it. 

This is more suited to 3D models but would work for a stylized 2D game as well, for instance, "Super Paper Mario"

 

To start off with, you might want to just come up with some hard-coded directions.  If the ship is naturally facing right at the start, then ship angle would be 0.0 when it is flying right.  Now to face left, assuming back-face culling is disabled, the ship angle angle would be 180 along the 'Y' axis.  glRotatef(180.0, 0.0, 1.0, 0.0); 

If you want a smooth transition between these two values you can use key-frame blending  http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter06.html

 

blendedPosition = (1.0 - weight) * keyFrameA + weight * keyFrameB;

 

In your case, it would look something like the following...

 

currentRotation = (1.0 - time) * rotationStart + time * rotationFinish

 

The first component grows smaller as time goes from 0.0 to 1.0 , The second component grows larger as time goes from 0.0 to 1.0

 

CurrentRotation will start off as 0.0, if it was facing right, then increment every frame all the way to 180.0, and it will be facing left.

This will become substantially more complex when characters are continuously changing direction part way through the interpolation, now you'd have to save currentRotation and use this as the new rotationStart, then restart 'time' at zero.

 

You should post how you would like to proceed.

Share this post


Link to post
Share on other sites
phil67rpg    443

here is my new rendering code

void draw_ship()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(0.0f,ship_1_y,0.0f);
glTranslatef(-1.5f,0.0f,0.0f);
glRotatef(ship_1_angle,0.0f,0.0f,1.0f);
glTranslatef(1.5f,0.0f,0.0f);
glColor3f(0.0f,1.0f,0.0f);
glBegin(GL_LINE_LOOP);
glVertex3f(-1.5f,-0.25f,0.0f);
glVertex3f(-1.75f,-0.5f,0.0f);
glVertex3f(-2.0f,-0.5f,0.0f);
glVertex3f(-1.5f,0.5f,0.0f);
glVertex3f(-1.0f,-0.5f,0.0f);
glVertex3f(-1.25f,-0.5f,0.0f);
glVertex3f(-1.5f,-0.25f,0.0f);
glEnd();
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f,ship_2_y,0.0f);
glTranslatef(1.5f,0.0f,0.0f);
glRotatef(ship_2_angle,0.0f,0.0f,1.0f);
glTranslatef(-1.5f,0.0f,0.0f);
glColor3f(1.0f,0.0f,0.0f);
glBegin(GL_LINE_LOOP);
glVertex3f(1.5f,-0.25f,0.0f);
glVertex3f(1.25f,-0.5f,0.0f);
glVertex3f(1.0f,-0.5f,0.0f);
glVertex3f(1.5f,0.5f,0.0f);
glVertex3f(2.0f,-0.5f,0.0f);
glVertex3f(1.75f,-0.5f,0.0f);
glVertex3f(1.5f,-0.25f,0.0f);
glEnd();
glPopMatrix();
glColor3f(1.0f,0.0f,0.0f);
glPointSize(2.0f);
glBegin(GL_POINTS);
glVertex3f(1.5f,up_two++,0.0f);
glEnd();
glPushMatrix();
glColor3f(0.0f,1.0f,0.0f);
glPointSize(2.0f);
glBegin(GL_POINTS);
glVertex3f(-1.5f,up++,0.0f);
glEnd();
glPopMatrix();
glutSwapBuffers();
}

here is my new movement code

void ship_left_two()
{
ship_1_angle+=2.5f;
}
void ship_right_two()
{
ship_1_angle-=2.5f;
}
void ship_up_two()
{
ship_1_y+=0.1f;
}
void ship_down_two()
{
ship_1_y-=0.1f;
}
void ship_up()
{
ship_2_y+=0.1f;
}
void ship_down()
{
ship_2_y-=0.1f;
}
void ship_left()
{
ship_2_angle+=2.5f;
}
void ship_right()
{
ship_2_angle-=2.5f;
}
void bullet()
{
up+=0.1f;
 
if(up >= 10.0f)
{
up=0.5f;
}
}
void bullet_two()
{
up_two+=0.1f;
 
if(up_two >= 10.0f)
{
up_two=0.5f;
}
}
glutPostRedisplay();
glutTimerFunc(25,update,0);
}

 

Share this post


Link to post
Share on other sites
marcClintDion    435

Well so far it's looking good, I like the ships.  I had to scale everything down with  glScalef(0.1, 0.1, 0.1); to get anything to display on screen.  That might just be a difference in our camera settings.

 

Tomorrow I'll go through your controls to see what's happening there.  

 

While you're waiting to hear back, you might want to get started on breaking the lines for the ships into  GL_LINES calls so you can make the ships explode into pieces.  When a collision occurs you can swap out the GL_LINE_LOOP calls for the GL_LINES call.  After that, glTranslate and glScale can be used on the line segments to simulate an explosion.  Each ship is made up of 6 line segments so you'll need 6 GL_LINES sets per ship, one for each edge.   I think for clarity, they should go into a function called DrawShipExplosion();  and the regular ship draw calls, as they are now,  put into a function called DrawShip();

 

I'll try and get back to you tomorrow.

 

 

//-------------------------------------------------------------------------------------------------------------------------------------------------

EDIT:   After that, glTranslate and glScale can be used on the line segments to simulate an explosion.

 

I meant to write:After that, glTranslate and glRotate can be used on the line segments to simulate an explosion.  Scaling works as well, I suppose.

Share this post


Link to post
Share on other sites
marcClintDion    435

Well, I think before you go much further, you should consider reorganizing the fundamentals of your draw functions.  Right now, both ships have offsets from the center of the screen hard-coded into the line_loop function calls.  I think you should make only one ship definition which is centered on the screen at (0.0, 0.0), X and Y.

 

Now both ships can be drawn with only one function which is being fed the individual ships configuration.  This will make all of the rest of the code come together much more smoothly.  For instance, right now, because the offsets are hard-coded into the ships, when you rotate them, they will behave like they are on a swing-arm. 

As they are now, you have to use an extra glTranslate call to center the rotation pivot back to the center of the ship.  This adds code and confuses things.  Things will get much worse than this when you add collision detection.

 

//=============================================================================

//Instead you can make a function something like this

 

void DrawShip(GLfloat position_X, GLfloat position_Y, GLfloat position_Z, GLfloat rotation, GLfloat color)

{

glPushMatrix();

  glTranslatef(position_X, position_Y, position_Z);   glRotatef(rotation, 0.0f, 0.0f,1.0f);   glColor3f(color,0.0f,0.0f); glBegin(GL_LINE_LOOP); glVertex3f(...); glVertex3f(...);

glVertex3f(...);

glVertex3f(...);

glVertex3f(...); glVertex3f(...);

  glEnd();

glPopMatrix();

}

 

//==========================================================================================================

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

//==========================================================================================================

 

Now each ship can be drawn as follows

//------------------------------------------------------

 

void Render(void)

{

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

  //============================================

 

 

  //---------------------------------------------------------------------------------------------------------------------------------------

    //draw ship_01  

  DrawShip(ship_01_POSITION_X, ship_01_POSITION_Y, ship_01_POSITION_Z, ship_01_ROTATION, ship_01_COLOR);

  //---------------------------------------------------------------------------------------------------------------------------------------

        //draw ship_02

  DrawShip(ship_02_POSITION_X, ship_02_POSITION_Y, ship_02_POSITION_Z, ship_02_ROTATION, ship_02_COLOR);

  //---------------------------------------------------------------------------------------------------------------------------------------

 

 

  //============

  glutSwapBuffers();

}

Share this post


Link to post
Share on other sites
phil67rpg    443


I think you should make only one ship definition which is centered on the screen at (0.0, 0.0), X and Y.

actually I want to ships to fight each other first and then enemy ships and asteroids.

Share this post


Link to post
Share on other sites
marcClintDion    435
//--------------------------------------------------------------------------------------------------------------------------------------- //draw ship_01 DrawShip(ship_01_POSITION_X, ship_01_POSITION_Y, ship_01_POSITION_Z, ship_01_ROTATION, ship_01_COLOR); //--------------------------------------------------------------------------------------------------------------------------------------- //draw ship_02 DrawShip(ship_02_POSITION_X, ship_02_POSITION_Y, ship_02_POSITION_Z, ship_02_ROTATION, ship_02_COLOR); //---------------------------------------------------------------------------------------------------------------------------------------

 

 

How this is written gives you two ships!  In fact, now you can make a 100 ships to fight each other and for those 100 ships there would only be 100 lines of code in the Render loop, at least for the draw calls anyways.  When you do it this way, it's as if the compiler is copying and pasting all the code for you and setting them all to the proper positions.   Doing things this way not only condenses your code and makes it easier to read but it helps to keep errors at bay since you have hundreds or even thousands of fewer lines of code to look at and deal with, and you won't be introducing errors and frustration by hand typing and adjusting them all.

 

Let's think about what the asteroids might look like, both with a function to draw them all and without a function to draw them all.  If we set up the asteroid draw, position, rotate, and scale calls in a function just like for the ships above

 

For 50 asteroids there would be, so far, 50 lines of code, there will be more code than that for logic and other stuff but that will be true either way.  For now let's say that we can draw 50 asteroids with 50 lines of code.

//-----------------------------------------------------------------------------------------------------------------

Now for 50 asteroids that each have been drawn manually, with about 15 lines of code required every time.  You would then have 15 * 50 = 750.  If you do it your way then there will be 750 lines of code vs. 50 lines of code!  There will be an extra 700 lines of code and you will have to define all the individual positions for each one, that would be horrible especially since it was work that did not even need to be done.  This would set most people back a month at least, and it would be a really tedious painful month

 

//====================================================================================================

 

 

 

void draw_ship() {

 

Maybe some of the confusion here is coming from your  render loop name, you've called your render loop: draw_ship.  You absolutely, positivity, without any doubt have to change this right now before anymore confusion here sets in because of this!   When I wrote that you should make a DrawShip function for drawing your ships you likely thought that I was talking about making that the render loop.  You see how the name choice for your render loop has already wreaked so much havoc on this conversation?

 

By calling your render loop "draw_ship" you are making it seem as if you are only using it to draw ships, yet it is drawing ships, and bullets, and asteroids, and whatever else.  You should call it just about anything else but draw_ship.  You can call it Render() or Draw_Scene() or Do_stuff() or Party_Time() or Go_Get_Em() ! 

Just please don't use draw_ship, this name that you've given your Render function is too specific to what only a small part of what the render loop will be doing. 

 

Imagine if you called your render loop, shoot_bullets(), It doesn't just shoot bullets, it does a whole bunch of other things as well.  It's just too confusing to do it that way. 

Ya see?

Share this post


Link to post
Share on other sites
phil67rpg    443

I have incorporated your code, but I cannot get the ships to rotate around their centers and to follow their noses when moving up and down. here is my code so far.

void
 
 
DrawShip(GLfloat position_X,GLfloat position_Y, GLfloat position_Z, GLfloat rotation,GLfloat color)
{
glPushMatrix();
glTranslatef(
 
position_X, position_Y, position_Z);
glRotatef(
 
rotation,0.0f,0.0f,1.0f);
glColor3f(
 
color,0.0f,0.0f);
glBegin(
 
GL_LINE_LOOP);
glVertex3f(-1.5f,-0.25f,0.0f);
glVertex3f(-1.75f,-0.5f,0.0f);
glVertex3f(-2.0f,-0.5f,0.0f);
glVertex3f(-1.5f,0.5f,0.0f);
glVertex3f(-1.0f,-0.5f,0.0f);
glVertex3f(-1.25f,-0.5f,0.0f);
glVertex3f(-1.5f,-0.25f,0.0f);
glEnd();
glPopMatrix();
}
void
 
 
Render(void)
{
glClear(
 
GL_COLOR_BUFFER_BIT);
DrawShip(ship_01_POSITION_X,ship_01_POSITION_Y,ship_01_POSITION_Z,ship_01_ROTATION,ship_01_COLOR);
DrawShip(ship_02_POSITION_X,ship_02_POSITION_Y,ship_02_POSITION_Z,ship_02_ROTATION,ship_02_COLOR);
glutSwapBuffers();
}

here is my movement code

void
 
 
ship_left_two()
{
ship_01_ROTATION+=2.5f;
}
void
 
 
ship_right_two()
{
ship_01_ROTATION-=2.5f;
}
void
 
 
ship_up_two()
{
ship_01_POSITION_Y+=0.1f;
}
void
 
 
ship_down_two()
{
ship_01_POSITION_Y-=0.1f;
}
void
 
 
ship_up()
{
ship_02_POSITION_Y+=0.1f;
}
void
 
 
ship_down()
{
ship_02_POSITION_Y-=0.1f;
}
void
 
 
ship_left()
{
ship_02_ROTATION+=2.5f;
}
void
 
 
ship_right()
{
ship_02_ROTATION-=2.5f;
}
 

 

 

Share this post


Link to post
Share on other sites
marcClintDion    435
It looks like the ships points are being defined off-center.   Once you've fixed this we can proceed to rotating them properly to face their trajectories
//=======================================================================================================
      glBegin(GL_LINE_LOOP);
          glVertex3f(-1.5f,-0.25f,0.0f);
          glVertex3f(-1.75f,-0.5f,0.0f);
          glVertex3f(-2.0f,-0.5f,0.0f);
          glVertex3f(-1.5f,0.5f,0.0f);
          glVertex3f(-1.0f,-0.5f,0.0f);
          glVertex3f(-1.25f,-0.5f,0.0f);
          glVertex3f(-1.5f,-0.25f,0.0f);
     glEnd();
//=======================================================================================================
The rest is looking good so far...
 
Edit: +1.5 to all the X values centers them on the Y-axis so they rotate properly.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this