/////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////// /////////////////////////////////////
//////////////////////////// Baballe ! par Julien COPPOLANI /////////////////////////////////////
//////////////////////////// /////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
#include <stdio.h> // fonctions sprintf, fopen, fread, fclose, ftell et fseek
#include <stdlib.h> // fonction rand
#include <math.h> // fonctions cos, sin, floor et fabs
#include <GL/glut.h>
// constantes
#define TAILLE_CIRCUIT 1024
#define DIST_VUE 8
#define PI 3.14159265358979
#define COS(X) cos( (X) * PI/180.0 )
#define SIN(X) sin( (X) * PI/180.0 )
enum { INVERT, FPS, SCORE, BOUNCING, RESTART };
enum { NOIR, ROUGE, VERT, BLEU, JAUNE_NOIR, CYAN_BLACK, MAGENTA, MULTI };
enum { SHORT_VIEW, FAR_VIEW };
enum { MARB118, MARB053, WOOD022, WOOD008, MULTI024, ROCK007, ROCK008, MULTI095,
MULTI005, MULTI119, WATER008 };
//variables globales
char titre[19] = "Baballe ! par JCOP";
char titre2[] = "Baballe ! par JCOP - Press <p> to begin.";
char buffer[25];
char buffer2[64*64*3]; // pour la texture
//GLboolean debut_partie = GL_TRUE;
GLubyte circuit[TAILLE_CIRCUIT][16][3];
GLfloat zb = 0.0, xb = 0.0, yb = 0.0;
GLfloat vitesse = 0.0;
GLfloat v_lateral = 0.0;
GLfloat v_haut = 0.0;
GLfloat v_haut_init = 5.0;
GLfloat v_haut_init_b = 5.0;
GLfloat v_max = 0.0, v_moy, dist_parcourue = 0.0;
GLint the_sphere;
GLfloat gravitation = 10.0;
GLfloat acceleration = 5.0;
GLshort anticipe_saut = GL_FALSE;
GLbyte couleur_de_fond = 'N';
GLfloat couleur_terrain[3] = {1.0, 1.0, 1.0};
GLfloat couleur_balle0[3] = {1.0, 0.0, 0.0};
GLfloat couleur_balle1[3] = {1.0, 1.0, 1.0};
GLshort score = 0;
GLint playtime = 1;
GLshort debut_aff_z = 0;
GLint retries = 0;
int mouse_x_init, mouse_y_init; // pour changer la vue par la souris
GLfloat mouse_theta_ini = 0.0, mouse_phi_ini = PI/12, mouse_theta, mouse_phi;
GLfloat cos_phi, cos_theta, sin_phi, sin_theta;
GLshort vue = 17;
GLshort nb_frames = 0;
GLboolean is_timer = GL_FALSE, aff_score = GL_FALSE, aff_vitesse = GL_FALSE;
GLint lasttime = 0;
int paused = GL_TRUE;
int left = 0, right = 0, up = 0, down = 0, brake_left = 0, brake_right = 0;
int slices = 8, stacks = 16;
GLfloat radius = 0.5;
GLboolean left_button = GL_FALSE, perdu = GL_FALSE, end = GL_FALSE;
GLshort pos_z;
GLboolean bounce = GL_FALSE;
static GLuint texName[11]; // pour la texture
GLuint current_texture = 0;
GLshort taille_circuit = TAILLE_CIRCUIT; // taille du circuit
GLboolean multi = GL_FALSE; // balle multicolore ou non
/////////////////////////////////////////// sphere //////////////////////////////////////////////
/*void sphere(GLint slices, GLint stacks)
{
//Le nombre de vertexes est égal à : (slices+1)*stacks;
static GLfloat vertex[544][3]; // ici on limite à slices = 16 et stacks = 32
GLfloat phi, theta;
int i=0, j=0, k;
GLboolean l;
GLfloat stacks_div = 360.0/stacks;
GLfloat slices_div = 180.0/slices;
GLshort nb_points = (slices+1)*stacks;
GLfloat t, p;
for(i=0,phi=0.0; i<stacks; phi+=stacks_div,i++) {
p = phi/180*PI;
theta=2.0;
j=0;
while (j<=slices) {
t = theta/180*PI;
k=(slices+1)*i+j;
vertex[k][0] = sin(t)*cos(p);
vertex[k][1] = cos(t);
vertex[k][2] = sin(t)*sin(p);
if ((j==0)||(j==slices-1))
theta+=slices_div-2.0;
else
theta+=slices_div;
j++;
}
}
// Nbre d'appels à glVertex3f :
for(i=0;i<stacks;i++) {
if (i%2)
l = GL_TRUE;
else
l = GL_FALSE;
glBegin(GL_QUAD_STRIP);
for(j=0;j<=slices;j+=2) {
k = (slices+1)*i+j;
l = !l;
if (l)
glColor3fv(couleur_balle0);
else
glColor3fv(couleur_balle1);
glVertex3f(vertex[k][0], vertex[k][1], vertex[k][2]);
glVertex3f(vertex[(k+slices+1)%nb_points][0], vertex[(k+slices+1)%nb_points][1], vertex[(k+slices+1)%nb_points][2]);
if (j!=slices) {
l = !l;
if (l)
glColor3fv(couleur_balle0);
else
glColor3fv(couleur_balle1);
glVertex3f(vertex[k+1][0], vertex[k+1][1], vertex[k+1][2]);
glVertex3f(vertex[(k+slices+2)%nb_points][0], vertex[(k+slices+2)%nb_points][1], vertex[(k+slices+2)%nb_points][2]);
}
}
glEnd();
}
}*/
void create_sphere(GLint slices, GLint stacks, GLfloat radius)
{
// a = theta, b= phi
GLfloat slices_div=180.0/slices;
GLfloat stacks_div = 360.0/stacks;
GLfloat phi, theta = -88.0;
GLuint color=0;
GLfloat x, y, z;
int i=0, j;
glNewList(the_sphere, GL_COMPILE);
//for (theta = -90.0, i = 0; i < slices; theta += slices_div, i++) {
while (i<slices) {
glBegin(GL_QUAD_STRIP);
for (phi = 0.0, j=0; j <= stacks; phi += stacks_div, j++) {
if (!multi) {
if (color)
glColor3fv(couleur_balle0);
else
glColor3fv(couleur_balle1);
}
else
glColor3f(rand()/32768.0, rand()/32768.0, rand()/32768.0);
x = radius * COS(phi) * COS(theta);
y = radius * SIN(phi) * COS(theta);
z = radius * SIN(theta);
glVertex3f(x, y, z);
x = radius * COS(phi) * COS(theta + (((i==0)||(i==slices-1))?slices_div-2.0:slices_div));
y = radius * SIN(phi) * COS(theta + (((i==0)||(i==slices-1))?slices_div-2.0:slices_div));
z = radius * SIN(theta + (((i==0)||(i==slices-1))?slices_div-2.0:slices_div));
glVertex3f(x, y, z);
color = 1 - color;
}
glEnd();
if (i==0)
theta+=slices_div-2.0;
else
theta+=slices_div;
i++;
}
glEndList();
}
/////////////////////////////////////////// textString //////////////////////////////////////////
void textString(int x, int y, char *msg, void *font)
{
glRasterPos2f(x, y);
while (*msg) {
glutBitmapCharacter(font, *msg);
msg++;
}
}
////////////////////////////////////////// strokeString /////////////////////////////////////////
void strokeString(int x, int y, char *msg, void *font)
{
glPushMatrix();
glTranslatef(x, y, 0);
glScalef(0.03125, 0.03125, 1);
while (*msg) {
glutStrokeCharacter(font, *msg);
msg++;
}
glPopMatrix();
}
/////////////////////////////////////////// filesize ////////////////////////////////////////////
long filesize(FILE *stream) {
long curpos, length;
curpos = ftell(stream);
fseek(stream, 0L, SEEK_END);
length = ftell(stream);
fseek(stream, curpos, SEEK_SET);
return length;
}
///////////////////////////////////////// display_score /////////////////////////////////////////
void display_score(void)
{
static char buff[6];
GLint time;
if ((aff_score)||(perdu)||(end)||(aff_vitesse)) {
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, 100, 0, 100);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
if (aff_vitesse) {
glColor3fv(couleur_terrain);
sprintf(buff, "%5.2f", vitesse);
strokeString(82, 96, buff, GLUT_STROKE_MONO_ROMAN);
}
if ((aff_score)||(perdu)||(end)) {
//glDisable(GL_DEPTH_TEST);
//glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(1.0, 1.0, 0.0, 0.75);
glRecti(18, 33, 83, 75);
glDisable(GL_BLEND);
glLineWidth(2.0);
glColor3f(1.00, 0.5, 0.0);
glBegin(GL_LINE_LOOP);
glVertex2i(18, 33);
glVertex2i(83, 33);
glVertex2i(83, 75);
glVertex2i(18, 75);
glEnd();
glLineWidth(1.0);
//glLineWidth(lineWidth);
glColor3f(0.0, 0.0, 1.0);
strokeString(43, 70, "SCORE", GLUT_STROKE_ROMAN);
strokeString(20, 60, "Position", GLUT_STROKE_ROMAN);
strokeString(20, 55, "Best Position", GLUT_STROKE_ROMAN);
strokeString(20, 50, "Average Speed", GLUT_STROKE_ROMAN);
strokeString(20, 45, "Max Speed", GLUT_STROKE_ROMAN);
strokeString(20, 40, "Time", GLUT_STROKE_ROMAN);
strokeString(20, 35, "Retries", GLUT_STROKE_ROMAN);
time = playtime / 1000;
v_moy = dist_parcourue * 1000 / playtime;
sprintf(buff, "%5i", debut_aff_z);
strokeString(65, 60, buff, GLUT_STROKE_MONO_ROMAN);
sprintf(buff, "%5i", score);
strokeString(65, 55, buff, GLUT_STROKE_MONO_ROMAN);
sprintf(buff, "%5.2f", v_moy);
strokeString(65, 50, buff, GLUT_STROKE_MONO_ROMAN);
sprintf(buff, "%5.2f", v_max);
strokeString(65, 45, buff, GLUT_STROKE_MONO_ROMAN);
sprintf(buff, "%5i", time);
strokeString(65, 40, buff, GLUT_STROKE_MONO_ROMAN);
sprintf(buff, "%5i", retries);
strokeString(65, 35, buff, GLUT_STROKE_MONO_ROMAN);
if (end) {
glColor3f(1.0, 0.0, 0.0);
strokeString(30, 80, "CONGRATULATIONS !", GLUT_STROKE_ROMAN);
}
//glEnable(GL_DEPTH_TEST);
//glEnable(GL_LIGHTING);
}
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
}
/////////////////////////////////////// display_the_end /////////////////////////////////////////
void display_the_end(void)
{
GLfloat i = (GLfloat)taille_circuit;
// !! glPushMatrix();
// !! glTranslatef(-xb, 0.0, -zb-DIST_VUE);
glPushMatrix();
glTranslatef(-3.0, 0.0, 0.0);
// Affichage du 'E'
glBegin(GL_LINE_LOOP);
glVertex3f(5.5, 4.0, i); glVertex3f(5.5, 2.0, i);
glVertex3f(4.0, 2.0, i); glVertex3f(4.0, 2.4, i);
glVertex3f(5.0, 2.4, i); glVertex3f(5.0, 2.8, i);
glVertex3f(4.0, 2.8, i); glVertex3f(4.0, 3.2, i);
glVertex3f(5.0, 3.2, i); glVertex3f(5.0, 3.6, i);
glVertex3f(4.0, 3.6, i); glVertex3f(4.0, 4.0, i);
glEnd();
// Affichage du 'N'
glBegin(GL_LINE_LOOP);
glVertex3f(3.5, 2.0, i); glVertex3f(3.0, 2.0, i);
glVertex3f(3.0, 3.0, i); glVertex3f(2.5, 2.0, i);
glVertex3f(2.0, 2.0, i); glVertex3f(2.0, 4.0, i);
glVertex3f(2.5, 4.0, i); glVertex3f(2.5, 3.0, i);
glVertex3f(3.0, 4.0, i); glVertex3f(3.5, 4.0, i);
glEnd();
// Affichage du 'D'
glBegin(GL_LINE_LOOP);
glVertex3f(1.5, 2.0, i); glVertex3f(0.5, 2.0, i);
glVertex3f(0.0, 2.5, i); glVertex3f(0.0, 3.5, i);
glVertex3f(0.5, 4.0, i); glVertex3f(1.5, 4.0, i);
glEnd();
glPopMatrix();
}
///////////////////////////////////////////// init //////////////////////////////////////////////
void init(void)
{
int i;
GLboolean error = GL_FALSE;
char *names[11] = { "marb118.raw", "marb053.raw", "wood022.raw", "wood008.raw",
"multi024.raw", "rock007.raw", "rock008.raw", "multi095.raw",
"multi005.raw", "multi119.raw", "water008.raw" };
char textname[22];
FILE *f;
FILE *f_circuit;
if ((f_circuit = fopen("circuits/circuit0.raw", "r"))!=NULL) {
taille_circuit = filesize(f_circuit); // taille en bytes
if (taille_circuit%48 == 0) {
fread(circuit, taille_circuit, 1, f_circuit);
fclose(f_circuit);
taille_circuit /= 48; // taille en longueur
}
else {
error = GL_TRUE;
printf("Taille du fichier incorrecte !!");
}
}
else
error = GL_TRUE;
if (error) {
f_circuit = fopen("circuits/circuit.raw", "r");
if (f_circuit)
{
fread(circuit,TAILLE_CIRCUIT*16*3, 1, f_circuit);
fclose(f_circuit);
}
}
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
the_sphere = glGenLists(1);
create_sphere(slices, stacks, radius);
// Initialisation des angles de vue
sin_phi = sin(mouse_phi_ini);
sin_theta = sin(mouse_theta_ini);
cos_phi = cos(mouse_phi_ini);
cos_theta = cos(mouse_theta_ini);
// chargement des textures
glGenTextures(11, texName);
for (i=0; i<11; i++) {
sprintf(textname, "textures/%s", names[i]);
f = fopen(textname, "r");
if (f) {
fread(buffer2, 64*64*3, 1, f);
fclose(f);
}
glBindTexture(GL_TEXTURE_2D, texName[i]);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexImage2D(GL_TEXTURE_2D, 0, 3, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer2);
}
}
///////////////////////////////// routine d'affichage principal /////////////////////////////////
void display(void)
{
static GLshort pos_x;
GLint time = glutGet(GLUT_ELAPSED_TIME);
//static DWORD temps_0 = temps;
GLfloat delta = (time - lasttime)/1000.0;
GLshort i, j;
nb_frames++; // pour le timer
if ((!perdu)&&(!paused)&&(!end)) {
playtime += time - lasttime;
lasttime = time;
if (left) {
//brake_right = 0;
v_lateral += 2*acceleration*delta;
}
else if (brake_left) {
v_lateral -= acceleration*delta;
if (v_lateral <= 0) {
v_lateral = 0.0;
brake_left = 0;
}
}
if (right) {
//brake_left = 0;
v_lateral -= 2*acceleration*delta;
}
else if (brake_right) {
v_lateral += acceleration*delta;
if (v_lateral >= 0) {
v_lateral = 0.0;
brake_right = 0;
}
}
if (up) {
vitesse += acceleration*delta;
if (vitesse > v_max)
v_max = vitesse;
}
else if (down) {
if (vitesse < -v_max)
v_max = -vitesse;
if (vitesse>=0)
vitesse -= 2*acceleration*delta;
else
vitesse -= acceleration*delta;
}
dist_parcourue += fabs(vitesse*delta); // totalise la distance parcourue totale
zb += vitesse*delta;
xb += v_lateral*delta;
yb += v_haut*delta;
if (v_haut!=0.0)
v_haut -= gravitation*delta;
if (yb<0.0) {
yb=0.0;
v_haut = 0.0;
if (anticipe_saut) {
v_haut = v_haut_init;
anticipe_saut = GL_FALSE;
}
else if (bounce) {
if (v_haut_init_b > 0.421875*v_haut_init) {
v_haut_init_b *= 0.75;
v_haut = v_haut_init_b;
}
else
v_haut_init_b = v_haut_init;
}
}
if (zb < 0.0) {
zb = 0.0;
vitesse = 0.0;
}
debut_aff_z = (GLshort) zb;
}// endif((!perdu)&&(!paused)&&(!end))
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texName[current_texture]);
////// affichage du terrain //////
glColor3fv(couleur_terrain);
glPushMatrix();
glTranslatef(-xb, 0.0, -zb-DIST_VUE);
glBegin(GL_QUADS);
for(j=debut_aff_z; j < debut_aff_z+vue; j++) {
if (j < taille_circuit) {
for(i=0; i<16; i++) {
if ((circuit[j][i][1]==0)){//&&(circuit[j][i][1]==0)&&(circuit[j][i][2]==0)) {
glTexCoord2s(0, 0); glVertex3i(i-8, 0, j);
glTexCoord2s(0, 1); glVertex3i(i-7, 0, j);
glTexCoord2s(1, 1); glVertex3i(i-7, 0, j+1);
glTexCoord2s(1, 0); glVertex3i(i-8, 0, j+1);
}
}
}
}
glEnd();
glDisable(GL_TEXTURE_2D);
if (debut_aff_z+vue > taille_circuit)
display_the_end();
glPopMatrix();
//////////////////////////////////
glEnable(GL_CULL_FACE);
//glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
glPushMatrix();
glTranslatef(0.0, radius+yb, -6.0);
glRotatef(zb*180/(PI*radius), 1.0, 0.0, 0.0);
//glRotatef(-xb*180/(PI*radius), 0.0, 0.0, 1.0);
//glScalef(0.5,0.5,0.5);
glCallList(the_sphere);
glPopMatrix();
glDisable(GL_CULL_FACE);
//glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
if (debut_aff_z+2 >= taille_circuit) {
end = GL_TRUE;
glutIdleFunc(NULL);
}
// teste si la balle ne sort pas du circuit //
else if (yb==0.0) {
pos_z = (GLshort)zb+2; // la balle est décalée sur l'axe z de -6 et le circuit de -8
pos_x = floor(xb);
if ((circuit[pos_z][pos_x+8][1]!=0)) {//||(circuit[pos_z][pos_x+7][1]!=0)||(circuit[pos_z][pos_x+7][2]!=0)) {
perdu = GL_TRUE;
glutIdleFunc(NULL);
}
else if (debut_aff_z > score)
score = debut_aff_z;
}
display_score();
glutSwapBuffers();
}
//////////////////////////////////////////// reshape ////////////////////////////////////////////
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (90.0, ((GLfloat) w) / ((GLfloat) h),0.5,64.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
gluLookAt (DIST_VUE*sin_theta*cos_phi, DIST_VUE*sin_phi, -DIST_VUE*cos_phi*cos_theta,
0.0, 0.0, 0.0,
-DIST_VUE*sin_theta*sin_phi, DIST_VUE*cos_phi, DIST_VUE*sin_phi*cos_theta);
glCullFace(GL_FRONT);
//glEnable(GL_POLYGON_SMOOTH);
}
///////////////////////////////////////////// timer /////////////////////////////////////////////
void timer(int value)
{
// value = 0
if (is_timer) {
if (value==0) {
glutTimerFunc(1000, timer, 0);
sprintf(buffer, "%s - %i", titre, nb_frames);
glutSetWindowTitle(buffer);
nb_frames = 0;
}
}
else
glutSetWindowTitle(titre);
}
//////////////////////////////////////////// special ////////////////////////////////////////////
void special (int key, int x, int y)
{
switch (key) {
case GLUT_KEY_UP:
up = 1;
break;
case GLUT_KEY_DOWN:
down = 1;
break;
case GLUT_KEY_LEFT:
left = 1;
brake_left = 0;
break;
case GLUT_KEY_RIGHT:
right = 1;
brake_right = 0;
break;
default:
break;
}
}
/////////////////////////////////////////// specialup ///////////////////////////////////////////
void specialup(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_UP:
up = 0;
break;
case GLUT_KEY_DOWN:
down = 0;
break;
case GLUT_KEY_LEFT:
left = 0;
brake_left = 1;
break;
case GLUT_KEY_RIGHT:
right = 0;
brake_right = 1;
break;
}
}
//////////////////////////////////////////// keyboard ///////////////////////////////////////////
void keyboard (unsigned char key, int x, int y)
{
static char buff_pause[] = "pause";
int i = 0;
int j = (score < pos_z) ? score : pos_z;
switch (key) {
case ' ':
if (!paused) {
if (v_haut==0)
v_haut=v_haut_init;
else
anticipe_saut=1;
}
break;
case 13:
if (end) {
xb = zb = yb = 0.0;
v_haut = vitesse = v_lateral = v_max = 0.0;
score = 0; retries = 0; dist_parcourue = 0.0; playtime = 1;
debut_aff_z = 0;
end = GL_FALSE;
glutIdleFunc(display);
lasttime = glutGet(GLUT_ELAPSED_TIME);
}
else if (perdu) {
retries++;
perdu = GL_FALSE;
v_haut = vitesse = v_lateral = 0.0;
// Recherche du point de départ antérieur //
xb = zb = 0.0;
debut_aff_z = 0;
j -= 20;
while (j > 2) {
if ((circuit[j][i][0]==0xFF)&&(circuit[j][i][1]==0)) {
zb = j - 1.5;
debut_aff_z = (GLshort) zb;
xb = i - 7.5;
break;
}
i++;
if (i==16) {
i = 0;
j--;
}
}
////////////////////////////////////////////
glutIdleFunc(display);
lasttime = glutGet(GLUT_ELAPSED_TIME);
}
break;
case 'i':
if (couleur_de_fond=='N') {
glClearColor(1.0, 1.0, 1.0, 0.0);
couleur_terrain[0] = couleur_terrain[1] = couleur_terrain[2] = 0.0;
couleur_de_fond = 'B';
}
else {
glClearColor(0.0, 0.0, 0.0, 0.0);
couleur_terrain[0] = couleur_terrain[1] = couleur_terrain[2] = 1.0;
couleur_de_fond = 'N';
}
glutPostRedisplay();
break;
case 'p':
paused = !paused;
if (paused) {
glutIdleFunc(NULL);
sprintf(buffer, "%s - %s", titre, buff_pause);
glutSetWindowTitle(buffer);
}
else {
glutIdleFunc(display);
glutSetWindowTitle(titre);
lasttime = glutGet(GLUT_ELAPSED_TIME);
}
break;
case 'v':
aff_vitesse = !aff_vitesse;
break;
/*case 't':
if (!is_timer) {
is_timer = 1;
nb_frames = 0;
//glutChangeToMenuEntry(2, "Hide FPS", FPS);
glutTimerFunc(1000, timer, 0);
}
else {
is_timer = 0;
//glutChangeToMenuEntry(2, "Display FPS", FPS);
}
break;*/
/*case 'v':
if (vue==17)
vue = 43;
else
vue = 17;
break;*/
default:
break;
}
}
//////////////////////////////////////////// mouse //////////////////////////////////////////////
void mouse(int button, int state, int x, int y)
{
static GLboolean press_down = GL_FALSE;
switch(button) {
case GLUT_LEFT_BUTTON:
if (state==GLUT_UP) {
left_button = GL_FALSE;
press_down = GL_FALSE;
mouse_phi_ini = mouse_phi;
mouse_theta_ini = mouse_theta;
}
else if (state==GLUT_DOWN) {
left_button = GL_TRUE;
if (press_down==GL_FALSE) {
press_down = GL_TRUE;
mouse_x_init = x;
mouse_y_init = y;
}
}
break;
default:
break;
}
}
//////////////////////////////////////////// motion /////////////////////////////////////////////
void motion(int x, int y)
{
if (left_button) {
mouse_theta = PI/360*(x-mouse_x_init) + mouse_theta_ini;
mouse_phi = PI/360*(y-mouse_y_init) + mouse_phi_ini;
if (mouse_theta>PI/2)
mouse_theta = PI/2;
else if (mouse_theta<-PI/2)
mouse_theta = -PI/2;
if (mouse_phi>PI/2)
mouse_phi = PI/2;
else if (mouse_phi<PI/36)
mouse_phi = PI/36;
sin_phi = sin(mouse_phi);
sin_theta = sin(mouse_theta);
cos_phi = cos(mouse_phi);
cos_theta = cos(mouse_theta);
glLoadIdentity ();
gluLookAt (DIST_VUE*sin_theta*cos_phi, DIST_VUE*sin_phi, -DIST_VUE*cos_phi*cos_theta,
0.0, 0.0, 0.0,
-DIST_VUE*sin_theta*sin_phi, DIST_VUE*cos_phi, DIST_VUE*sin_phi*cos_theta);
glutPostRedisplay();
}
}
///////////////////////////////////////// visibility ////////////////////////////////////////////
void visibility(int state)
{
switch(state) {
case GLUT_NOT_VISIBLE:
glutIdleFunc(NULL);
break;
case GLUT_VISIBLE:
glutIdleFunc(display);
break;
}
}
//////////////////////////////////////////// menu ///////////////////////////////////////////////
void menu(int value)
{
switch (value) {
case INVERT:
if (couleur_de_fond=='N') {
glClearColor(1.0, 1.0, 1.0, 0.0);
couleur_terrain[0] = couleur_terrain[1] = couleur_terrain[2] = 0.0;
couleur_de_fond = 'B';
}
else {
glClearColor(0.0, 0.0, 0.0, 0.0);
couleur_terrain[0] = couleur_terrain[1] = couleur_terrain[2] = 1.0;
couleur_de_fond = 'N';
}
break;
//glutPostRedisplay();
case FPS:
if (!is_timer) {
is_timer = GL_TRUE;
nb_frames = 0;
glutChangeToMenuEntry(2, "Hide FPS", FPS);
glutTimerFunc(1000, timer, 0);
}
else {
is_timer = GL_FALSE;
glutChangeToMenuEntry(2, "Display FPS", FPS);
}
break;
case SCORE:
if (!aff_score)
glutChangeToMenuEntry(3, "Hide Score", SCORE);
else
glutChangeToMenuEntry(3, "Display Score", SCORE);
aff_score = !aff_score;
break;
case BOUNCING:
if (!bounce)
glutChangeToMenuEntry(4, "Bounce off", BOUNCING);
else
glutChangeToMenuEntry(4, "Bounce on", BOUNCING);
bounce = !bounce;
break;
case RESTART:
xb = zb = yb = 0.0;
debut_aff_z = 0;
v_haut = vitesse = v_lateral = v_max = 0.0;
score = 0; retries = 0; dist_parcourue = 0.0; playtime = 1;
perdu = GL_FALSE;
break;
}
lasttime = glutGet(GLUT_ELAPSED_TIME);
glutPostRedisplay();
}
///////////////////////////////////////// menu_slices ///////////////////////////////////////////
void menu_slices(int value)
{
slices = value;
create_sphere(slices,stacks, radius);
lasttime = glutGet(GLUT_ELAPSED_TIME);
glutPostRedisplay();
}
///////////////////////////////////////// menu_stacks ///////////////////////////////////////////
void menu_stacks(int value)
{
stacks = value;
create_sphere(slices,stacks, radius);
lasttime = glutGet(GLUT_ELAPSED_TIME);
glutPostRedisplay();
}
///////////////////////////////////////// menu_radius ///////////////////////////////////////////
void menu_radius(int value)
{
radius = (GLfloat)value/8;
create_sphere(slices,stacks, radius);
lasttime = glutGet(GLUT_ELAPSED_TIME);
glutPostRedisplay();
}
///////////////////////////////////////// menu_colors ///////////////////////////////////////////
void menu_colors(int value)
{
multi = GL_FALSE;
couleur_balle1[0] = couleur_balle1[1] = couleur_balle1[2] = 1.0;
switch (value) {
case NOIR:
couleur_balle0[0] = couleur_balle0[1] = couleur_balle0[2] = 0.0;
break;
case ROUGE:
couleur_balle0[0] = 1.0;
couleur_balle0[1] = couleur_balle0[2] = 0.0;
break;
case VERT:
couleur_balle0[1] = 0.75;
couleur_balle0[0] = couleur_balle0[2] = 0.0;
break;
case BLEU:
couleur_balle0[2] = 1.0;
couleur_balle0[0] = couleur_balle0[1] = 0.0;
break;
case JAUNE_NOIR:
couleur_balle0[0] = couleur_balle0[1] = 1.0;
couleur_balle0[2] = 0.0;
couleur_balle1[0] = couleur_balle1[1] = couleur_balle1[2] = 0.0;
break;
case CYAN_BLACK:
couleur_balle0[1] = couleur_balle0[2] = 1.0;
couleur_balle0[0] = 0.0;
couleur_balle1[0] = couleur_balle1[1] = couleur_balle1[2] = 0.0;
break;
case MAGENTA:
couleur_balle0[0] = couleur_balle0[2] = 1.0;
couleur_balle0[1] = 0.0;
break;
case MULTI:
multi = GL_TRUE;
break;
}
create_sphere(slices,stacks, radius);
lasttime = glutGet(GLUT_ELAPSED_TIME);
glutPostRedisplay();
}
////////////////////////////////////////// menu_vue /////////////////////////////////////////////
void menu_vue(int value)
{
switch(value) {
case SHORT_VIEW:
vue = 17;
break;
case FAR_VIEW:
vue = 25;
break;
}
lasttime = glutGet(GLUT_ELAPSED_TIME);
glutPostRedisplay();
}
///////////////////////////////////// menu_acceleration /////////////////////////////////////////
void menu_acceleration(int value)
{
// t = 2 * v_haut_init / gravitation
//<=> pour t = 1 seconde, g = 2*v
v_haut_init = v_haut_init_b = (GLfloat)value;
acceleration = v_haut_init;
gravitation = 2*v_haut_init;
lasttime = glutGet(GLUT_ELAPSED_TIME);
}
//////////////////////////////////////// menu_sphere ////////////////////////////////////////////
void menu_sphere(int value)
{
return;
//lasttime = glutGet(GLUT_ELAPSED_TIME);
}
//////////////////////////////////////// menu_texture ////////////////////////////////////////////
void menu_texture(int value)
{
current_texture = value;
lasttime = glutGet(GLUT_ELAPSED_TIME);
glutPostRedisplay();
}
//////////////////////////////////////// createmenus ////////////////////////////////////////////
void createmenus(void)
{
int mainmenu, submenu_slices, submenu_stacks, submenu_radius, submenu_acceleration,
submenu_sphere, submenu_vue, submenu_colors, submenu_texture;
char buff[2];
int i;
submenu_slices = glutCreateMenu(menu_slices);
for (i=3;i<=14;i++) {
sprintf(buff, "%i", i);
glutAddMenuEntry(buff, i);
}
submenu_stacks = glutCreateMenu(menu_stacks);
for (i=6;i<=28;i+=2) {
sprintf(buff, "%i", i);
glutAddMenuEntry(buff, i);
}
submenu_radius = glutCreateMenu(menu_radius);
glutAddMenuEntry("0.25", 2);
glutAddMenuEntry("0.375", 3);
glutAddMenuEntry("0.5", 4);
glutAddMenuEntry("0.75", 6);
glutAddMenuEntry("1.0", 8);
submenu_colors = glutCreateMenu(menu_colors);
glutAddMenuEntry("Black", NOIR);
glutAddMenuEntry("Red", ROUGE);
glutAddMenuEntry("Green", VERT);
glutAddMenuEntry("Blue", BLEU);
glutAddMenuEntry("Yellow-black", JAUNE_NOIR);
glutAddMenuEntry("Cyan-black", CYAN_BLACK);
glutAddMenuEntry("Magenta", MAGENTA);
glutAddMenuEntry("Multicolor", MULTI);
submenu_acceleration = glutCreateMenu(menu_acceleration);
for (i=2; i<11; i++) {
sprintf(buff, "%i", i);
glutAddMenuEntry(buff, i);
}
submenu_sphere = glutCreateMenu(menu_sphere);
glutAddSubMenu("Radius", submenu_radius);
glutAddSubMenu("Colors", submenu_colors);
glutAddSubMenu("Slices", submenu_slices);
glutAddSubMenu("Stacks", submenu_stacks);
submenu_vue = glutCreateMenu(menu_vue);
glutAddMenuEntry("Short", SHORT_VIEW);
glutAddMenuEntry("Far", FAR_VIEW);
submenu_texture = glutCreateMenu(menu_texture);
glutAddMenuEntry("Marble1", MARB118);
glutAddMenuEntry("Marble2", MARB053);
glutAddMenuEntry("Wood1", WOOD022);
glutAddMenuEntry("Wood2", WOOD008);
glutAddMenuEntry("Rock1", MULTI024);
glutAddMenuEntry("Rock2", ROCK007);
glutAddMenuEntry("Rock3", ROCK008);
glutAddMenuEntry("Multi1", MULTI095);
glutAddMenuEntry("Multi2", MULTI005);
glutAddMenuEntry("Multi3", MULTI119);
glutAddMenuEntry("Water", WATER008);
mainmenu = glutCreateMenu(menu);
glutAddMenuEntry("Invert colors", INVERT);
glutAddMenuEntry("Display FPS", FPS);
glutAddMenuEntry("Display Score", SCORE);
glutAddMenuEntry("Bouncing on", BOUNCING);
glutAddMenuEntry("Restart", RESTART);
glutAddSubMenu("Acceleration", submenu_acceleration);
glutAddSubMenu("View", submenu_vue);
glutAddSubMenu("Sphere", submenu_sphere);
glutAddSubMenu("Texture", submenu_texture);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutSetMenu(mainmenu);
}
//////////////////////////////////// Entrée du programme ///////////////////////////////////////
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(512, 512);
glutInitWindowPosition(100, 100);
glutCreateWindow(titre2);
glutSetCursor(GLUT_CURSOR_CROSSHAIR);
glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF);
createmenus();
init();
glutDisplayFunc(display);
//glutIdleFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutSpecialFunc(special);
glutSpecialUpFunc(specialup);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutVisibilityFunc(visibility);
glutMainLoop();
return 0;
}