Algorithme de Projet N5 : Mini-Basket

Resultat :
     Jeu de mini-basket avec obstacle gerant les performances du joueur

Idee de l'algorithme :
     - Dessiner l'interface sur jeu en initialisant les objets
     - Attendre que le joueur clique sur l'interface, et regler 
       la puissance et l'angle de tir et fonction des clics
     - Si le joueur clique sur le bouton de lancement, dessin
       de la trajectoire de la balle, et verification de sa collision
       avec les objets de l'interface
     - Si le joueur clique sur le bouton pour quitter, creation d'une
       zone pour demander confirmation au joueur

Lexique des types
     -> objet = structure
	       hauteur   (entier) hauteur de l'objet
	       largeur   (entier) largeur de l'objet
	       placement (entier) abscisse de l'objet
     -> Balle = structure
               x (entier) abscisse de la balle
	       y (entier) ordonnee de la balle

Lexique des fonctions :
     -> fonction ClicSouris(in posX:entier, in posY:entier,
		 in-out puissance:entier, in-out angle:reel) : entier
	/* Modifie l'interface en fonction de la position du clic de souris
	   et renvoie un entier correspondant au statut du jeu */
     -> fonction aleat(in min:entier, in max:entier) : vide
	/* Renvoie un entier aleatoire entre min et max */
     -> fonction collision(in panier:objet, in obstacle:objet, 
		 in balle Balle) : booleen
        /* Renvoie vrai si la balle rentre en collision avec un objet */
     -> fonction dansPanier(in panier:objet, in balle:Balle) : booleen
	/* Renvoie vrai si la balle est dans le panier */
     -> fonction dessineObjet(in obstacle:objet, in panier:objet) : vide
	/* Dessine l'obstacle et le panier sur l'interface */
     -> fonction dessineCanon(in angle:reel) : vide
	/* Dessine le canon indiquant l'angle de tir */
     -> fonction dessineBalle(in balle:Balle, in couleur:entier) : vide
        /* Dessine la balle en fonction de ses coordonnees */ 
     -> fonction dessineJauge(in puissance:entier) : vide
        /* Dessine la jauge en fonction de la puissance */
     -> fonction dessineMenu(in tirsReussi:entier, in tirs:entier);
	/* Dessine le menu en fonction du score du joueur */

Lexique des constantes
     M_PI      (reel)    =3.1415    la constante PI

Lexique des variables
     sourisX     (entier)  abscisse de la souris         DONNEE
     sourisY     (entier)  ordonnee de la souris         DONNEE
     statutJeu   (entier)  statut du jeu                 INTER
     puissance   (entier)  puissance su tir	         DONNEE
     angle       (reel)	   angle du tir en radian        DONNEE
     nbTirReussi (entier)  nombre de tir reussi par      RES
			   le joueur
     nbTir       (entier)  nombre de tir fait par le     RES
			   joueur
     initObjet   (booleen) vrai si on doit reinitialiser INTER
			   le panier et l'obtacle
     obstacle    (objet)   informations de l'obstacle    INTER
     panier	 (objet)   informations du panier	 INTER
     balle	 (Balle)   informations de la balle	 INTER
     t		 (reel)	   instant de la position de la  INTER
			   balle

