PDA

View Full Version : Help with collision



BennyR
01-04-2014, 02:06 PM
The idea of the game is to have ball move and hit a target on a wall. I have no idea how to do the collision with the wall and the ball.

Here is the code:

//Windows - uncomment the includes below

#include "shared/gltools.h" //OpenGL toolkit - in the local shared folder
#include <math.h> //These were included in glm.cpp so I kept them here
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "shared/glm.h"
#include <iostream> //Needed for console output (debugging)


//
// texture.cpp
//
//
//Windows uncomment the includes below


//Mac includes + frameworks OpenGL and GLUT - comment out for Windows
//#include <iostream>
//#include <stdio.h>
//#include <OpenGL/glu.h>
//#include <GLUT/glut.h>
//#include "gltools.h"
//#include <OpenGL/gl.h>
//#include <OpenGL/glext.h>
//#include <OpenGL/gl3ext.h>

//note that this needs gltools.h and gltools.cpp to be included in the shared directory

//can define any number of textures here - we just have 2 images
//these are just integers so you can use them as such
#define IMAGE1 0
#define IMAGE2 1
#define IMAGE3 2
#define IMAGE4 3


bool ballGoingUp = false;
bool ballGoingDown;
bool ballGoingLeft;
bool ballGoingRight;
bool boolMoving = false;

float ballUDMovement = 0.0;
float ballLRMovement = 0.0;
float length = 1.0;
float rotationTimer = 0;
float scoreNumber;

float ballMoving1;
float ballMoving2;

int frame=0,time2 = 0,timebase=0;
char frameRate [6];

#define TEXTURE_COUNT 4
GLuint textures[TEXTURE_COUNT];
char score [6];

//below is simply a character array to hold the file names
//note that you may need to replace the below with the full directory root depending on where you put your image files
//if you put them where the exe is then you just need the name as below
const char *textureFiles[TEXTURE_COUNT] = {"padhamsBG.tga", "brick_texture.tga","grass_diff.tga","FootballCompleteMap.tga"};


//for lighting if you want to experiment with these

GLfloat mKa[4] = {0.11f,0.06f,0.11f,1.0f}; //ambient
GLfloat mKd[4] = {0.43f,0.47f,0.54f,1.0f}; //diffuse
GLfloat mKs[4] = {1.0f,1.0f,1.0f,1.0f}; //specular
GLfloat mKe[4] = {0.5f,0.5f,0.0f,1.0f}; //emission




// Useful lighting colour values
GLfloat greenLight[] = { 0.0f, 0.6f, 0.0f, 1.0f };
GLfloat redLight[] = { 0.6f, 0.0f, 0.0f, 1.0f };
GLfloat blueLight[] = { 0.0f, 0.0f, 0.6f, 1.0f };
GLfloat whiteLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat noLight[] = { 0.1f, 0.1f, 0.1f, 1.0f };//well, very little light intensity
GLfloat lightPos[] = { 100.0f, 100.0f, 50.0f, 1.0f };
GLfloat lightPos1[] = { ballLRMovement, ballUDMovement, 0.0f, 0.0f };


//we need these for the texture loader
//they are to do with the image format and size
GLint iWidth, iHeight, iComponents;
GLenum eFormat;
// this is a pointer to memory where the image bytes will be held
GLbyte *pBytes0;

//end of intialisation

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

void renderBitmapString(
float x,
float y,
float z,
void *font,
char *string) {
char *c;
glRasterPos3f(x, y,z);
for (c=string; *c != '\0'; c++) {
glutBitmapCharacter(font, *c);
}
}


void SpecialKeys(int key, int x, int y)
{

if(key == GLUT_KEY_UP){

ballUDMovement = ballUDMovement + length;

}

if(key == GLUT_KEY_DOWN){


ballUDMovement = ballUDMovement - length;
}

if(key == GLUT_KEY_LEFT){


ballLRMovement = ballLRMovement - length;
ballMoving2 = ballLRMovement;
}

if(key == GLUT_KEY_RIGHT){


ballLRMovement = ballLRMovement + length;
ballMoving2 = ballLRMovement;
}

if(key == GLUT_KEY_F1){

ballGoingUp = true;
ballMoving1 += ballUDMovement/5;

}
}

