Colission Avoidance using c++ and opengl

Started by
8 comments, last by Brainx7 10 years, 4 months ago
Hello, so I have a code in which a object starts moving in a straight line as soon as the program is run. I also have it that wherever I click in the window a square is drawn. so I'm trying to have the first object avoid colliding with the square whenever I place one right in fron of it.

this is what I have so far please help


 #include <GL/glut.h>
#include<math.h>
GLsizei MOUSEx=0, MOUSEy=0;
GLfloat SIDE=50;
GLfloat translatex=0, translatey, rotatedegree;
GLfloat translatea, translateb;
void drawSquare()
{
    glColor3f( 0, 0, 1 );
    glBegin(GL_POLYGON);
        glVertex3f(MOUSEx, MOUSEy,0);
        glVertex3f(MOUSEx+SIDE, MOUSEy,0);
        glVertex3f(MOUSEx+SIDE, MOUSEy+SIDE,0);
        glVertex3f(MOUSEx, MOUSEy+SIDE,0);
    glEnd();
    glFlush();
}   


void Torus2D( float inner, float outer, unsigned int pts )
{
    glBegin( GL_QUAD_STRIP );
    for( unsigned int i = 0; i <= pts; ++i )
    {
        float angle = ( i / (float)pts ) * 3.14159 * 2.0f;
        glVertex2f( inner * cos( angle ), inner * sin( angle ) );
        glVertex2f( outer * cos( angle ), outer * sin( angle ) );
    }
    glEnd();
}
void display(void)
{   
    glClearColor (0.0,0.0,0.0,1.0);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    
     glColor3f( 3, 0, 0 );
    //glTranslatef(50,400,0);
     glTranslatef(translatex+200,translatey+400,0);
  glRotatef(rotatedegree-66, 0, 0, 1);

      Torus2D( 0, 30, 8 );
        glLoadIdentity();
        glTranslatef(translatea,translateb,0);
     drawSquare();
    glFlush();
    
}
void reshape(int w, int h)
{   
    glViewport(0,0,(GLsizei)w,(GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
     //gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
    glOrtho(0.0,1368,768,0,-1.0,1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void spindisplay(void)
{       
    glutPostRedisplay();
}

void setX(int x)
{
    MOUSEx=x;
}

void setY(int y)
{
    MOUSEy=y;
}
void mouse(int btn, int state, int x, int y)
{
    if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN)   
    {
        setX(x);
        setY(y);
        //drawSquare(MOUSEx,HEIGHT-MOUSEy);
        glutPostRedisplay();
    }
    if(btn==GLUT_RIGHT_BUTTON && state==GLUT_DOWN)   
    {
        exit(1);   // To Exit the Program
    }
}

void timer(int ignored) {
    translatex+=1.08;
    int x, y;


    if(translatex < MOUSEx && translatex > MOUSEx-265)

    {
    
    translatey += -1.08;
    
    
    }


    if(translatex > MOUSEx || translatex < MOUSEx-265)

    {
    
    translatey += 1.08;
    
    
    }
    






    

     glutPostRedisplay();
        glutTimerFunc(30,timer,0);
      


}

int main(int argc, char **argv)
{   glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowSize(1366,768);
    glutInitWindowPosition(0,0);
    
    glutCreateWindow("Moving squares");
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutIdleFunc(spindisplay);
     glEnable(GL_DEPTH_TEST);
     glutTimerFunc (40, timer,0);  
    glutMainLoop();
}
Advertisement

this is what I have so far please help

It doesn’t work that way.
You don’t get to post a big code dump without even explaining what actually happens (as apposed to what you want to happen, which you did post), and even if you did it is still poor form to post a code dump.

Explain what actually happens, then post the code relevant to only that part.

Just because I am super-nice I looked over the code and I found the “timer()” function that modifies the position of the whatever.

This is the only code relevant to your question, and there is not even a remote attempt at collision detection etc. there.

You didn’t even make the slightest attempt.

You decided you wanted to do something, put in no effort what-so-ever, and immediately asked for someone else do the whole thing for you, all while using poor question-asking form and a big code dump that isn’t even inside code tags.

I don’t need another phil67rpg-induced heart attack. No sir.

Perhaps you should ask again when you have actually made an attempt at solving the problem.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

this is what I have so far please help

It doesn’t work that way.
You don’t get to post a big code dump without even explaining what actually happens (as apposed to what you want to happen, which you did post), and even if you did it is still poor form to post a code dump.

Explain what actually happens, then post the code relevant to only that part.

Just because I am super-nice I looked over the code and I found the “timer()” function that modifies the position of the whatever.

This is the only code relevant to your question, and there is not even a remote attempt at collision detection etc. there.

You didn’t even make the slightest attempt.

You decided you wanted to do something, put in no effort what-so-ever, and immediately asked for someone else do the whole thing for you, all while using poor question-asking form and a big code dump that isn’t even inside code tags.

I don’t need another phil67rpg-induced heart attack. No sir.

Perhaps you should ask again when you have actually made an attempt at solving the problem.

L. Spiro

you have no Idea how hard i've been trying , so if you're not going to help please take all that garbage to yourself

Okay, I know it's already been said, but OpenGL is a 2D/3D rendering library, not a game engine, so it's not going to do collision detection for you. Also, you can't rely on someone else to walk you through everything, while expecting someone else to figure out complex problems for you.

Now that I have the obvious out of the way (before someone else can say it again), I'll give you a method of how I personally would approach this, but the implementation is totally up to you.

First of all, you may want to consider a few variables here:

- How close do I need to be for the object to begin avoiding?

- What direction do I want it to move to avoid me?

- Do I want the avoiding object to dodge me every time, or simply attempt to dodge me if possible?

After you have this thought out, you can begin. I'm going to assume you have an understanding of basic trigonometry. If you don't, then you're clearly getting a bit ahead of yourself.

Now, first you want to at the very least have some code to compute a bounding circle. Use the distance formula to check whether the user is currently within that "threat range". If it is, then ideally, you should take the velocity as well as the angle at which the object is being approached. You should be able to form the angles of direction/avoidance by calculating the angle that the user is approaching the object, and do the same using the velocity to adjust the angle. With the resulting angle of both, you move the object in that direction at a velocity that you decide, and you should have a desirable result, if not, a result worth tweaking.

I've never done this before, but I've done similar things. It's only hard if you aren't fluent in 2D math. Of course, no one can simply just write your implementation for you, you have to rely on your own strength if you're going to survive. Hope this helps.

Shogun.

you have no Idea how hard i've been trying

That’s because you didn’t attempt to explain what you have tried, what ideas you had, how you weighed their pros and cons, and finally ended up with nothing for a solution.

Before we can even have a discussion about code we need to have one about concepts and ideas.
You need to have an idea on how to proceed.
Then you can try to implement it.
Then if you have problems you can come back and ask about code and your implementation.


Either try to code something and then ask about that, or rephrase the question more along the lines of, “I had this idea for collision detection but I thought it was bad because of X, so I was wondering if there is a better way to do it.”


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid


Perhaps you should ask again when you have actually made an attempt at solving the problem.

L. Spiro

you have no Idea how hard i've been trying , so if you're not going to help please take all that garbage to yourself

you realize he's got like 7000 points and links to a game engine hes made in the signature right? now - maybe you don't care at all and that's fine - but I mean - you might want to consider the probability that maybe this person is correct and you are not - you gotta at least, at a bare minimum, use the code tags

Brainx7 I suggest you read this. http://www.red3d.com/cwr/steer/

L. Spiro


Ok you're right , I should have been more informaitve I apologize. I've been trying harder lately, and so what it does now, is that when you click very close to the moving octagon, like right in front of it, the octagon moves up until completely avoiding the square, and then it keeps moving in a straight line, but now I want that if i place the rectangle in front of the octagon but to the top of the octagon, the octagon moves down instead. All I've done is manipulate the timer function and all the ifs statements so I'll show you my code and see if you have any Idea of how I could do what I want it to do.


#include <GL/glut.h>
#include<math.h>
GLsizei MOUSEx=0, MOUSEy=0;
GLfloat SIDE=50;
GLfloat translatex=0, translatey, rotatedegree;
GLfloat translatea, translateb;
void drawSquare()
{
    glColor3f( 0, 0, 1 );
    glBegin(GL_POLYGON);
        glVertex3f(MOUSEx, MOUSEy,0);
        glVertex3f(MOUSEx+SIDE, MOUSEy,0);
        glVertex3f(MOUSEx+SIDE, MOUSEy+SIDE,0);
        glVertex3f(MOUSEx, MOUSEy+SIDE,0);
    glEnd();
    glFlush();
}   


void Torus2D( float inner, float outer, unsigned int pts )
{
    glBegin( GL_QUAD_STRIP );
    for( unsigned int i = 0; i <= pts; ++i )
    {
        float angle = ( i / (float)pts ) * 3.14159 * 2.0f;
        glVertex2f( inner * cos( angle ), inner * sin( angle ) );
        glVertex2f( outer * cos( angle ), outer * sin( angle ) );
    }
    glEnd();
}
void display(void)
{   
    glClearColor (0.0,0.0,0.0,1.0);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    
     glColor3f( 3, 0, 0 );
    //glTranslatef(50,400,0);
           glTranslatef(translatex+200,translatey+400,0);
  glRotatef(rotatedegree-68, 0, 0, 1);
 
      Torus2D( 0, 30, 8 );
        glLoadIdentity();
        glTranslatef(translatea,translateb,0);
     drawSquare();
    glFlush();
    
}
void reshape(int w, int h)
{   
    glViewport(0,0,(GLsizei)w,(GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
     //gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
    glOrtho(0.0,1368,768,0,-1.0,1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void spindisplay(void)
{       
    glutPostRedisplay();
}

void setX(int x)
{
    MOUSEx=x;
}

void setY(int y)
{
    MOUSEy=y;
}
void mouse(int btn, int state, int x, int y)
{
    if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN)   
    {
        setX(x);
        setY(y);
     //   drawSquare(MOUSEx,HEIGHT-MOUSEy);
        glutPostRedisplay();
    }
    if(btn==GLUT_RIGHT_BUTTON && state==GLUT_DOWN)   
    {
        exit(1);   // To Exit the Program
    }
}

void timer(int ignored) {
    //translatex+=1.08;
    int x, y;


    
        if ( MOUSEx-200 < translatex )
        
        {    translatex+=1.08;
        
        
        }

        else if ( MOUSEy-320 < translatey )
    
    {
        translatex+=1.08;
        
        
        }   
        else if (MOUSEy-430 > translatey)

    {    translatex+=1.08;
        
        }

        else if (MOUSEx-280 > translatex)

    {    
        translatex+=1.08;
    
        }
                
        

            else if (MOUSEx-180 > translatex)

    {    
        //translatex+=1.08;
        translatey += -1.08;
    
        }

        

     glutPostRedisplay();
        glutTimerFunc(30,timer,0);
      


}

int main(int argc, char **argv)
{   glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowSize(1366,768);
    glutInitWindowPosition(0,0);
    
    glutCreateWindow("Avoidance");
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutIdleFunc(spindisplay);
     glEnable(GL_DEPTH_TEST);
     glutTimerFunc (40, timer,0);  
    glutMainLoop();
}

Okay I did a rendition of your program - only because when I copy pasted your code and included the freeglut library it compiled and ran

You shouldn't be using globals and stuff the way you are - and you should definitely have some header files and definition files with structs/classes.. it will make your life so much easier..

I tried not to change too much - just added a couple structs and changed some of your functions around.. I commented everything as well as i could to explain what I am doing.. If you copy paste this code it should compile and run with a working collision implementation


#include <GL/glut.h>
#include <math.h>
#include <time.h>


// These structures can hold your square and polygon data
// more easily than just free variables
struct Square
{
	float width;
	float height;
	float posX;
	float posY;
};

struct MyPolygon
{
	unsigned int pts;
	float inner;
	float outer;

	float xSpeed;
	float ySpeed;
	float posX;
	float posY;
};

struct Screen
{
	unsigned int width;
	unsigned int height;
};

// These are the variables you had declared
GLsizei MOUSEx=0, MOUSEy=0;
GLfloat SIDE=50;
GLfloat translatex=0, translatey, rotatedegree;
GLfloat translatea, translateb;
float twoPI = 3.14159f * 2.0f;

// This is a simple clock type given with c++ std lib.. I used it cause you can use it without
// including anything else
clock_t timerOld;
clock_t timerNew;


// Since you are using globals all the time and I didnt want to change too much - these
// instances of the structs above are globals too
Square square;
MyPolygon poly;
Screen screen;


// Theis is your draw square function
// I put all the draw related operations here - it makes more sense this way
void DrawSquare()
{
	glLoadIdentity();
	glTranslatef(square.posX,square.posY,0); // Instead of keeping track of some wierd translation variables...
										     // its much easier to just change the square posX and posY variables
											 // and translate its indentity matrix using that
	glColor3f( 0, 0, 1 );
	glBegin(GL_POLYGON);

	glVertex3f(-square.width/2.0f, -square.height/2.0f, 0); // Now when you are drawing the square you basically just
	glVertex3f( square.width/2.0f, -square.height/2.0f, 0); // make it so the square's xPos and yPos are its center
	glVertex3f( square.width/2.0f,  square.height/2.0f, 0); // therefor the vertices on the left and right will be plus and minus half of the squares width from the center
	glVertex3f(-square.width/2.0f,  square.height/2.0f, 0); // and the vertices on the top and bottom will be plus and minus half of the squares height from the center

	glEnd();
}   


void DrawTorus2D()
{
    glLoadIdentity();  // Again moved all polygon drawing code in the draw Torus function (not sure why its called that)
    glColor3f( 1, 0, 0 );
	glTranslatef(poly.posX, poly.posY, 0); // Again we use the polygons posX and posY to translate the identity matrix - then we just change
	                                       // poly.posX and poly.posY to move the polygon
	glRotatef(rotatedegree-68, 0, 0, 1);
    glBegin( GL_QUAD_STRIP );
    for( unsigned int i = 0; i <= poly.pts; ++i )
    {
        float angle = ( i / float(poly.pts) * twoPI );
        glVertex2f( poly.inner * cos( angle ), poly.inner * sin( angle ) ); // left your drawing code the same except made inner, outer, and pts
        glVertex2f( poly.outer * cos( angle ), poly.outer * sin( angle ) ); // variables within the MyPolygon structure
    }
    glEnd();
}

void Update(float pTimeDelta)
{
	// Now here is where we update the positions of the square and polygon
	// The square we just set its position to the last mouse click position
	square.posX = float(MOUSEx);
	square.posY = float(MOUSEy);

	// And the polygon is a bit more interesting.. the polygon now has an xSpeed and ySpeed that determine how fast the
	// polygon will move in the x and y directions... The speed is relative to the projection matrix and viewport as far
	// as units per second go...
	// pTimeDelta is the time elapsed since the last frame - if you multiply the speed (units per second) by the elapsed time
	// which is in seconds.. you get units.. therefor by doing this multiplication - you are finding the amount of units
	// to move this frame to make the polygon move at xSpeed units per second and ySpeed units per second
	// You then add this movement amount to the current x and y positions
	poly.posX += pTimeDelta*poly.xSpeed;
	poly.posY += pTimeDelta*poly.ySpeed;
}

void CheckCollisions()
{
	// Here is where we check for collisions between the two objects and do something if a collision was detected
	float deltaX = abs(poly.posX - square.posX);  // find the absolute value of x distance between the square current x position and polygon's center
	float deltaY = abs(poly.posY - square.posY);  // same thing but for y distance
	float centerToCenterX = poly.outer + square.width/2.0f; // find the closest distance in the x direction the two shapes can be before there is a collision
	float centerToCenterY = poly.outer + square.height/2.0f; // same thing for the y direction

	if  (  deltaX <= centerToCenterX && deltaY <= centerToCenterY )  // if the x distance between the square and polygon is less than the minimum x distance and
	{																 // the y distance between the square and polygon is less than the minimum y distance then there is a collision
		if ( deltaX < deltaY )    // if the poly.posX is closer to the square center than the poly.posX, the collision was with the top or bottom of polygon
		{
			if (poly.posY > square.posY) // move the polygon so that it is outside the collision zone
				poly.posY = square.posY + centerToCenterY;
			else
				poly.posY = square.posY - centerToCenterY;

			poly.ySpeed *= -1; // change the y speed to the opposite direction
		}
		else if ( deltaX > deltaY )  // if the poly.posY is closer to the square center than the poly.posX, the collision was with the side of polygon
		{
			if (poly.posX > square.posX) // move polygon so that it is outside of collision zone
				poly.posX = square.posX + centerToCenterX;
			else
				poly.posX = square.posX - centerToCenterX;

			poly.xSpeed *= -1; // reverse the x speed
		}
		else
		{
			poly.xSpeed *= -1; // if the x and y distance are somehow equal, change both of their velocity directions
			poly.ySpeed *= -1;
		}
	}
	
	// This simple little check keeps the polygon inside the screen bounds
	if ( poly.posX + poly.outer >= screen.width || poly.posX - poly.outer < 0 )
		poly.xSpeed *= -1;
	if ( poly.posY + poly.outer >= screen.height || poly.posY - poly.outer < 0 )
		poly.ySpeed *= -1;
}

void Draw()
{
	// Here we call the necessary draw functions
    glClearColor (0.0,0.0,0.0,1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	DrawSquare();
	DrawTorus2D();
	glFlush();
}

// Here we check collisions, update positions, and then draw the stuff
void display(void)
{
	float timeDelta; // this could be a global if you want but no need

	timerNew = clock(); // get the current time
	timeDelta = float(timerNew)/CLOCKS_PER_SEC - float(timerOld)/CLOCKS_PER_SEC; // subtract the old time from the current time to get the elapsed time for this frame
	timerOld = timerNew; // set the old time to the time created this frame

	CheckCollisions();
	Update(timeDelta);
	Draw();

    glFlush();  
}

void reshape(int w, int h)
{   
    glViewport(0,0,(GLsizei)w,(GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	glOrtho(0.0,screen.width,screen.height,0,-1.0,1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void spindisplay(void)
{
	glutPostRedisplay();
}

void setX(int x)
{
	MOUSEx=x;
}

void setY(int y)
{
	MOUSEy=y;
}

void mouse(int btn, int state, int x, int y)
{
	if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN)   
	{
		setX(x);
		setY(y);
		glutPostRedisplay();
	}
    if(btn==GLUT_RIGHT_BUTTON && state==GLUT_DOWN)   
	{
        exit(1);   // To Exit the Program
	}
}

int main(int argc, char **argv)
{
	timerOld = clock(); // Initialize timerOld with the time

	// Set your square attributes as you want
	square.height = 50.0f;
	square.width = 50.0f;
	square.posX = 0.0f; // starting position of the square
	square.posY = 0.0f;

	// Set your polygon attributes as you want
	poly.inner = 0.0f;
	poly.outer = 40.0f;
	poly.xSpeed = 200.0f; // This is just a speed I chose randomly - set it to whatever you want
	poly.ySpeed = 200.0f; // you could even make it so pressing a button changes it
	poly.pts = 8; // your polygon vertex count
	poly.posX = 100.0f; // starting position of polygon - cant start at zero cause the collision detection function will send it up up and away then
	poly.posY = 100.0f; // its easy enough to fix that - but ill leave that to you

	screen.width = 1366; // useful to have this data available - as it was used for example in the screen collision and resize function
	screen.height = 768;

	glutInit(&argc,argv);

	// No need for the timer function - you should just use a time elapsed variable like I used
	// here - at least for right now
	glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
	glutInitWindowSize(screen.width,screen.height);
	glutInitWindowPosition(0,0);
	glutCreateWindow("Avoidance");
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutMouseFunc(mouse);
	glutIdleFunc(spindisplay);

	glEnable(GL_DEPTH_TEST); 
	glutMainLoop();
}

Notice I used the code tags here^^

Anyways - there are a lot of ways to improve this collision setup I have made - but hopefully this will set you in the right direction

Okay I did a rendition of your program - only because when I copy pasted your code and included the freeglut library it compiled and ran

You shouldn't be using globals and stuff the way you are - and you should definitely have some header files and definition files with structs/classes.. it will make your life so much easier..

I tried not to change too much - just added a couple structs and changed some of your functions around.. I commented everything as well as i could to explain what I am doing.. If you copy paste this code it should compile and run with a working collision implementation


#include <GL/glut.h>
#include <math.h>
#include <time.h>


// These structures can hold your square and polygon data
// more easily than just free variables
struct Square
{
	float width;
	float height;
	float posX;
	float posY;
};

struct MyPolygon
{
	unsigned int pts;
	float inner;
	float outer;

	float xSpeed;
	float ySpeed;
	float posX;
	float posY;
};

struct Screen
{
	unsigned int width;
	unsigned int height;
};

// These are the variables you had declared
GLsizei MOUSEx=0, MOUSEy=0;
GLfloat SIDE=50;
GLfloat translatex=0, translatey, rotatedegree;
GLfloat translatea, translateb;
float twoPI = 3.14159f * 2.0f;

// This is a simple clock type given with c++ std lib.. I used it cause you can use it without
// including anything else
clock_t timerOld;
clock_t timerNew;


// Since you are using globals all the time and I didnt want to change too much - these
// instances of the structs above are globals too
Square square;
MyPolygon poly;
Screen screen;


// Theis is your draw square function
// I put all the draw related operations here - it makes more sense this way
void DrawSquare()
{
	glLoadIdentity();
	glTranslatef(square.posX,square.posY,0); // Instead of keeping track of some wierd translation variables...
										     // its much easier to just change the square posX and posY variables
											 // and translate its indentity matrix using that
	glColor3f( 0, 0, 1 );
	glBegin(GL_POLYGON);

	glVertex3f(-square.width/2.0f, -square.height/2.0f, 0); // Now when you are drawing the square you basically just
	glVertex3f( square.width/2.0f, -square.height/2.0f, 0); // make it so the square's xPos and yPos are its center
	glVertex3f( square.width/2.0f,  square.height/2.0f, 0); // therefor the vertices on the left and right will be plus and minus half of the squares width from the center
	glVertex3f(-square.width/2.0f,  square.height/2.0f, 0); // and the vertices on the top and bottom will be plus and minus half of the squares height from the center

	glEnd();
}   


void DrawTorus2D()
{
    glLoadIdentity();  // Again moved all polygon drawing code in the draw Torus function (not sure why its called that)
    glColor3f( 1, 0, 0 );
	glTranslatef(poly.posX, poly.posY, 0); // Again we use the polygons posX and posY to translate the identity matrix - then we just change
	                                       // poly.posX and poly.posY to move the polygon
	glRotatef(rotatedegree-68, 0, 0, 1);
    glBegin( GL_QUAD_STRIP );
    for( unsigned int i = 0; i <= poly.pts; ++i )
    {
        float angle = ( i / float(poly.pts) * twoPI );
        glVertex2f( poly.inner * cos( angle ), poly.inner * sin( angle ) ); // left your drawing code the same except made inner, outer, and pts
        glVertex2f( poly.outer * cos( angle ), poly.outer * sin( angle ) ); // variables within the MyPolygon structure
    }
    glEnd();
}

void Update(float pTimeDelta)
{
	// Now here is where we update the positions of the square and polygon
	// The square we just set its position to the last mouse click position
	square.posX = float(MOUSEx);
	square.posY = float(MOUSEy);

	// And the polygon is a bit more interesting.. the polygon now has an xSpeed and ySpeed that determine how fast the
	// polygon will move in the x and y directions... The speed is relative to the projection matrix and viewport as far
	// as units per second go...
	// pTimeDelta is the time elapsed since the last frame - if you multiply the speed (units per second) by the elapsed time
	// which is in seconds.. you get units.. therefor by doing this multiplication - you are finding the amount of units
	// to move this frame to make the polygon move at xSpeed units per second and ySpeed units per second
	// You then add this movement amount to the current x and y positions
	poly.posX += pTimeDelta*poly.xSpeed;
	poly.posY += pTimeDelta*poly.ySpeed;
}

void CheckCollisions()
{
	// Here is where we check for collisions between the two objects and do something if a collision was detected
	float deltaX = abs(poly.posX - square.posX);  // find the absolute value of x distance between the square current x position and polygon's center
	float deltaY = abs(poly.posY - square.posY);  // same thing but for y distance
	float centerToCenterX = poly.outer + square.width/2.0f; // find the closest distance in the x direction the two shapes can be before there is a collision
	float centerToCenterY = poly.outer + square.height/2.0f; // same thing for the y direction

	if  (  deltaX <= centerToCenterX && deltaY <= centerToCenterY )  // if the x distance between the square and polygon is less than the minimum x distance and
	{																 // the y distance between the square and polygon is less than the minimum y distance then there is a collision
		if ( deltaX < deltaY )    // if the poly.posX is closer to the square center than the poly.posX, the collision was with the top or bottom of polygon
		{
			if (poly.posY > square.posY) // move the polygon so that it is outside the collision zone
				poly.posY = square.posY + centerToCenterY;
			else
				poly.posY = square.posY - centerToCenterY;

			poly.ySpeed *= -1; // change the y speed to the opposite direction
		}
		else if ( deltaX > deltaY )  // if the poly.posY is closer to the square center than the poly.posX, the collision was with the side of polygon
		{
			if (poly.posX > square.posX) // move polygon so that it is outside of collision zone
				poly.posX = square.posX + centerToCenterX;
			else
				poly.posX = square.posX - centerToCenterX;

			poly.xSpeed *= -1; // reverse the x speed
		}
		else
		{
			poly.xSpeed *= -1; // if the x and y distance are somehow equal, change both of their velocity directions
			poly.ySpeed *= -1;
		}
	}
	
	// This simple little check keeps the polygon inside the screen bounds
	if ( poly.posX + poly.outer >= screen.width || poly.posX - poly.outer < 0 )
		poly.xSpeed *= -1;
	if ( poly.posY + poly.outer >= screen.height || poly.posY - poly.outer < 0 )
		poly.ySpeed *= -1;
}

void Draw()
{
	// Here we call the necessary draw functions
    glClearColor (0.0,0.0,0.0,1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	DrawSquare();
	DrawTorus2D();
	glFlush();
}

// Here we check collisions, update positions, and then draw the stuff
void display(void)
{
	float timeDelta; // this could be a global if you want but no need

	timerNew = clock(); // get the current time
	timeDelta = float(timerNew)/CLOCKS_PER_SEC - float(timerOld)/CLOCKS_PER_SEC; // subtract the old time from the current time to get the elapsed time for this frame
	timerOld = timerNew; // set the old time to the time created this frame

	CheckCollisions();
	Update(timeDelta);
	Draw();

    glFlush();  
}

void reshape(int w, int h)
{   
    glViewport(0,0,(GLsizei)w,(GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	glOrtho(0.0,screen.width,screen.height,0,-1.0,1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void spindisplay(void)
{
	glutPostRedisplay();
}

void setX(int x)
{
	MOUSEx=x;
}

void setY(int y)
{
	MOUSEy=y;
}

void mouse(int btn, int state, int x, int y)
{
	if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN)   
	{
		setX(x);
		setY(y);
		glutPostRedisplay();
	}
    if(btn==GLUT_RIGHT_BUTTON && state==GLUT_DOWN)   
	{
        exit(1);   // To Exit the Program
	}
}

int main(int argc, char **argv)
{
	timerOld = clock(); // Initialize timerOld with the time

	// Set your square attributes as you want
	square.height = 50.0f;
	square.width = 50.0f;
	square.posX = 0.0f; // starting position of the square
	square.posY = 0.0f;

	// Set your polygon attributes as you want
	poly.inner = 0.0f;
	poly.outer = 40.0f;
	poly.xSpeed = 200.0f; // This is just a speed I chose randomly - set it to whatever you want
	poly.ySpeed = 200.0f; // you could even make it so pressing a button changes it
	poly.pts = 8; // your polygon vertex count
	poly.posX = 100.0f; // starting position of polygon - cant start at zero cause the collision detection function will send it up up and away then
	poly.posY = 100.0f; // its easy enough to fix that - but ill leave that to you

	screen.width = 1366; // useful to have this data available - as it was used for example in the screen collision and resize function
	screen.height = 768;

	glutInit(&argc,argv);

	// No need for the timer function - you should just use a time elapsed variable like I used
	// here - at least for right now
	glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
	glutInitWindowSize(screen.width,screen.height);
	glutInitWindowPosition(0,0);
	glutCreateWindow("Avoidance");
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutMouseFunc(mouse);
	glutIdleFunc(spindisplay);

	glEnable(GL_DEPTH_TEST); 
	glutMainLoop();
}

Notice I used the code tags here^^

Anyways - there are a lot of ways to improve this collision setup I have made - but hopefully this will set you in the right direction

This is great dude, thanks a lot

This topic is closed to new replies.

Advertisement