Commit a653e487 authored by Paul Desplanque's avatar Paul Desplanque Committed by GitHub

Add files via upload

parent d8cbe651
hazlab:
gcc -O2 -Wall -o hazlab -lGLU -lm -lglut -lGL *.c
clean:
rm hazlab &>/dev/null
This diff is collapsed.
/*
dimlab.h
DIMENSIONS ET POSITIONNEMENT DU LABYRINTHE ET DE LA BULLE FLOTTANTE
pour la vitesse des mouvements, cf le début de navig.c
pour les paramètres de la caméra, cf GererActionTouchesGlut() et Jeu() dans jeu.c
*/
#ifndef _HAZLAB_DIM_
#define _HAZLAB_DIM_
/*paramètres modifiables*/
#define COEFF_TAILLE 3 /*influe sur la taille de la matrice-labyrinthe*/
#define HTR_MUR 1.000f /*hauteur des murs*/
#define ALT_SOL -0.833f /*altitude du sol (coordonnée Y)*/
#define GEOM_BULLE 24 /*paramètres de la bulle qui flotte au centre de la fenètre*/
#define GEOM_OMBRE_BULLE 12
#define RAYON_BULLE 0.100 /*doit être supérieur à VITESSE_TRANSLAT (navig.c)*/
#define ALT_O_BULLE 0.750f+ALT_SOL /*coordonnée Y d'origine*/
#define AMP_MVT_BULLE 0.125f /*coefficient d'amplitude du mouvement sinusoïdal*/
/*autres*/
#define ALT_MUR ALT_SOL+HTR_MUR /*coordonnée Y du haut des murs*/
#define DIST_MAX (0.5-RAYON_BULLE) /*pour délimiter les zones interdites à la bulle*/
#endif
/*
hazlab.h
DECLARATIONS DIVERSES
*/
#ifndef _HAZLAB_
#define _HAZLAB_
/*bibliothèque standard*/
#include <stdio.h>
#include <stddef.h>
/*optimisations compilateur*/
/*
#ifdef __GNUC__
#define hINLINE( fonction ) __attribute__((always_inline)) fonction
#elif defined(_MSC_VER)
#define hINLINE( fonction ) __inline fonction
#else
#define hINLINE( fonction ) fonction
#endif
*/
#define hINLINE( fonction ) fonction
/*par souci de portabilité*/
enum {hLITTLE_ENDIAN, hBIG_ENDIAN};
/*messages d'erreurs*/
#define hMSG_ERREUR_1 "* Erreur: l'allocation memoire a echoue *\n"
#define hMSG_ERREUR_2 "* Erreur: le fichier \"%s\" est manquant *\n"
#define hMSG_ERREUR_3 "* Erreur: \"%s\" n'est pas au format BMP/DIB(Windows V3) 24 bits non compresse *\n"
#define hMSG_ERREUR_4 "* Erreur: \"%s\" -> au moins une dimension est trop grande ou trop petite *\n"
#define hMSG_ERREUR_5 "* Erreur: \"%s\" -> au moins une dimension n'est pas une puissance de 2 *\n"
/*types perso*/
typedef unsigned long hulong;
typedef unsigned char huchar;
typedef unsigned char hbool;
enum {hFAUX, hVRAI};
/*autres, commenter ou décommenter si nécessaire*/
/*#define CAMERA_LIBRE*/ /*pour passer à travers les murs*/
#endif
This diff is collapsed.
/*
main.c
PROGRAMME PRINCIPAL ET FONCTIONS UTILES
*/
/*=== externe ================================================================*/
#include <stdlib.h>
#include <limits.h>
#include <GL/glut.h>
#include "hazlab.h"
#include "textures.h"
#include "dimlab.h"
extern char Menu( void ); /*menu.c*/
extern void CreationLab( void ); /*crealab.c*/
extern GLfloat* SommetsPtrMurs, * CoordTxPtrMurs, * SommetsPtrSups, * CoordTxPtrSups;
extern void Jeu( void ); /*jeu.c*/
extern void InitNav( void ); /*navig.c*/
extern void TermNav( void );
extern void TermTextures( char ); /*textures.c*/
/*=== global(partagé) ========================================================*/
int* LabyPtr; /*début de la zone mémoire contenant la matrice-labyrinthe*/
int** LabyIJ; /*pour utiliser cette matrice sous forme LabyIJ[i][j]*/
int TailleLab; /*taille (de la matrice) d'un coté du labyrinthe*/
hbool LabyConstruit; /*indique l'existence de la matrice*/
char Codage = hLITTLE_ENDIAN; /*par défaut destiné à x86 ;-)*/
char TailleLong = 1; /*taille (calcul ultérieur de la bonne valeur) en octets d'un entier de type "long"*/
char TailleChar = CHAR_BIT/8; /*idem pour un type "char"*/
/*=== échange de la valeur de deux GLbytes ===================================*/
void EchangerGLbyte( GLubyte* const a, GLubyte* const b )
{
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
/*=== comptage des bits égaux à 1 dans un entier de type "long" ==============*/
huchar CompterBits1( hulong entier )
{
huchar cpt = 0;
while( entier )
{
cpt++;
entier &= (entier-1);
}
return cpt;
}
/*=== inversion des n octets d'un entier de type "long" ======================*/
void InverserLong( hulong* const entier, char const n )
{
char i = -1;
hulong masque = -1l, resultat = 0l;
masque = ~(masque>>8); /*bits du premier octet à 1, le reste à 0*/
while( ++i <n )
{
resultat |= ((*entier & masque)>>((TailleLong-1-i)<<3)) << (i<<3); /*on sélectionne le bon octet grâce au masque et on l'ajoute à la bonne place au résultat*/
masque >>= 8; /*on décale le masque sur l'octet suivant*/
}
*entier = resultat;
}
/*=== vérification du codage interne des entiers =============================*/
hINLINE( static void VerifierCodage( void ) )
{
hulong n = -2l; /*dernier bit à 0*/
char p = *(char*)&n;
if( p==-1 )
Codage = hBIG_ENDIAN;
n = -1l; /*tous les bits à 1*/
while( n >>= 8 ) TailleLong++;
}
/*=== destruction du labyrinthe ==============================================*/
static void LibererMemoire( void )
{
if( LabyConstruit )
{
free( LabyPtr );
free( LabyIJ );
free( SommetsPtrMurs );
free( CoordTxPtrMurs );
free( SommetsPtrSups );
free( CoordTxPtrSups );
TermNav();
TermTextures( NBR_TEXTURES );
}
}
/*=== point d'entrée =========================================================*/
int main( int nbreArgs, char* listArgs[] )
{
VerifierCodage();
atexit( LibererMemoire );
glutInit( &nbreArgs, listArgs );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
while( (TailleLab = Menu()) !=0 )
{
TailleLab = TailleLab*4*COEFF_TAILLE-1;
CreationLab();
LabyConstruit = hVRAI;
InitNav();
Jeu();
LibererMemoire();
LabyConstruit = hFAUX;
}
return EXIT_SUCCESS;
}
/*
menu.c
FENETRE DU MENU D'ENTREE (CHOIX DE LA TAILLE DU LABYRINTHE)
*/
/*=== externe ================================================================*/
#include <GL/glut.h>
#include <setjmp.h>
#include "hazlab.h"
/*=== global(menu.c)==========================================================*/
static char Choix = 3; /*(Choix-1) indexe Niveaux[]*/
#define MAX_CHOIX 5 /*tailles différentes proposées, modifier Niveaux[] en conséquence*/
static char const* const Niveaux[] = {"MINUSCULE", "PETIT", "MOYEN", "GRAND", "GIGANTESQUE"};
#define COULEUR_ARRIERE_PLAN 0.8f, 0.9f, 1.0f, 1.0f /*dimensions et couleurs de la fenêtre*/
#define COULEUR_RECTANGLE 0.5f, 0.6f, 0.7f
#define COULEUR_POLICE 0.9f, 0.9f, 0.9f
#define COULEUR_CADRE_SELECT 0.0f, 0.0f+Clic, 0.0f+Clic
#define COULEUR_POLICE_SELECT 0.0f, 0.0f+Clic, 0.0f+Clic
#define TAILLE_X 214
#define TAILLE_Y 60*MAX_CHOIX
static hbool PosCursOK; /*concernent la gestion de la souris*/
static hbool Clic;
static jmp_buf FinMenu; /*pour pouvoir sortir de glutMainLoop() !!!*/
/*=== en cas de redimensionnement de la fenêtre ==============================*/
static void Redimensionner( int const largeur, int const hauteur )
{
glutReshapeWindow( TAILLE_X, TAILLE_Y );
}
/*=== affichage du menu ======================================================*/
static void Afficher( void )
{
int i, j, k;
glClear( GL_COLOR_BUFFER_BIT );
for( i = 0; i<MAX_CHOIX; i++ )
{
k = 60*MAX_CHOIX-56-60*i;
glColor3f( COULEUR_RECTANGLE );
glRecti( 4, k, TAILLE_X-4, k+52 );
glColor3f( COULEUR_POLICE );
if( Choix==i+1 )
{
glColor3f( COULEUR_CADRE_SELECT );
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
glRecti( 4, k, TAILLE_X-4, k+52 );
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
glColor3f( COULEUR_POLICE_SELECT );
}
glRasterPos2i( 20, k+16 );
for( j = 0; Niveaux[i][j]; j++ )
glutBitmapCharacter( GLUT_BITMAP_TIMES_ROMAN_24, Niveaux[i][j] );
}
glutSwapBuffers();
}
/*=== mise à jour du choix par les touches directionnelles haut et bas =======*/
static void MAJChoixClavier( int const touche, int const x, int const y )
{
if( Clic )
return;
switch( touche )
{
case GLUT_KEY_DOWN :
if( ++Choix ==MAX_CHOIX+1 )
Choix = 1;
break;
case GLUT_KEY_UP :
if( ! --Choix )
Choix = MAX_CHOIX;
break;
default :
return;
}
glutPostRedisplay();
}
/*=== validation du choix au clavier =========================================*/
static void ValiderChoixClavier( huchar const touche, int const x, int const y )
{
if( Clic )
return;
switch( touche )
{
case 27 : /*Echap*/
Choix = 0;
case 13 : /*Entrée*/
break;
default :
return;
}
longjmp( FinMenu, 1 );
}
/*=== mise à jour du choix par la position du curseur de la souris ===========*/
static void MAJChoixSouris( int const x, int const y )
{
if( (PosCursOK = (x>0 && x<TAILLE_X && y>0 && y<TAILLE_Y)) )
{
char t = Choix;
Choix = y/60+1;
if( t!=Choix )
glutPostRedisplay();
}
}
/*=== validation du choix à la souris ========================================*/
static void ValiderChoixSouris( int const bouton, int const etat, int const x, int const y )
{
if( bouton!=GLUT_LEFT_BUTTON )
return;
if( etat==GLUT_UP )
if( PosCursOK )
longjmp( FinMenu, 1 );
else
Clic = hFAUX;
else
Clic = hVRAI;
glutPostRedisplay();
}
/*=== création de la fenêtre de menu =========================================*/
char Menu( void )
{
int fenetreMenu;
short resolEcranX = glutGet( GLUT_SCREEN_WIDTH );
short resolEcranY = glutGet( GLUT_SCREEN_HEIGHT );
glutInitWindowSize( TAILLE_X, TAILLE_Y );
glutInitWindowPosition( (resolEcranX-TAILLE_X)/2, (resolEcranY-TAILLE_Y)/2 );
fenetreMenu = glutCreateWindow( "HAZLAB" );
glClearColor( COULEUR_ARRIERE_PLAN );
glMatrixMode( GL_PROJECTION );
gluOrtho2D( 0.0, TAILLE_X, 0.0, TAILLE_Y);
Clic = hFAUX;
glutReshapeFunc( Redimensionner );
glutDisplayFunc( Afficher );
glutSpecialFunc( MAJChoixClavier );
glutKeyboardFunc( ValiderChoixClavier );
glutMotionFunc( MAJChoixSouris );
glutPassiveMotionFunc( MAJChoixSouris );
glutMouseFunc( ValiderChoixSouris );
if( setjmp( FinMenu )==0 )
glutMainLoop();
glutMotionFunc( NULL );
glutPassiveMotionFunc( NULL );
glutMouseFunc( NULL );
glutDestroyWindow( fenetreMenu );
return Choix;
}
/*
navig.c
NAVIGATION 3D ET GESTION DES MOUVEMENTS
*/
/*=== externe ================================================================*/
#include <GL/gl.h>
#include <math.h>
#include <stdlib.h>
#include "hazlab.h"
#include "dimlab.h"
extern hbool Avance, Recule, Gauche, Droite; /*jeu.c*/
extern void SortieTrouvee( void );
extern int TailleLab; /*main.c*/
extern int** LabyIJ;
extern int Sortie; /*crealab.c*/
/*=== global(partagé) ========================================================*/
GLfloat ValeurAltBulle; /*coordonnée Y de la bulle flottante ...*/
GLfloat ValeurRayOmbre; /*... rayon de son ombre en fonction de Y ...*/
GLfloat ValeurRotatY; /*... valeur en degrés de l'angle de rotation /Y ...*/
GLfloat ValeurTransX, ValeurTransZ; /*... et coordonnées de déplacement à transmettre au rendu 3D*/
/*=== global(navig.c) ========================================================*/
#define VITESSE_TRANSLAT 0.075f /*vitesse de déplacement, doit être inférieur à RAYON_BULLE (dimlab.h)*/
#define CONV_DR 0.017453f /*coeff de conversion DEG->RAD*/
#define EXTENSION_OMBRE 14.0f /*coeff de variation du rayon de l'ombre de la bulle*/
#define NBRE_VALEURS_ROTAT 90 /*nombre de valeurs possibles (détermine la vitesse) pour l'angle de rotation /Y de la caméra*/
typedef struct agl /*pour enregistrer les angles en liste chaînée*/
{
GLfloat degres, sinus, cosinus;
struct agl* prec, * suiv;
}
ANGLE;
static ANGLE* AngleY; /*angle courant de rotation /Y*/
static hbool Erreur = hFAUX; /*vrai en cas d'erreur mémoire*/
#define NBRE_VALEURS_ALT 120 /*nombre de valeurs possibles (détermine la vitesse) pour l'altitude de la bulle*/
typedef struct alt /*pour enregistrer les valeurs d'altitude en liste chaînée*/
{
GLfloat valeur, autre;
struct alt* suiv;
}
ALTI;
static ALTI* AltitudeBulle; /*coordonnée Y courante de la bulle*/
static hbool Erreur2 = hFAUX; /*vrai en cas d'erreur mémoire*/
static int I, J; /*coordonnées courantes dans la matrice LabyIJ*/
/*=== initialisation de la rotation de la caméra =============================*/
static void InitRotationCam( void )
{
short i = NBRE_VALEURS_ROTAT-1;
ANGLE* tPtrAgl[NBRE_VALEURS_ROTAT];
GLfloat tmp;
do /*on enregistre les valeurs mathématiques ...*/
{
if( (tPtrAgl[i] = malloc( sizeof( ANGLE ) )) ==NULL )
{
fprintf( stderr, hMSG_ERREUR_1 );
Erreur = hVRAI;
for( ++i ; i<NBRE_VALEURS_ROTAT; i++ )
free( tPtrAgl[i] );
exit( EXIT_FAILURE );
}
tPtrAgl[i]->degres = i*360.0f/NBRE_VALEURS_ROTAT;
tPtrAgl[i]->sinus = VITESSE_TRANSLAT*sin( tmp = tPtrAgl[i]->degres*CONV_DR );
tPtrAgl[i]->cosinus = VITESSE_TRANSLAT*cos( tmp );
}
while( --i >=0 );
tPtrAgl[0]->suiv = tPtrAgl[1]; /*... puis on "accroche" les maillons*/
tPtrAgl[0]->prec = tPtrAgl[NBRE_VALEURS_ROTAT-1];
tPtrAgl[NBRE_VALEURS_ROTAT-1]->suiv = tPtrAgl[0];
tPtrAgl[i = NBRE_VALEURS_ROTAT-1]->prec = tPtrAgl[NBRE_VALEURS_ROTAT-2];
while( --i )
{
tPtrAgl[i]->suiv = tPtrAgl[i+1];
tPtrAgl[i]->prec = tPtrAgl[i-1];
}
AngleY = *tPtrAgl;
}
/*=== initialisation du mouvement de la bulle ================================*/
static void InitMvtBulle( void )
{
short i = NBRE_VALEURS_ALT-1;
GLfloat tmp;
ALTI* tPtrAlt[NBRE_VALEURS_ALT+1]; /*+1 pour éviter à la boucle ci-dessous d'aller lire en mémoire interdite ^^*/
do
{
if( (tPtrAlt[i] = malloc( sizeof( ALTI ) )) ==NULL )
{
fprintf( stderr, hMSG_ERREUR_1 );
Erreur2 = hVRAI;
for( ++i ; i<NBRE_VALEURS_ALT; i++ )
free( tPtrAlt[i] );
exit( EXIT_FAILURE );
}
tmp = tPtrAlt[i]->valeur = ALT_O_BULLE + AMP_MVT_BULLE*sin( i*CONV_DR*360.0f/NBRE_VALEURS_ALT );
tPtrAlt[i]->autre = RAYON_BULLE*1.3f + tmp/EXTENSION_OMBRE;
tPtrAlt[i]->suiv = tPtrAlt[i+1];
}
while( --i >=0 );
tPtrAlt[NBRE_VALEURS_ALT-1]->suiv = tPtrAlt[0]; /*on boucle sur le début*/
AltitudeBulle = *tPtrAlt;
}
/*=== mise à jour de l'altitude de la bulle ==================================*/
void MAJAltBulle( void )
{
AltitudeBulle = AltitudeBulle->suiv;
ValeurAltBulle = AltitudeBulle->valeur;
ValeurRayOmbre = AltitudeBulle->autre;
}
/*=== mise à jour des coordonnées ============================================*/
void MAJCoord( void )
{
static GLfloat deplacement;
#ifndef CAMERA_LIBRE
static int ai, aj, ci, cj;
static GLfloat di, dj, avtz, avtx;
static hbool ok;
#endif
if( Gauche )
AngleY = AngleY->prec;
else
if( Droite )
AngleY = AngleY->suiv;
ValeurRotatY = AngleY->degres;
if( !(deplacement = Avance-Recule) )
return;
#ifndef CAMERA_LIBRE
avtz = ValeurTransZ;
ValeurTransZ += deplacement*AngleY->cosinus;
ai = I;
I = floor( 0.5-ValeurTransZ );
di = I+ValeurTransZ;
ci = (((di<0)<<1)-1)*(fabs( di )>DIST_MAX);
avtx = ValeurTransX;
ValeurTransX -= deplacement*AngleY->sinus;
aj = J;
J = floor( 0.5-ValeurTransX );
dj = J+ValeurTransX;
cj = (((dj<0)<<1)-1)*(fabs( dj )>DIST_MAX);
if( ai==Sortie || aj==Sortie )
SortieTrouvee();
if( !ci ^ !cj )
{
if( ci && !LabyIJ[I+ci][J] )
ValeurTransZ = -I-DIST_MAX*ci;
else
if( !LabyIJ[I][J+cj] )
ValeurTransX = -J-DIST_MAX*cj;
}
else
{
if( !cj )
return;
ok = hFAUX;
if( !LabyIJ[I][J+cj] || I!=ai )
{
ValeurTransX = -J-DIST_MAX*cj;
ok = hVRAI;
}
if( !LabyIJ[I+ci][J] || J!=aj )
{
ValeurTransZ = -I-DIST_MAX*ci;
ok = hVRAI;
}
if( ok )
return;
if( ci*cj>0 )
{
if( 0.5f-avtx-aj > 0.5f-avtz-ai )
if( ci>0 )
ValeurTransZ = -I-DIST_MAX*ci;
else
ValeurTransX = -J-DIST_MAX*cj;
else
if( ci>0 )
ValeurTransX = -J-DIST_MAX*cj;
else
ValeurTransZ = -I-DIST_MAX*ci;
}
else
{
if( 0.5f-avtz-ai > aj+0.5f-avtx )
if( ci>0 )
ValeurTransX = -J-DIST_MAX*cj;
else
ValeurTransZ = -I-DIST_MAX*ci;
else
if( ci>0 )
ValeurTransZ = -I-DIST_MAX*ci;
else
ValeurTransX = -J-DIST_MAX*cj;
}
}
#else
ValeurTransZ += deplacement*AngleY->cosinus;
ValeurTransX -= deplacement*AngleY->sinus;
#endif
}
/*=== construction des données ===============================================*/
void InitNav( void )
{
InitRotationCam();
ValeurRotatY = 0.0f;
ValeurTransX = ValeurTransZ = I = J = -TailleLab/2;
InitMvtBulle();
ValeurAltBulle = ALT_O_BULLE;
}
/*=== destruction des données ================================================*/
void TermNav( void )
{
short i;
if( Erreur )
return;
else
{
ANGLE* a = AngleY, * b;
for( i = 0; i<NBRE_VALEURS_ROTAT; i++ )
{
b = a->suiv;
free( a );
a = b;
}
}
if( Erreur2 )
return;
else
{
ALTI* a = AltitudeBulle, * b;
for( i = 0; i<NBRE_VALEURS_ALT; i++ )
{
b = a->suiv;
free( a );
a = b;
}
}
}
/*
textures.c
CHARGEMENT DES TEXTURES
à partir de fichiers-image au format BMP/DIB(Windows V3) 24 bits non compressé uniquement
*/
/*=== externe ================================================================*/
#include <GL/gl.h>
#include <GL/glu.h>
#include <stdlib.h>
#include "hazlab.h"
#include "textures.h"
extern void InverserLong( hulong* const, char const ); /*main.c*/
extern void EchangerGLbyte( GLubyte* const, GLubyte* const );
extern huchar CompterBits1( hulong );
extern char Codage, TailleChar;
/*=== global(partagé) ========================================================*/
GLuint IdTextures[NBR_TEXTURES]; /*tableau d'identifiants de texture*/
/*=== global(textures.c) =====================================================*/
#define LIRE_LG( var ) fread( &var, 4l/TailleChar, 1, fichier )
#define QUITTER( var ) TermTextures( var );\
Erreur = hVRAI;\
exit( EXIT_FAILURE )
static char NomFic[20]; /*nom du fichier en cours de traitement*/
static hbool Erreur = hFAUX; /*vrai en cas d'erreur mémoire*/
static GLubyte* AdrTextures[NBR_TEXTURES]; /*tableau de pointeurs vers les textures chargées*/
#ifdef UTIL_MIPMAPS
static GLint ModeTexturage; /*la qualité de texturage utilisée*/
#endif
typedef struct
{
GLubyte Bleu, Vert, Rouge;
}
PIXEL_BMP;
/*=== destruction des données ================================================*/
void TermTextures( char n )
{
unsigned char i;
if( Erreur )
return;
for( i = 0; i<n; i++ )
free( AdrTextures[i] );
glDeleteTextures( NBR_TEXTURES, IdTextures );
}
/*=== chargement en mémoire d'une image bitmap ===============================*/
hINLINE( static void LireBMP( FILE* const fichier, unsigned char const indice ) )
{
long largeur = 0l, hauteur = 0l; /*seul le type "long" est assuré par l'ISO de pouvoir contenir 4 octets*/
hulong debut = 0, enTete = 0, nbPixels = 0, compress = 0, i = 0;