void drawTexturedQuad(int image)
{
//add some lighting normals for each vertex
//draw the texture on the front
glEnable(GL_TEXTURE_2D);
glFrontFace(GL_CW); //use glFrontFace(GL_CW) to texture the other side - not needed here as we set this elsewhere
glColor3f(0.8, 0.8, 0.8);
glEnable( GL_TEXTURE_2D );
//bind the texture
glBindTexture(GL_TEXTURE_2D, textures[image]);
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0,0.0);
glVertex3f(-50.0, 0.0,100.0);
glTexCoord3f(1.0,0.0,0.0);
glVertex3f(50.0, 0.0,100.0);
glTexCoord2f(1.0,1.0);
glVertex3f(50.0, 100.0,100.0);
glTexCoord2f(0.0,1.0);
glVertex3f(-50.0, 100.0,100.0);
glEnd();
glDisable( GL_TEXTURE_2D );

}


void drawGrass(int image)
{
//add some lighting normals for each vertex
//draw the texture on the front
glEnable(GL_TEXTURE_2D);
glFrontFace(GL_CW); //use glFrontFace(GL_CW) to texture the other side - not needed here as we set this elsewhere
glColor3f(0.8, 0.8, 0.8);
glEnable( GL_TEXTURE_2D );
//bind the texture
glBindTexture(GL_TEXTURE_2D, textures[image]);
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0,0.0);
glVertex3f(-800.0, 0.0,100.0);
glTexCoord3f(1.0,0.0,0.0);
glVertex3f(800.0, 0.0,100.0);
glTexCoord2f(1.0,1.0);
glVertex3f(800.0, 300.0,100.0);
glTexCoord2f(0.0,1.0);
glVertex3f(-800.0, 300.0,100.0);
glEnd();
glDisable( GL_TEXTURE_2D );

}

void drawMiddleWall(int image)
{
//add some lighting normals for each vertex
//draw the texture on the front
glEnable(GL_TEXTURE_2D);
glFrontFace(GL_CW); //use glFrontFace(GL_CW) to texture the other side - not needed here as we set this elsewhere
glColor3f(0.8, 0.8, 0.8);
glEnable( GL_TEXTURE_2D );
//bind the texture
glBindTexture(GL_TEXTURE_2D, textures[image]);
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0,0.0);
glVertex3f(-100.0, 0.0,100.0);
glTexCoord3f(1.0,0.0,0.0);
glVertex3f(100.0, 0.0,100.0);
glTexCoord2f(1.0,1.0);
glVertex3f(100.0, 100.0,100.0);
glTexCoord2f(0.0,1.0);
glVertex3f(-100.0, 100.0,100.0);
glEnd();
glDisable( GL_TEXTURE_2D );

}

void drawSideWall(int image)
{
//add some lighting normals for each vertex
//draw the texture on the front
glEnable(GL_TEXTURE_2D);
glFrontFace(GL_CW); //use glFrontFace(GL_CW) to texture the other side - not needed here as we set this elsewhere
glColor3f(0.8, 0.8, 0.8);
glEnable( GL_TEXTURE_2D );
//bind the texture
glBindTexture(GL_TEXTURE_2D, textures[image]);
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0,0.0);
glVertex3f(-100.0, 0.0,100.0);
glTexCoord3f(1.0,0.0,0.0);
glVertex3f(100.0, 0.0,100.0);
glTexCoord2f(1.0,1.0);
glVertex3f(100.0, 100.0,100.0);
glTexCoord2f(0.0,1.0);
glVertex3f(-100.0, 100.0,100.0);
glEnd();
glDisable( GL_TEXTURE_2D );

}

void drawSky(int image)
{
//add some lighting normals for each vertex
//draw the texture on the front
glEnable(GL_TEXTURE_2D);
glFrontFace(GL_CW); //use glFrontFace(GL_CW) to texture the other side - not needed here as we set this elsewhere
glColor3f(0.8, 0.8, 0.8);
glEnable( GL_TEXTURE_2D );
//bind the texture
glBindTexture(GL_TEXTURE_2D, textures[image]);
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0,0.0);
glVertex3f(-300.0, 0.0,100.0);
glTexCoord3f(1.0,0.0,0.0);
glVertex3f(300.0, 0.0,100.0);
glTexCoord2f(1.0,1.0);
glVertex3f(300.0, 110.0,100.0);
glTexCoord2f(0.0,1.0);
glVertex3f(-300.0, 110.0,99.0);
glEnd();
glDisable( GL_TEXTURE_2D );

}

