/* $Id: tank.c,v 1.11 1996/02/15 14:08:37 if540-37 Exp if540-37 $ */ /* * (C) COPYRIGHT Vincent S. Cojot and others 1996-1997 * All Rights Reserved * Licensed Materials - Property of Vincent S. Cojot and others. * Use, duplication or disclosure restricted by Vincent S. Cojot. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef USING_MESA #include #else #include #endif #include "defines.h" #include "tank.h" /* ------------------------------------------------*/ /* Fonction principale du programme. Elle est constitue des */ /* initialisations de GL et des divers parametres puis de l'initialisation */ /* des listes d'objets pre-compilees afin d'accelerer le mouvement. */ /* ------------------------------------------------*/ void main(int argc, char *argv[]) { /* On utilise le login de l'usager comme identificateur... */ gethostname( hostname, 10); strcpy (OurName,hostname); /* On commence a traiter les arguments de la ligne de commande. */ ProcessCommandArgs(argc,argv); /* C'est ici que l'on demarre le processus fils... */ ForkIPCDaemon(); /* Si on est dans le processus pere, alors continue avec GL...*/ if (ForkPID) { /* Initialise GL et autres.. */ printf("Initializing..."); initialize(); /* initialise les display lists. */ initialize_lists(); Show_init_progress(); /* Trouve la position de depart. */ while ( FindStartupPosition() ); /* Transfere les valeurs trouvees dans la position de note tank.*/ scenePosx = RandomscenePosx; scenePosz = RandomscenePosz; sceneAngle = RandomsceneAngle; Show_init_progress(); /* Initialise le temps de depart. */ gettimeofday( &temps, NULL); CurrentDate=fmod(temps.tv_sec,20000)*1000000+temps.tv_usec; GameStatus->TheCurrentTime = 0.0; Show_init_progress(); /* Fin de l'initialisation.. */ printf("Done!!!!\n"); /* Loop principal de notre jeu: one appelle drawScene(). */ auxMainLoop( drawScene ); } } /* ------------------------------------------------*/ /* Fonction utilisee dans l'eventualite ou l'on essaie de modifier */ /* la geometrie de la fenetre d'affichage */ /* ------------------------------------------------*/ GLvoid resize( GLsizei Rwidth, GLsizei Rheight ) { width = Rwidth; height = Rheight; ChangeZoom(); } /* ------------------------------------------------*/ /* Initialisation des parametres GL et de la fenetre d'affichage */ /* ------------------------------------------------*/ GLvoid initialize(GLvoid) { /* Le jeu vient de commencer, donc il est faux qu'il est en train */ /* de terminer.. */ GameStatus->GameTerminating = 0; /* Il faut redefinir AUX_ESCAPE avant le auxInitWindow() pour */ /* pouvoir definir notre propre fonction de sortie... */ auxKeyFunc(AUX_ESCAPE, TerminateEntireGame); /* Plan de vision minimum en-deca duquel */ /* la vision des objets n'est plus permise */ near_plane = 0.1; /* Plan de vision maximum au-dela duquel */ /* la vision des objets n'est plus permise */ far_plane = 10000.0; /* Obtenir le nom de l'usager */ strcpy (loginname, getlogin()); sprintf(InfoMessage.texta, "Tank driven by : %s", loginname); /* Activation de la position de la fenetre dans le contexte X */ auxInitPosition( trueWidth/2 , trueHeight/2 , trueWidth , trueHeight); /* Activation du mode d'affichage GL utilise: Double Buffer, */ /* couleurs RGBA, profondeurs activees */ auxInitDisplayMode( AUX_RGBA | AUX_DEPTH | AUX_DOUBLE); /* Ouvre la fenetre X avec les parametres prepares par */ /* auxInitDisplayMode et par auxInitPosition. */ auxInitWindow( InfoMessage.texta ); /* Creation de la police de caracteres necessaire a l'affichage */ /* des parametres de controle dans l'ecran */ auxCreateFont(); /* Arrange la fenetre X11 */ ManageX11Windows(); /* Fonction a executer si aucun "event" n'est en attente */ /* d'etre traite par le systeme. */ auxIdleFunc( drawScene ); /* Fonction a executer dans le cas ou la geometrie de la */ /* fenetre X du programme est modifiee. */ auxReshapeFunc( resize ); resize(width,height); /* Associations des touches de clavier et des events du pointeur */ /* de souris avec des fonctions particulieres */ auxMouseFunc(AUX_LEFTBUTTON, AUX_MOUSEDOWN, mouseDown); auxMouseFunc(AUX_LEFTBUTTON, AUX_MOUSEUP, mouseUp); auxKeyFunc(AUX_UP, forwardKey); auxKeyFunc(AUX_DOWN, backwardKey); auxKeyFunc(AUX_LEFT, leftKey); auxKeyFunc(AUX_RIGHT, rightKey); auxKeyFunc(AUX_1, zoom30Key); auxKeyFunc(AUX_2, zoom60Key); auxKeyFunc(AUX_3, zoom90Key); auxKeyFunc(AUX_4, zoom120Key); auxKeyFunc(AUX_5, zoom45Key); auxKeyFunc(AUX_m, ToggleMode); auxKeyFunc(AUX_t, ToggleText); auxKeyFunc(AUX_h, ToggleHUD); auxKeyFunc(AUX_o, ToggleOver); auxKeyFunc(AUX_w, ToggleWingman); auxKeyFunc(AUX_s, ToggleSky); auxKeyFunc(AUX_p, ToggleFloor); auxKeyFunc(AUX_f, ToggleFog); auxKeyFunc(AUX_z, MoveBack); auxKeyFunc(AUX_a, MoveForward); auxKeyFunc(AUX_q, MoveLeft); auxKeyFunc(AUX_e, MoveRight); auxKeyFunc(AUX_r, ReverseSpeed); auxKeyFunc(AUX_n, AddNewFriends); auxKeyFunc(AUX_SPACE, FireMissile); auxKeyFunc(AUX_i, CallOnLineHelp); auxKeyFunc(AUX_y, WhoIsPlayingWithMe); auxKeyFunc(AUX_j, JoinNetworkGame); auxKeyFunc(AUX_d, ShowEnemyNames); /* Ceci sert a eviter de dessiner les faches cachees et donc */ /* a accelerer l'affichage de ce que voit le pilote */ glEnable(GL_CULL_FACE); /* Definitions diverses pour les tests de profondeur.*/ glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); /* Definition de la fontion de Blending. */ glBlendFunc(GL_SRC_ALPHA,GL_DST_ALPHA); /* Au cas ou il est desirable de faire de l'anti-aliasing.*/ /* glEnable(GL_POINT_SMOOTH); */ /* glEnable(GL_LINE_SMOOTH); */ /* Definitions diverses pour le Fog.*/ glFogi(GL_FOG_MODE, GL_EXP); glFogfv(GL_FOG_COLOR, fogColor); glFogf(GL_FOG_DENSITY, 0.05); glHint(GL_FOG_HINT,GL_FASTEST); /* Charge en memoire les images du tank. */ makeMissileImages(); Show_init_progress(); /* Charge en memoire les images des explosions. */ makeExplosionImages(); Show_init_progress(); /* definis quelques parametres des textures. */ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* Definition de la perspective initiale. Celle-ci peut */ /* ensuite etre changee avec les touches 1,2,3,4 et 5. */ /* L'angle de vue est alors affiche dans l'ecran. */ glMatrixMode( GL_PROJECTION ); aspect = (GLfloat) trueWidth / (GLfloat) trueHeight; gluPerspective( zoomFactor, aspect, near_plane, far_plane ); glMatrixMode( GL_MODELVIEW ); /* L'ensemble du monde est mis par defaut en shading FLAT */ /* afin d'accelerer l'affichage */ glShadeModel (GL_FLAT); glLineWidth(1.0); /* Afficher le message de bienvenue...*/ sprintf(InfoMessage.texta, "Welcome to Tank 0.4a!!!"); sprintf(InfoMessage.textc, "Press \"i\" for Help."); sprintf(InfoMessage.texte, "Press \"t\" for Debug/Normal mode."); InfoMessage.Valid = 1; InfoMessage.Age = -2.0; } /* ------------------------------------------------*/ /* Ceci est la fonction de dessin du monde tel que vu par le pilote du */ /* tank. C'est elle qui constitue la boucle principale du programme. */ /* ------------------------------------------------*/ GLvoid drawScene(GLvoid) { ManageNetworkStatus(); /* Calcul des parametres d'acceleration. */ RockFactor = RockTank(); /* ajustement des facteurs multiplicatifs de la vitesse en fonction du */ /* Frame rate du systeme graphique */ gettimeofday( &temps, NULL); TimeInterval = fmod(temps.tv_sec,20000)*1000000+temps.tv_usec - CurrentDate; if ( fabs(TimeInterval) < 2000*1000000 ) { TimeTravel = TimeInterval/1000000; } else { TimeInterval = fmod(temps.tv_sec,20000)*1000000+temps.tv_usec - CurrentDate; } CurrentDate += TimeInterval; GameStatus->TheCurrentTime += TimeTravel; #ifdef DEBUG printf("interv: %lf\n", TimeInterval); #endif /* si on n'est pas en mode Network, alors le joueur joue tout seul. */ /* Donc c'est a nous d'animer et de gerer les tanks enemis pour que */ /* le/la joueur/euse puisse s'amuser tout(e) seul(e). */ if (!Network) { SimulationRun(); } /* Utilisation du brouillard si l'utilisateur le desire.*/ if (Fog) { glEnable(GL_FOG); } else { glDisable(GL_FOG); } glPushAttrib(GL_ALL_ATTRIB_BITS); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glPushMatrix(); /* Modification du point de vue car la position de */ /* l'observateur a changee. C'est la "Bird's eye view" */ if ( overhead ) { glRotated(90.0, 1.0, 0.0, 0.0); glTranslated(0.0, sceneY, 0.0); glRotated(RockFactor, 1.0, 0.0, 0.0); } /* Modification du point de vue car la position de */ /* l'observateur a changee. C'est le Wingman*/ if ( wingman ) { glRotated(WingAngle - 90.0, 0.0, 1.0, 0.0); glTranslated( -10.0*cos(WingAngle* PI / 180) , 0.0 , -10.0*sin(WingAngle* PI / 180)); glRotated(RockFactor, 1.0, 0.0, 0.0); } /* Pour donner un effet d'acceleration. */ glRotated(-RotaSpeed/20, 0.0, 0.0, 1.0); glRotated(-RockFactor, 1.0, 0.0, 0.0); /* Positionnement de la scene.. */ glRotated(-sceneAngle, 0.0, 1.0, 0.0); glTranslated( scenePosx, 0.0, scenePosz ); glCallList(ALL_MY_AXIS); /* Identification du mode d'affichage */ if ( mode ) { glCallList(ALL_MY_WIRE_FLOOR); glCallList(ALL_WIRE_OBSTACLES); /* Le mode est WireFrame alors dessiner un */ /* Cylindre WireFrame */ glPushMatrix(); glTranslatef(0.0, 8.0, 0.0); glScalef (20.0, 20.0, 20.0); glCallList(MY_WIRE_CYL); glPopMatrix(); glPushMatrix(); glTranslated( -scenePosx, -1.0, -scenePosz ); glRotated(sceneAngle, 0.0, 1.0, 0.0); /* Pour donner un effet d'acceleration. */ glRotated(-RotaSpeed/20, 0.0, 0.0, 1.0); glTranslated( 0.0, -1.0, 0.0 ); glRotated(RockFactor, 1.0, 0.0, 0.0); glCallList(ALL_MY_WIRE_TANK); glPopMatrix(); } else { glShadeModel (GL_SMOOTH); if ( Floor ) { glCallList(ALL_MY_SOLID_FLOOR); } else { glCallList(ALL_MY_LIGHT_FLOOR); glCallList(ALL_MY_WIRE_FLOOR); } glShadeModel (GL_FLAT); glCallList(ALL_SOLID_OBSTACLES); /* Le mode est Solid alors dessiner un */ /* Cylindre solide */ glPushMatrix(); glTranslatef(0.0, 8.0, 0.0); glScalef (20.0, 20.0, 20.0); glShadeModel (GL_SMOOTH); glCallList(MY_SOLID_CYL); if (Skymode) { glTranslatef(0.0, 45.0 * zoomFactor / 120, 0.0); glScalef (100.0, 120.0 * zoomFactor / 120, 100.0); glCallList(DEEP_BLUE_SKY); } glShadeModel (GL_FLAT); glPopMatrix(); glPushMatrix(); glTranslated( -scenePosx, -1.0, -scenePosz ); glRotated(sceneAngle, 0.0, 1.0, 0.0); /* Pour donner un effet d'acceleration. */ glRotated(-RotaSpeed/20, 0.0, 0.0, 1.0); glTranslated( 0.0, -1.0, 0.0 ); glRotated(RockFactor, 1.0, 0.0, 0.0); glCallList(ALL_MY_SOLID_TANK); glPopMatrix(); } /* Si on est en mode Network, envoie aussi un paquet */ /* pour notre tank. */ if (Alive) { SendMyTankPacket(); } /* Si il y a d'autres tanks avec le notre, appelle les routines */ /* de gestion des autres tanks. */ if ( tanks ) { MoveTanks(); } /* Si il y a des debris d'autres tanks , appelle les routines */ /* de gestion des debris. */ if ( destroyed ) { MoveDestroyedTanks(); } glDisable(GL_FOG); /* Si notre tank a un missiles en vol, appelle les routines de */ /* gestion des explosions. */ if ( MyFlyingMissile ) { MoveMyMissile(); /* Si on est en mode Network, envoie aussi un paquet */ /* Pour notre missile.. */ if (Network) { SendMyMissilePacket(); } } /* Si il y a des missiles en vol, appelle les routines de */ /* gestion des missiles. */ if ( FlyingMissile ) { MoveMissiles(); } /* Si il y a des explosions, appelle les routines de gestion */ /* des explosions. */ if ( explosion ) { CallAllExplosions(); } if (Fog) { glEnable(GL_FOG); } /* Decremente FiredRecently car le canon doit etre pret */ /* tirer de nouveau au bout de FIRE_DELAY */ FiredRecently -= TimeTravel; /* Incrementer la position de notre tank d'une quantite */ /* fonction de la vitesse de deplacement */ scenePosz += TimeTravel * LongSpeed * cos ( sceneAngle * PI / 180) ; scenePosx += TimeTravel * LongSpeed * sin ( sceneAngle * PI / 180) ; /* Conserver la meme courbure de la trajectoire */ /* quelle que soit la direction du deplacement */ sceneAngle += TimeTravel * sgn(LongSpeed) * RotaSpeed; /* Normaliser l'angle pour rester entre -360 et +360 */ sceneAngle = fmod (sceneAngle , 360.0); VerifierCollision(); glPopMatrix(); glPopAttrib(); /* Enleve le FOG si il est active car le tableau de bord ne doit pas */ /* etre affecte par le brouillard. */ if (Fog) { glDisable(GL_FOG); } /* Dessine le texte et le Head-Up-Display */ glPushAttrib(GL_ALL_ATTRIB_BITS); glMatrixMode(GL_PROJECTION); glPushMatrix(); glDisable(GL_DEPTH_TEST); glLoadIdentity(); gluOrtho2D(0.0, 1.0, 0.0, 1.0); /* Appel de la fonction qui dessine les jolies */ /* petites lignes avec les curseurs de vitesse */ /* juste en dessous. */ if (hud) { DrawHUD(); } glMatrixMode (GL_MODELVIEW); glPushMatrix(); if (scoretxt) { DrawText(); } if (InfoMessage.Valid) { DisplayInfoMessage(); } glPopMatrix(); glMatrixMode( GL_PROJECTION ); glEnable(GL_DEPTH_TEST); glPopMatrix(); glMatrixMode (GL_MODELVIEW); glPopAttrib(); /* On attends que le hardware video ait fini */ /* d'afficher le tout et le signale au systeme. */ glFinish(); /* On est en mode Double Buffer, on echange donc */ /* les buffers maintenant que le second est pret */ /* a etre affiche. */ glXSwapBuffers(auxXDisplay(), auxXWindow() ); } GLvoid mouseDown(AUX_EVENTREC *event) { GLint x, y ; x = event->data[AUX_MOUSEX]; y = event->data[AUX_MOUSEY]; /* Simulate a hit */ glClearIndex(12); drawScene(); } GLvoid mouseUp(AUX_EVENTREC *event) { glClearIndex(0); drawScene(); } /* ------------------------------------------------*/ /* La routine TerminateEntireGame() Termine le jeu et envoie */ /* un signal de terminaison au daemon associe...*/ /* ------------------------------------------------*/ GLvoid TerminateEntireGame(GLvoid) { CloseSegment(); if ( (counter = kill(ForkPID, SIGTERM) ) == -1 ) { printf("Error terminating Network Daemon, exiting...\n"); exit(1); } else { printf("Network Daemon terminated successfully.\n"); } GameStatus->GameTerminating = 1; } /* ------------------------------------------------*/ /* La touche fleche gauche incremente la vitesse angulaire */ /* de 1 degre par second vers la gauche. */ /* ------------------------------------------------*/ GLvoid leftKey(GLvoid) { RotaSpeed += 5; if (RotaSpeed > 75) RotaSpeed = 75; } /* ------------------------------------------------*/ /* La touche fleche droite incremente la vitesse angulaire */ /* de 1 degre par second vers la droite. */ /* ------------------------------------------------*/ GLvoid rightKey(GLvoid) { RotaSpeed -= 5; if (RotaSpeed < -75) RotaSpeed = -75; } /* ------------------------------------------------*/ /* La touche fleche avant incremente la vitesse longitudinale */ /* de 1 metre par second vers l'avant du tank. */ /* ------------------------------------------------*/ GLvoid forwardKey(GLvoid) { VeryOldLongSpeed = OldLongSpeed; OldLongSpeed = LongSpeed; InertiaTime = CurrentDate; LongSpeed++; if (LongSpeed > 10) LongSpeed = 10; } /* ------------------------------------------------*/ /* La touche fleche arriere incremente la vitesse longitudinale */ /* de 1 metre par second vers l'arriere du tank. */ /* ------------------------------------------------*/ GLvoid backwardKey(GLvoid) { VeryOldLongSpeed = OldLongSpeed; OldLongSpeed = LongSpeed; InertiaTime = CurrentDate; LongSpeed--; if (LongSpeed < -10) LongSpeed = -10; } GLvoid MoveBack (GLvoid) { sceneY -= 10.0; if (sceneY < -600.0) sceneY = -600.0; } GLvoid MoveForward (GLvoid) { sceneY += 10.0; if (sceneY > -10.0) sceneY = -10.0; } GLvoid MoveRight (GLvoid) { WingAngle -= 10.0; if (WingAngle < -180.0) WingAngle = 180.0; } GLvoid MoveLeft (GLvoid) { WingAngle += 10.0; if (WingAngle > 180.0) WingAngle = -180.0; } GLvoid ReverseSpeed (GLvoid) { LongSpeed = - LongSpeed; } /* ------------------------------------------------*/ /* La touche numerique "1" regle l'angle de vue a 30, c'est un zoom. */ /* ------------------------------------------------*/ GLvoid zoom30Key(GLvoid) { zoomFactor = 30 ; ChangeZoom(); ResetInfoMessage(); sprintf(InfoMessage.textb, " Zoom set to 30 deg."); InfoMessage.Valid = 1; InfoMessage.Age = 1.0; } /* ------------------------------------------------*/ /* La touche numerique "5" regle l'angle de vue a 45, c'est une */ /* vue normale. */ /* ------------------------------------------------*/ GLvoid zoom45Key(GLvoid) { zoomFactor = 45 ; ChangeZoom(); ResetInfoMessage(); sprintf(InfoMessage.textb, " Zoom set to 45 deg."); InfoMessage.Valid = 1; InfoMessage.Age = 1.0; } /* ------------------------------------------------*/ /* La touche numerique "2" regle l'angle de vue a 60, c'est un petit */ /* Grand Angle. */ /* ------------------------------------------------*/ GLvoid zoom60Key(GLvoid) { zoomFactor = 60 ; ChangeZoom(); ResetInfoMessage(); sprintf(InfoMessage.textb, " Zoom set to 60 deg."); InfoMessage.Valid = 1; InfoMessage.Age = 1.0; } /* ------------------------------------------------*/ /* La touche numerique "3" regle l'angle de vue a 90, c'est un Grand Angle. */ /* ------------------------------------------------*/ GLvoid zoom90Key(GLvoid) { zoomFactor = 90 ; ChangeZoom(); ResetInfoMessage(); sprintf(InfoMessage.textb, " Zoom set to 90 deg."); InfoMessage.Valid = 1; InfoMessage.Age = 1.0; } /* ------------------------------------------------*/ /* La touche numerique "4" regle l'angle de vue a 120, c'est un tres */ /* Grand Angle ou "FishEye". */ /* ------------------------------------------------*/ GLvoid zoom120Key(GLvoid) { zoomFactor = 120 ; ChangeZoom(); ResetInfoMessage(); sprintf(InfoMessage.textb, " Zoom set to 120 deg."); InfoMessage.Valid = 1; InfoMessage.Age = 1.0; } /* ------------------------------------------------*/ /* Cette routine gere le basculement du jeu entre le mode "network" */ /* et le mode "single player". */ /* ------------------------------------------------*/ GLvoid ManageNetworkStatus(GLvoid) { /* Mise a jour du temps de dernier changement reseau.. */ GameStatus->StatusLastChangeTime += TimeTravel; GameStatus->LastTimeNetworkPlayed += TimeTravel; /* Recupere les donnees reseau...*/ if (Network) { if (Alive) { /* si le joueur n'a pas ete touche...*/ if (GameStatus->NetworkEnabled) { /* si le daemon indique network */ /* Si le dernier paquet recu date de moins de NETWORK_RUN_TIMEOUT */ if (GameStatus->StatusLastChangeTime <= NETWORK_RUN_TIMEOUT) { /* Si on a recu des paquets... */ if (GameStatus->StatusChanged) { CopyPacketsInLocalMem(); Network = 1; } } else { ExitNetworkGame(); } } else { ExitNetworkGame(); } } else { ExitNetworkGame(); } } else { if (GameStatus->NetworkEnabled) { if (GameStatus->LastTimeNetworkPlayed > NETWORK_REMIND_TIMEOUT) { ResetInfoMessage(); sprintf(InfoMessage.textb, " Other Network Players detected!!!"); sprintf(InfoMessage.textd, " Press \"j\" to join them!!!!"); InfoMessage.Valid = 1; InfoMessage.Age = 1.0; GameStatus->LastTimeNetworkPlayed = 0; } } } #ifdef DEBUG printf(" Net: %i, NetD: %i, Alive: %i\n", Network, GameStatus->NetworkEnabled, Alive); #endif } /* ---------------------------------------------------------------*/ /* Cette routine sort le joueur du mode network si le network tombe.. */ /* ---------------------------------------------------------------*/ GLvoid ExitNetworkGame(GLvoid) { FlushGameState(); Network = 0; GameStatus->NetworkEnabled = 0; GameStatus->LastTimeNetworkPlayed = 0; if (!InfoMessage.Valid) { ResetInfoMessage(); sprintf(InfoMessage.textb, " Other network players not responding.."); sprintf(InfoMessage.textd, " Single Player Mode resumed."); InfoMessage.Valid = 1; InfoMessage.Age = 0.0; } } /* ---------------------------------------------------------------*/ /* Cette routine sort le joueur du mode network si il a ete touche. */ /* ---------------------------------------------------------------*/ GLvoid KilledFromNetworkGame(char *Who) { FlushGameState(); Alive = 0; Network = 0; GameStatus->NetworkEnabled = 0; GameStatus->LastTimeNetworkPlayed = 0; ResetInfoMessage(); sprintf(InfoMessage.textb, " Your Tank was destroyed by %s.",Who); sprintf(InfoMessage.textd, " Single Player Mode resumed."); InfoMessage.Valid = 1; InfoMessage.Age = 0.0; /* envoie un paquet avec un time_stamp de -1 pour dire que notre */ /* tank a ete detruit... */ SendMyDyingTankPacket(); } /* ---------------------------------------------------------------*/ /* Cette routine permet au joueur de se joindre a un jeu en reseau */ /* si d'autres joueurs en reseau on ete detectes.. */ /* ---------------------------------------------------------------*/ GLvoid JoinNetworkGame(GLvoid) { ResetInfoMessage(); if (GameStatus->NetworkEnabled) { /* si le daemon indique network */ if (!Network) { Fog = 1; Alive = 1; Network = 1; sprintf(InfoMessage.textb, " You just joined a network Game!!!."); sprintf(InfoMessage.textd, " Welcome to the BATTLEFIELD!!!."); InfoMessage.Valid = 1; InfoMessage.Age = 0.0; FlushGameState(); /* Trouve la position de depart. */ while ( FindStartupPosition() ); /* Transfere les valeurs trouvees dans la position de note tank.*/ scenePosx = RandomscenePosx; scenePosz = RandomscenePosz; sceneAngle = RandomsceneAngle; } else { sprintf(InfoMessage.textb, " You are already in a network Game!!!."); InfoMessage.Valid = 1; InfoMessage.Age = 0.0; } } else { sprintf(InfoMessage.textb, " Cannot join a network Game!!!."); sprintf(InfoMessage.textd, " No network Players detected!!!."); InfoMessage.Valid = 1; InfoMessage.Age = 0.0; } } /* ---------------------------------------------------------------*/ /* Cette routine permet d'avoir un beau ciel bleu ou pas. */ /* ---------------------------------------------------------------*/ GLvoid FlushGameState(GLvoid) { int i; for (i=0; i 2 ) { if ( InertiaTimeDifference > (TANK_INERT_FACTOR/(4*SCENE_INERT_FACTOR)) ) { VeryOldLongSpeed = OldLongSpeed; OldLongSpeed = LongSpeed; res_temp= res_temp_temp - sgn(res_temp_temp)*count; count = (count + 1)%4; InertiaTime = CurrentDate; } } else { if ( InertiaTimeDifference > (TANK_INERT_FACTOR/SCENE_INERT_FACTOR) ) { VeryOldLongSpeed = OldLongSpeed; OldLongSpeed = LongSpeed; InertiaTime = CurrentDate; } } #ifdef DEBUG printf("rock factor: %f\n", res_temp); #endif return res_temp; } /* ------------------------------------------------*/ /* La fonction DrawHUD contient tous les vertex de la definition */ /* du Head-Up-Display du pilote du tank. On y retrouve les petites */ /* fleches animees et les lignes d'axes. */ /* ------------------------------------------------*/ GLvoid DrawHUD (GLvoid) { glShadeModel (GL_SMOOTH); glCallList(CONTROL_PANEL); glShadeModel (GL_FLAT); glCallList(CONTROL_PANEL_RADAR); glPushAttrib(GL_COLOR_BUFFER_BIT); t1 = 0.25 - (GLfloat) RotaSpeed / 700; t2 = 0.22 + (GLfloat) LongSpeed / 100; glColor3f(0.3, 0.95, 0.95); /* Lignes pour le controle 1.*/ glBegin(GL_QUAD_STRIP); glVertex2f( 0.25, 0.345); glVertex2f( t1, 0.345); glVertex2f( 0.25, 0.315); glVertex2f( t1, 0.315); glVertex2f( 0.25, 0.345); glVertex2f( t1, 0.345); glEnd(); /* Lignes pour le controle 2.*/ glBegin(GL_QUAD_STRIP); glVertex2f( 0.7225, 0.22); glVertex2f( 0.7225, t2); glVertex2f( 0.6925, 0.22); glVertex2f( 0.6925, t2); glVertex2f( 0.7225, 0.22); glVertex2f( 0.7225, t2); glEnd(); glColor3f(0.95, 0.35, 0.35); /* Lignes pour le controle 3.*/ glBegin(GL_QUAD_STRIP); if ( FiredRecently > 0.0) { glVertex2f( 0.7825, 0.12); glVertex2f( 0.7825, FiredRecently/(5*FIRE_DELAY) + 0.12 ); glVertex2f( 0.7525, 0.12); glVertex2f( 0.7525, FiredRecently/(5*FIRE_DELAY) + 0.12 ); } glEnd(); glLineWidth(2.0); glCallList(ALL_MY_STATIC_HEAD_UP); glLineWidth(1.0); RadarDiffX = 0.26; /* Affichage du point de notre tank sur le radar..*/ if ( fabs(scenePosx) < 160.0) { if ( fabs(scenePosz) < 160.0) { glPushMatrix(); glColor3f(0.3, 0.95, 0.95); glTranslatef( RadarX + (scenePosx*RadarDiffX/320) , RadarY - (scenePosz*RadarDiffY/320) , 0.0); glRotated(sceneAngle, 0.0, 0.0, 1.0); glCallList(RADAR_ITEM_MY_TANK); glPopMatrix(); } } if ( tanks ) { for (j=0; j 0) { #ifdef DEBUG printf("Not Ready to Fire!!! %.2f \n", FiredRecently); #endif } else { #ifdef DEBUG printf("Fire!!! %.2f \n", FiredRecently); #endif Missiles[0].Posx = scenePosx + (2.0 * sin ( sceneAngle * PI / 180) ); Missiles[0].Posz = scenePosz + (2.0 * cos ( sceneAngle * PI / 180) ); Missiles[0].Angle = sceneAngle; Missiles[0].Age = 0.0; Missiles[0].Valid = 1; #ifdef DEBUG Missiles[0].Posx = -20; Missiles[0].Posz = -140; Missiles[0].Angle = 30; #endif FlyingMissile++ ; MyFlyingMissile = 1; FiredRecently = FIRE_DELAY ; OldLongSpeed -= 1; VeryOldLongSpeed -= 1; #ifdef SOUND if(system("/bin/cat " PREFIX "/share/tank/eatthis.au >/dev/audio &") != 0) { } #endif } } /* ------------------------------------------------*/ /* La fonction makeMissileImages est la routine chargee. */ /* de mettre les images des missiles dans des structures */ /* de donnees accessibles par le programme. */ /* ------------------------------------------------*/ GLvoid makeMissileImages(GLvoid) { int a, i, j; char filename[255] ; MISS_IMAGE my_img; for (a = 0 ; a < NB_OF_MISSILE_TEXTURES ; a++ ) { if ( a < 9 ) { sprintf(filename, "%s/miss0%i.tga", TANK_HOME, a+1); } else { sprintf(filename, "%s/miss%i.tga", TANK_HOME, a+1); } read_Miss_tga(&my_img, filename, MAXWIDTH, MAXLENGTH); #ifdef DEBUG printf("loaded Image File %s sucessfully..\n", filename); #endif for (i = 0; i < MissImageWidth; i++) { for (j = 0; j < MissImageHeight; j++) { MissileImages[a][i][j][0] = (GLfloat) my_img.img[i][j].b/255; MissileImages[a][i][j][1] = (GLfloat) my_img.img[i][j].g/255; MissileImages[a][i][j][2] = (GLfloat) my_img.img[i][j].r/255; if ( ( MissileImages[a][i][j][0] == 0 ) && ( MissileImages[a][i][j][1] == 0 ) && ( MissileImages[a][i][j][2] == 0 ) ) { MissileImages[a][i][j][3] = 0.0; } else { MissileImages[a][i][j][3] = 1.0; } } } } } /* ------------------------------------------------*/ /* La fonction makeExplosionImages est la routine chargee. */ /* de mettre les images des explosions dans des structures */ /* de donnees accessibles par le programme. */ /* ------------------------------------------------*/ GLvoid makeExplosionImages(GLvoid) { int a, i, j; char filename[255] ; EXPL_IMAGE my_img; for (a = 0 ; a < NB_OF_EXPL_TEXTURES ; a++ ) { if ( a < 9 ) { sprintf(filename, "%s/expl0%i.tga", TANK_HOME, a+1); } else { sprintf(filename, "%s/expl%i.tga", TANK_HOME, a+1); } read_Expl_tga(&my_img, filename, EXPL_MAXWIDTH, EXPL_MAXLENGTH); #ifdef DEBUG printf("loaded Image File %s sucessfully..\n", filename); #endif for (i = 0; i < ExplImageWidth; i++) { for (j = 0; j < ExplImageHeight; j++) { ExplosionImages[a][i][j][0] = (GLfloat) my_img.img[i][j].b/255; ExplosionImages[a][i][j][1] = (GLfloat) my_img.img[i][j].g/255; ExplosionImages[a][i][j][2] = (GLfloat) my_img.img[i][j].r/255; ExplosionImages[a][i][j][3] = EXPL_ALPHA_MULTI_FACTOR*( ExplosionImages[a][i][j][0] + ExplosionImages[a][i][j][1] + ExplosionImages[a][i][j][2] ) ; } } } } /* ------------------------------------------------*/ /* Petite routine pour montrer la progression de l'initialisation */ /* du jeu a la sauce doom... */ /* ------------------------------------------------*/ GLvoid Show_init_progress(GLvoid) { printf("."); fflush(stdout); } /* ------------------------------------------------*/ /* Routine destinee a afficher des messages pendant le jeu. */ /* ------------------------------------------------*/ GLvoid DisplayInfoMessage(GLvoid) { if (InfoMessage.Age <= MAX_MESSAGE_AGE) { glPushAttrib(GL_COLOR_BUFFER_BIT); glColor3f(0.15, 0.90, 0.70); glRasterPos2f(0.05, 0.95); auxDrawStr(InfoMessage.texta); glRasterPos2f(0.05, 0.90); auxDrawStr(InfoMessage.textb); glRasterPos2f(0.05, 0.85); auxDrawStr(InfoMessage.textc); glRasterPos2f(0.05, 0.80); auxDrawStr(InfoMessage.textd); glRasterPos2f(0.05, 0.75); auxDrawStr(InfoMessage.texte); glRasterPos2f(0.05, 0.70); auxDrawStr(InfoMessage.textf); glRasterPos2f(0.05, 0.65); auxDrawStr(InfoMessage.textg); glPopAttrib(); InfoMessage.Age += TimeTravel; } else { InfoMessage.Valid = 0; sprintf(InfoMessage.texta, " "); sprintf(InfoMessage.textb, " "); sprintf(InfoMessage.textc, " "); sprintf(InfoMessage.textd, " "); sprintf(InfoMessage.texte, " "); sprintf(InfoMessage.textf, " "); sprintf(InfoMessage.textg, " "); } } /* ------------------------------------------------*/ /* Routine destinee a effacer des messages pendant le jeu. */ /* ------------------------------------------------*/ GLvoid ResetInfoMessage(GLvoid) { sprintf(InfoMessage.texta, " "); sprintf(InfoMessage.textb, " "); sprintf(InfoMessage.textc, " "); sprintf(InfoMessage.textd, " "); sprintf(InfoMessage.texte, " "); sprintf(InfoMessage.textf, " "); sprintf(InfoMessage.textg, " "); } /* ------------------------------------------------*/ /* Routine destinee a definir des attributs X11. */ /* ------------------------------------------------*/ GLvoid ManageX11Windows(GLvoid) { /* Various window manager settings */ wmhints = XAllocWMHints(); wmhints->initial_state = NormalState; wmhints->input = True; wmhints->flags = AllHints; /* Set the class for this program */ classhints = XAllocClassHint(); classhints->res_name = window_Name; classhints->res_class = window_Name; /* Setup the max and minimum size that the window will be */ sizehints = XAllocSizeHints(); sizehints->flags = PSize | PMinSize | PMaxSize; sizehints->min_width = width; sizehints->min_height = height; sizehints->max_width = width; sizehints->max_height = height; if (XStringListToTextProperty(&window_Name, 1, &windowName) == 0) { fprintf(stderr, "X: Cannot create window name resource!\n"); exit(3); } XSetWMHints(auxXDisplay(), auxXWindow(), wmhints); XSetWMNormalHints(auxXDisplay(), auxXWindow(), sizehints); XFree((char *)wmhints); XFree((char *)classhints); XFree((char *)sizehints); }