Algorithme :

  statutJeu <- 0
  puissance <- 50
  angle <- M_PI/4
  nbTirReussi <- 0
  nbTir <- 0
  initObjet <- vrai
  t <- 0.1

  /* Initialisation la fenetre */
  ouvrirFenetreTailleTitre(800,600,"MINI-BASKET")
  initPalette(NULL,256)

  /* Tant que le statut du jeu n'indique pas qu'il faut quitter */
  tant que statutJeu!=-1
    viderFenetre()
    srand(time(NULL))

    /* Si il faut reinitialiser l'obstacle et le panier */
    si initObjet alors
      /* Intialisation du panier et de l'obstacle
	 calcul aleatoire des coordonnes des deux objets */
      obstacle.hauteur <- aleat(100,400)
      obstacle.largeur <- aleat(10,300)
      obstacle.placement <- aleat(250,550-obstacle.largeur)
      panier.hauteur <- aleat(20,100)
      panier.largeur <- aleat(20,50)
      panier.placement <- aleat(600,789-panier.largeur)
    fsi

    /* Dessin de l'interface */
    dessineObjet(obstacle,panier)
    dessineMenu(nbTirReussi,nbTir)
    dessineCanon(angle)
    dessineJauge(puissance)
    
    /* Dessin de la balle */
    balle.x <- 150*cos(angle)
    balle.y <- 600-150*sin(angle)
    dessineBalle(balle,6)
    
    /* Tant que le statut n'indique aucune action */ 
    tant que statutJeu=0
      /* Recuperation de la position de la souris */
      positionSouris(sourisX,sourisY)
      rafraichirFenetre()
      
      /* Modification de l'interface en fonction du clic */
      statutJeu <- ClicSouris(sourisX,sourisY,puissance,angle)

      /* Dessin de la balle en fonction de l'angle de tir */
      dessineBalle(balle,1)
      balle.x <- 150*cos(angle)
      balle.y <- 600-150*sin(angle)
      dessineBalle(balle,6)
    ftant

    /* Si le statut du jeu indique le lancement */
    si statutJeu=1 alors
      t <- 0.1
      
      /* Tant que la balle n'a subit aucune collision */
      tant que collision(panier,obstacle,balle)=faux
	/* Dessin de la balle : on efface l'ancienne balle, on 
	   calcule ses nouvelles coordonnees, puis on trace la
	   balle */
	dessineBalle(balle,1)
	balle.x <- puissance*cos(angle)*t+150*cos(angle)
	balle.y <- -0.5*9.81*t*t+puissance*sin(angle)*t)*-1
	  +600-150*sin(angle)
	dessineBalle(balle,6)

	/* Temporisation de la trajectoire */
	t <- t+0.1
	usleep(100000)
	
	/* Si la balle traverse un element de l'interface on le redessine*/ 
	si balle.y<40 alors
	  dessineMenu(nbTirReussi,nbTir)
	fsi
	si balle.y<260 et balle.x<60
	  dessineJauge(puissance)
	fsi
	si balle.y>450 et balle.x<150
	  dessineCanon(angle)
	fsi
      ftant
      
      /* Augmentation du score si tir reussi */
      nbTir <- nbTir+1

      /* Ecriture d'un message en fonction de la reussite du joueur */
      modifierCouleur(2)
      si dansPanier(panier,balle) alors
	nbTirReussi <- nbTirReussi+1 
	ecrireSurImpression(300,150,"Bien jou !")
      sinon
	ecrireSurImpression(300,150,"Perdu dommage !")
      fsi
      ecrireSurImpression(300,170,"Cliquez pour recommencer...")
      
      /* Modification du statut de jeu et indication qu'il faut reinitialiser
	 l'obstacle et le panier */
      statutJeu <- 0
      initObjet <- vrai
      attendreClic()
    fsi

    /* Si le statut du jeu indique qu'il faut quitter */
    si statutJeu=-1 alors
      /* On trace un fenetre pour demander confirmation au joueur */
      modifierCouleur(256)
      tracerRectangle(300,100,500,200)     
      ecrireSurImpression(310,125,"Voulez-vous vraiment quitter ?")      
      ecrireSurImpression(340,167,"OUI")
      ecrireSurImpression(440,167,"NON")
      tracerRectangle(320,150,380,175)
      tracerRectangle(420,150,480,175)
      
      /* Tant que le joueur clique ailleurs que sur les zones de reponses,
	 on recuperation de la position de la souris */
      repeter
	positionSouris(sourisX,sourisY)
      tant que (((sourisX>320 et sourisX<380) || (sourisX>420 et sourisX<480))
	      et sourisY>150 et sourisY<175) = false
      /* Si le joueur indique qu'il faut quitter le jeu */
      si sourisX<380 alors
	/* On indique qu'il faut quitter le jeu */
	statutJeu <- -1
      sinon
	/* On reprned le jeu dans le meme etat */
	statutJeu <- 0
	initObjet <- faux
      fsi
    fsi
  ftant
  fermerFenetre()