void disk( float x, float y, float r)
{
glBegin( GL_TRIANGLE_FAN );
glVertex2f( x, y );
for( float i = 0; i <= 2 * 3.14 + 0.1; i += 0.1 )
{
glVertex2f( x + sin( i ) * r, y + cos( i ) * r );
}
glEnd();
}

void drawBall()
{
GLUquadricObj *qObj = gluNewQuadric();

gluQuadricNormals(qObj, GLU_SMOOTH);

gluQuadricTexture(qObj, GL_TRUE);

glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, 5);

glPushMatrix();
glTranslatef(0.0, -101, 100.0);
gluSphere(qObj, 20.0f, 24, 24);
glPopMatrix();

}

void direction1()
{
glBegin(GL_QUADS);
glColor3f(1.0,0.0,0.0);
glVertex2f(ballLRMovement,-70);
glVertex2f(ballLRMovement,-60);
glVertex2f(-5,-60);
glVertex2f(-5,-70);
glEnd();
}

void direction2()
{

glBegin(GL_QUADS);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(10,0);
glVertex2f(10,ballUDMovement);
glVertex2f(20,ballUDMovement);
glVertex2f(20,0);
glEnd();

}


// Called to draw scene


void RenderScene(void)
{


// Clear the window with current clearing colour
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);



glMatrixMode(GL_MODELVIEW);

// a test point
//use for locating points in your view
/* glEnable(GL_POINT_SMOOTH);
glPointSize(10.0);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POINTS);
glVertex3f(0.0f, 0.0f, 100.0f);
glEnd();
*/

sprintf(score, "5");
glColor3f(1.0, 0.0, 0.0);
renderBitmapString(-6,30,101,GLUT_BITMAP_HELVETICA_18,score);

sprintf(score, "10");
glColor3f(1.0, 0.0, 0.0);
renderBitmapString(-45,-12,101,GLUT_BITMAP_HELVETICA_18,score);

sprintf(score, "4");
glColor3f(1.0, 0.0, 0.0);
renderBitmapString(45,5,101,GLUT_BITMAP_HELVETICA_ 18,score);

sprintf(score,"Score: ");
glColor3f(1.0, 1.0, 1.0);
renderBitmapString(-160,130,101,GLUT_BITMAP_TIMES_ROMAN_24,score);


frame++;
time2=glutGet(GLUT_ELAPSED_TIME);
if (time2 - timebase > 1000) {

sprintf(frameRate,"FPS: %4.2f",
frame*1000.0/(time2-timebase));

timebase = time2;
frame = 0;
}
renderBitmapString(30,130,101,GLUT_BITMAP_TIMES_RO MAN_24,frameRate);


glPushMatrix();
glTranslatef(ballMoving2,0,0);
if (ballGoingUp = true)
{
glTranslatef(0,ballMoving1,-ballMoving1);
}
drawBall();
glPopMatrix();


glPushMatrix();
glTranslatef(0,-250,0);
glRotatef(-50,1,0,0);
drawGrass(IMAGE3);
glPopMatrix();

glPushMatrix();
glTranslatef(0,-20,-80);
drawMiddleWall(IMAGE2);
glPopMatrix();

glPushMatrix();
glTranslatef(200,-20,100);
glRotatef(-70,0.0,1.0,0.0);
drawSideWall(IMAGE2);
glPopMatrix();

glPushMatrix();
glTranslatef(-200,-20,100);
glRotatef(70,0.0,1.0,0.0);
drawSideWall(IMAGE2);
glPopMatrix();

glPushMatrix();
glTranslatef(-20,80,-100);
drawSky(IMAGE1);
glPopMatrix();

glPushMatrix();
glTranslatef(-20,20,25);
disk(15,15,15);
glPopMatrix();

glPushMatrix();
glTranslatef(-60,-18,25);
disk(10,10,10);
glPopMatrix();

glPushMatrix();
glTranslatef(35,-10,25);
disk(20,20,20);
glPopMatrix();

glPushMatrix();
glTranslatef(-80,-40,100);
direction1();
glPopMatrix();

glPushMatrix();
glTranslatef(70,-100,100);
direction2();
glPopMatrix();

}


// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
//textures