Definition des fonctions :
     -> fonction ClicSouris(in posX:entier, in posY:entier,
		 in-out puissance:entier, in-out angle:reel) : entier
	/* Modifie l'interface en fonction de la position du clic de souris
	   et renvoie un entier correspondant au statut du jeu */
        Lexique local des variables :
	    nouvAngle   (reel)    nouvel angle calculer    INTER
	Algorithme :
	    /* Si le joueur clic sur quitter, alors on retourne -1 */
	    si posX>=0 et posX<80 et posY>=0 et posY<30 alors
               retour_de_ClicSouris <- -1
	    fsi

	    /* Si le joueur clique sur la jauge, on recalcule la puissance 
	       et on retourne 0 */
	    si posX>20 et posX<50 et posY>=50 et posY<250 alors
	       puissance <- 50+50*((250-posY)/200.0)
	       dessineJauge(puissance)
	       retour_de_ClicSouris <- 0
	    sinon
	       /* Si le joueur clique dans la zone du canon, on recalcule 
		  le nouvel angle puis on retourne 0 */ 
               si sqrt((posX*posX)+(posY-600)*(posY-600))>100 et
		  sqrt((posX*posX)+(posY-600)*(posY-600))<120 alors
		  nouvAngle <- atan((600-posY)/posX)
		  /* Si l'anqle est compris dans [5,85], alors on le 
		     conserve et redessine le canon */
		  si nouvAngle>5*M_PI/180 et nouvAngle<85*M_PI/180 alors
		     angle <- nouvAngle
		     dessineCanon(angle)
		  fsi
		  retour_de_ClicSouris <- 0
	       sinon
	          /* Si le joueur clique sur le bouton de lancement, 
		     on retourne 0 */
		  si sqrt((posX-35)*(posX-35)+(posY-565)*(posY-565))<5 alors
	             retour_de_ClicSouris <- 1
                  sinon
		     retour_de_ClicSouris <- 0
		  fsi
               fsi
            fsi
     -> fonction aleat(in min:entier, in max:entier) : vide
	/* Renvoie un entier aleatoire entre min et max */
        Algorithme :
	   retour_de_aleat <- min+(max-min)*(rand()/RAND_MAX)
     -> fonction collision(in panier:objet, in obstacle:objet, 
		 in balle Balle) : booleen
        /* Renvoie vrai si la balle rentre en collision avec un objet */
	Algorithme :
	   /* Si la balle touche le sol */
	   si balle.y+3>=600 alors
	      retour_de_collision <- vrai
           sinon
              /* Si la balle depasse la limite du decor */
	      si balle.x+3>=800 alors
		 retour_de_collision <- vrai
	      sinon      
		 /* Si la balle touche l'obstacle */
                 si balle.x+3>=obstacle.placement et 
		      balle.y+3>=600-obstacle.hauteur et 
		      balle.x-3<=obstacle.placement+obstacle.largeur alors
		    retour_de_collision <- vrai
		 sinon
		    /* Si la balle touche le premier poteau du panier */
		    si balle.x+3>=panier.placement et 
		         balle.y+3>=600-panier.hauteur et
	                 balle.x-3<=panier.placement+5 alors
		       retour_de_collision <- vrai
	            sinon
		       /* Si la balle touche le deuxieme poteau du panier */	
		       si balle.x+3>=panier.placement+panier.largeur+5 et
		            balle.y+3>=600-panier.hauteur et
	                    balle.x-3<=panier.placement+panier.largeur+10 alors 
	    	          retour_de_collision <- vrai
	               sinon
	                  retour_de_collision <- faux
	               fsi
		    fsi
		 fsi
	      fsi
           fsi
     -> fonction dansPanier(in panier:objet, in balle:Balle) : booleen
	/* Renvoie vrai si la balle est dans le panier */
	Algorithme :
	   /* Si les coordonnees de la balle correspondent a l'interieur 
	      du panier on renvoie vrai sinon on renvoie faux */
	   si balle.x+3>=panier.placement+5 et balle.y-3>=600-panier.hauteur 
	      et balle.x-3<=panier.placement+panier.largeur+5 alors
              retour_de_dansPanier <- vrai
	   sinon
              retour_de_dansPanier <- faux
	   fsi
     -> fonction dessineObjet(in obstacle:objet, in panier:objet) : vide
	/* Dessine l'obstacle et le panier sur l'interface */
	Algorithme :
	   /* Dessin de l'obstacle */
	   modifierCouleur(14)
	   remplirRectangle(obstacle.placement,600-obstacle.hauteur,
		  obstacle.placement+obstacle.largeur,600)
	   /* Dessin des poteaux du panier */
	   modifierCouleur(3)
	   remplirRectangle(panier.placement,600-panier.hauteur,
		  panier.placement+5,600)
           remplirRectangle(panier.placement+panier.largeur+5,
		  600-panier.hauteur,panier.placement+panier.largeur+10,600)
           /* Dessin du contour de l'obstacle et des deux poteaux */
           modifierCouleur(256)
	   tracerRectangle(obstacle.placement,600-obstacle.hauteur,
		  obstacle.placement+obstacle.largeur,600)
           tracerRectangle(panier.placement,600-panier.hauteur,
	          panier.placement+5,600)
           tracerRectangle(panier.placement+panier.largeur+5,600-panier.hauteur,
		  panier.placement+panier.largeur+10,600)
     -> fonction dessineCanon(in angle:reel) : vide
	/* Dessine le canon indiquant l'angle de tir */
	Algorithme :
	   modifierCouleur(1)
	   remplirCercle(0,600,150)
	   modifierCouleur(256)
	   tracerLigne(0,600,150*cos(angle),600-150*sin(angle))
	   modifierCouleur(7)
	   remplirCercle(0,600,100)
	   modifierCouleur(2)
	   remplirCercle(35,565,10)
	   modifierCouleur(256)
	   tracerCercle(0,600,100)
	   tracerCercle(0,600,120)
	   tracerCercle(35,565,10) 
     -> fonction dessineBalle(in balle:Balle, in couleur:entier) : vide
        /* Dessine la balle en fonction de ses coordonnees */ 
	Algorithme :	
	   modifierCouleur(couleur)
	   remplirCercle(balle.x,balle.y,3)
     -> fonction dessineJauge(in puissance:entier) : vide
        /* Dessine la jauge en fonction de la puissance */
	Lexique local des variables :
	    posY   (entier)  Ordonnee de la souris dans la jauge   INTER
	Algorithme :
	    /* Calcul de l'ordonnee de la jauge */
	    posY <- -1*((puissance-50)*200)/50.0+250
	    
	    /* Dessin de la jauge */
	    modifierCouleur(1)
	    remplirRectangle(21,51,50,250)
	    modifierCouleur(3)
	    remplirRectangle(21,posY,50,250)
	    modifierCouleur(256)
	    tracerLigne(21,posY,50,posY)
	    tracerRectangle(20,50,50,250)	   
     -> fonction dessineMenu(in tirsReussi:entier, in tirs:entier);
	/* Dessine le menu en fonction du score du joueur */
	Lexique local des variables :
	    moyenne (reel)         Pourcentage de tir reussi   RES
	    score   (stringstream) Texte du score du joueur
	Algorithme :
            /* Calcule de la moyenne */
	    si tirs=0 alors
	       moyenne <- 0
	    sinon
	       moyenne <- (tirsReussi/tirs)*100
	       moyenne <- ceil(moyenne*100)/100
	    fsi
	    /* Dessin du menu */
	    score <- "Score : ",tirsReussi," / ",moyenne,"%"
	    modifierCouleur(1)
	    remplirRectangle(0,0,800,30)
	    modifierCouleur(256)
	    ecrireSurImpression(20,20,"Quitter")
	    tracerLigne(0,30,800,30)
	    tracerLigne(80,0,80,30)
	    tracerLigne(650,0,650,30)
	    ecrireSurImpression(670,20,score.str().c_str()) 