GLuint texture;
// allocate a texture name
glGenTextures( 1, &texture );
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
//make sure any TGA has no alpha channel - photoshop is a good converter to targa (TGA)
//the gltLoadTGA method is found in gltools.cpp and is from the OpenGL SuperBible book
//there are quite a few ways of loading images
// Load textures in a for loop
glGenTextures(TEXTURE_COUNT, textures);
//this puts the texture into OpenGL texture memory
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
for(int iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++)
{
// Bind to next texture object
glBindTexture(GL_TEXTURE_2D, textures[iLoop]);

// Load texture data, set filter and wrap modes
//note that gltLoadTGA is in the glm.cpp file and not a built-in openGL function
pBytes0 = gltLoadTGA(textureFiles[iLoop],&iWidth, &iHeight,
&iComponents, &eFormat);

glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes0);

//set up texture parameters

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
//try these too
// glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
// glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
free(pBytes0);
}

//enable textures
glEnable(GL_TEXTURE_2D);


glEnable(GL_DEPTH_TEST); // Hidden surface removal
//glFrontFace(GL_CCW);// Counter clock-wise polygons face out
//glEnable(GL_CULL_FACE); // Do not calculate inside

glCullFace(GL_FRONT_AND_BACK);

// Enable lighting
glEnable(GL_LIGHTING);
glEnable(GL_POINT_SMOOTH);
// Setup and enable light 0
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,whiteLight);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);


// Enable colour tracking
glEnable(GL_COLOR_MATERIAL);

// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

// Black blue background
glClearColor(0.0f, 0.0f, 0.03f, 1.0f );
}


void TimerFunc(int value)
{
rotationTimer = rotationTimer +1;
glutSwapBuffers();
glutPostRedisplay();
glutTimerFunc(25, TimerFunc, 1);
}

void ChangeSize(int w, int h)
{
GLfloat fAspect;

// Prevent a divide by zero
if(h == 0)
h = 1;

// Set Viewport to window dimensions
glViewport(0, 0, w, h);

// Calculate aspect ratio of the window
fAspect = (GLfloat)w/(GLfloat)h;

// Set the perspective coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// field of view of 45 degrees, near and far planes 1.0 and 1000
//that znear and zfar should typically have a ratio of 1000:1 to make sorting out z depth easier for the GPU
gluPerspective(55.0f, fAspect, 1.0, 1000.0);
// Modelview matrix reset
glMatrixMode(GL_MODELVIEW);
//pull the eye position back to view the scene
gluLookAt(0.00,0,400.0,//eye
0.00,0.00,0.00,//centre
0.00,1.00,0.00);//up
}




int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(800, 600);// a 4:3 ratio
glutCreateWindow("Football Game");
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
glutTimerFunc(25, TimerFunc, 1);
glutSpecialFunc(SpecialKeys);
SetupRC();
glutMainLoop();
return 0;
}

tonyo_au
01-04-2014, 08:25 PM
I have no idea how to do the collision...
This is a very big topic but there is plenty of examples on the web.

rodrigoloc
01-07-2014, 10:30 AM
OpenGL doesn't handle collision detection. You could try with box-collision detection and spherical-collision detection. It's something like this:


// Box collision:
Vector3 Box1, Box2
If Box1 is inside Box2
// Collision
Else
// No collision


// Spherical collision:
Vector3 Obj1Position; Float Obj1Size;
Vector3 Obj2Position; Float Obj2Size;

If (Distance between Obj1Position and Obj2Position) < (Obj1Size + Obj2Size)
// Collision
Else
// No collision

till213
01-10-2014, 05:52 AM
"I have no idea how to do the collision with the wall and the ball."

The "ball hits the wall" test is probably one of the simplest: my math background is a bit dusty, but I think it boils down to determine whether a point is in a plane (your "wall*) or not. Now your point is not infinitely small, but has a radius instead (your "ball"), so you probably want to know: "What is the distance of a point (centre of your ball) to a given plane?" - When that distance is smaller than the radius of your ball, you have a hit!

For everything else(tm) you could also incorporate a "physics engine" which does all the math for you. "Bullet Physics" is such an engine, and it is open source!

Here is a tutorial how to incorporate it into a "the ball hits the wall" game (aka Breakout): it seems I cannot add URLs (yet?) to my posts, so google for "Bullet Physics Tutorial: Getting Started ray wenderlich" (should be the first hit)

It is for iOS and OpenGL ES 2.0 and XCode, but you'll figure it out ;)