Subversion Repositories shark

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*--------------------------------------------------------------*/
/*              BILIARDO: FILE CONTENENTE TASK PALLA E SCHEDULAZIONE             */
/*--------------------------------------------------------------*/

#include <kernel/func.h>
#include <stdlib.h>
#include <math.h>
#include "biliardo.h"
#include "posizion.h"

#define R 4   // dimensioni della palla
#define RB 7   // dimensioni della buca
#define COD_FRECCIA 64

static int ballexit[BALL_MAX_P]; // controllo eliminazione task palla
static int      npc = 0;        // numero dei task palla in gioco
struct  posizione PosPalla[BALL_MAX_P]; // posizione delle palle in gioco
int FlagPartita = 0;
int ch = 0, curs = 0;
int punteggio[2]; // punteggio relativo al giocatore
int giocatore = 0; // giocatore
int bForza;


TASK    palla(int i) {

  float oxf, oyf; // posizione precedente della palla
  int col;

  setPalla (i);

  mutex_lock(&palmutex);
  col = PosPalla[i].col;
  oxf = PosPalla[i].x;
  oyf = BALL_Y - PosPalla[i].y;
  mutex_unlock(&palmutex);

  mutex_lock(&mutex);
  grx_disc(oxf, oyf, R, col);
  grx_text("                      ",432,85, black, black);
  mutex_unlock(&mutex);

  while (1) {

      mutex_lock(&mutex);
      grx_disc(oxf, oyf, R, 0);
//      grx_line(oxf, oyf, oxf+vx, oyf-vy, 0);
      mutex_unlock(&mutex);

      mutex_lock(&palmutex);
      oxf = PosPalla[i].x;
      oyf = BALL_Y - PosPalla[i].y;
      mutex_unlock(&palmutex);

      mutex_lock (&delmutex);
      if (ballexit[i]) {
         npc--;
         mutex_unlock (&delmutex);
         return 0;
      }
      mutex_unlock (&delmutex);

      mutex_lock(&mutex);
      grx_disc(oxf, oyf, R, col);
//      grx_line(oxf, oyf, oxf+vx, oyf-vy, col);
           mutex_unlock(&mutex);

    task_endcycle();
  }
}

TASK sched() {

  int i, j;
  int k;

  char strTmp[21];
  struct  posizione posIn[BALL_MAX_P];
  struct  posizione posOut[BALL_MAX_P];
  struct posizione pos[BALL_MAX_P];


  int flag, bBevuta = 0;
  float dist = 0;


  float dx, dy; // variazione coordinate
  float dt;             /* incremento temporale         */
  float modx, mody;

  // angolo formato dalla retta passante per il baricentro delle palle in collisione
  float thetaB1 = 0, thetaB2 = 0;
  float tratto;    //tratto percorso
  float thetaO1, thetaO2;

  float attr = 0.0021; // attrito applicato ad ogni palla
  float acc;
  float g = 9.86; // forza di gravit… utilizzata per il calcolo dell'attrito
  float v0 = 0;

  float xCurs, yCurs;
  int bRiposiz = 1;
  int punteggio[2];
  int giocatore = 0;
  int sign;
  float v1x, v1y, v2x, v2y;
  float phi;
  float thetaV1, thetaV2;
  float thetaBarOld1, thetaBarOld2;
  // evita che venga segnalata pi— volte una collisione
  int flag1coll[BALL_MAX_P];
  // segna nella locazione di una palla con quale altra palla ha colliso
  int flagCollCorr[BALL_MAX_P];
  // ricorda per ogni palla quale Š stata la collisione precedente
  int flagCollPrec[BALL_MAX_P];
  int flagAgg[BALL_MAX_P];
  int flagAggNum[BALL_MAX_P];

  for (i=0; i<BALL_MAX_P; i++) {
      flagCollPrec[i] = -1;
  }

  dt = ((float)PERIOD_BALL)/40000;

  acc = attr * g;

  flag = 1;
  k = 0;

  while (1) {
   if (ch == 'i') {
      punteggio[0] = 0, punteggio[1] = 0;
      ch = 0;
   }

   if (FlagPartita) {

// inizio mutex
  mutex_lock(&palmutex);

   if (PosPalla[i].theta < 0)
      PosPalla[i].theta += 2*PI;
   else
      if (PosPalla[i].theta > 2*PI)
         PosPalla[i].theta -= 2*PI;

      for(i=0; i<BALL_MAX_P; i++) {
         flag1coll[i] = 0;
         flagCollCorr[i] = -1;
         flagAgg[i] = 0;
         posIn[i].x = posOut[i].x = PosPalla[i].x;
         posIn[i].y = posOut[i].y = PosPalla[i].y;
         posIn[i].v = posOut[i].v = PosPalla[i].v;
         posIn[i].theta = posOut[i].theta = PosPalla[i].theta;


      }

  mutex_unlock(&palmutex);

// fine mutex

    for(i=0; i<BALL_MAX_P; i++) {

      for(j=0; j<BALL_MAX_P; j++) {

         if (i < j && flagCollCorr[i] == -1) {

            if(posIn[i].x-R >= posIn[j].x-R && posIn[i].x-R <= posIn[j].x+R
                           && posIn[i].y-R >= posIn[j].y-R && posIn[i].y-R <= posIn[j].y+R) {

               flagCollCorr[i] = j;
               flagCollCorr[j] = i;
               break;
            }
           else

            if(posIn[i].x-R >= posIn[j].x-R && posIn[i].x-R <= posIn[j].x+R
            && posIn[i].y+R >= posIn[j].y-R && posIn[i].y+R <= posIn[j].y+R) {

               flagCollCorr[i] = j;
               flagCollCorr[j] = i;
               break;
            }
            else

               if(posIn[i].x+R >= posIn[j].x-R && posIn[i].x+R <= posIn[j].x+R
               && posIn[i].y+R >= posIn[j].y-R && posIn[i].y+R <= posIn[j].y+R) {

                  flagCollCorr[i] = j;
                  flagCollCorr[j] = i;
                  break;
               }
               else

                  if(posIn[i].x+R >= posIn[j].x-R && posIn[i].x+R <= posIn[j].x+R
                                 && posIn[i].y-R >= posIn[j].y-R && posIn[i].y-R <= posIn[j].y+R) {

                     flagCollCorr[i] = j;
                     flagCollCorr[j] = i;
                     break;
                  }
                  else {
                    flagCollCorr[i] = -1;
                    flagCollPrec[i] = -1;
                  }


        }      // fine if(i!=j)
      }        // fine ciclo for(j)


            if (flagCollCorr[i] != -1 && flagCollCorr[i] != flagCollPrec[i])  {


               dist = sqrt(pow(posIn[i].x - posIn[flagCollCorr[i]].x,2)
                    + pow(posIn[i].y - posIn[flagCollCorr[i]].y,2));
               if (dist < 2*R) {
                  flagAgg[i] = 1;
                  flagAgg[flagCollCorr[i]] = 1;
                  dist = ceil (2*R-dist);
                  if ((int)dist%2 != 0)
                     dist += 1;
                  flagAggNum[i] = (int)dist/2;

               }

                  // permette la sola collisione di due palle contemporaneamente
                  flag1coll[i] = 1;

               flagCollPrec[i] = flagCollCorr[i];

            }

    }          // fine ciclo for(i)


    for(i=0; i<BALL_MAX_P; i++) {   // inizio ciclo for calcolo collisioni

       if (flag1coll[i]) {

          if (flag1coll[0])
             bBevuta = 0;



          sign = 1;
          modx = posIn[i].x - posIn[flagCollCorr[i]].x;
          mody = posIn[i].y - posIn[flagCollCorr[i]].y;
          if (modx*mody < 0) sign = 0;
          if (modx < 0) modx = -modx;
          if (mody < 0) mody = -mody;

// prima palla
          if (posIn[i].x <= posIn[flagCollCorr[i]].x && posIn[i].y <= posIn[flagCollCorr[i]].y) {
             // angolo formato dalla retta passante per il baricentro delle due palle
             thetaB1 = atan (mody / modx);

             if (flagAgg[i]) {
                posOut[i].x -=flagAggNum[i], posOut[i].y -=flagAggNum[i];
                flagAgg[i] = 0;
             }

          }
          else
              if (posIn[i].x >= posIn[flagCollCorr[i]].x && posIn[i].y <= posIn[flagCollCorr[i]].y) {
                 thetaB1 = PI - atan (mody / modx);

                 if (flagAgg[i]) {
                    posOut[i].x +=flagAggNum[i], posOut[i].y -=flagAggNum[i];
                    flagAgg[i] = 0;
                 }

              }
              else
                  if (posIn[i].x >= posIn[flagCollCorr[i]].x && posIn[i].y >= posIn[flagCollCorr[i]].y) {
                     thetaB1 = PI + atan (mody / modx);

                     if (flagAgg[i]) {
                        posOut[i].x +=flagAggNum[i], posOut[i].y +=flagAggNum[i];
                        flagAgg[i] = 0;
                     }

                  }
                  else
                      if (posIn[i].x <= posIn[flagCollCorr[i]].x && posIn[i].y >= posIn[flagCollCorr[i]].y) {
                         thetaB1 = 2*PI - atan (mody / modx);

                         if (flagAgg[i]) {
                            posOut[i].x -=flagAggNum[i], posOut[i].y +=flagAggNum[i];
                            flagAgg[i] = 0;
                         }

                  }

          if (thetaB1 < 0)
             thetaB1 += 2*PI;
          else
             if (thetaB1 > 2*PI)
                thetaB1 -= 2*PI;

// seconda palla
          if (posIn[i].x >= posIn[flagCollCorr[i]].x && posIn[i].y >= posIn[flagCollCorr[i]].y) {
             // angolo formato dalla retta passante per il baricentro delle due palle
             thetaB2 = atan (mody / modx);
          }
          else
              if (posIn[i].x <= posIn[flagCollCorr[i]].x && posIn[i].y >= posIn[flagCollCorr[i]].y) {
                 thetaB2 = PI - atan (mody / modx);
              }
              else
                  if (posIn[i].x <= posIn[flagCollCorr[i]].x && posIn[i].y <= posIn[flagCollCorr[i]].y) {
                     thetaB2 = PI + atan (mody / modx);
                  }
                  else
                      if (posIn[i].x >= posIn[flagCollCorr[i]].x && posIn[i].y <= posIn[flagCollCorr[i]].y) {
                         thetaB2 = 2*PI - atan (mody / modx);
                  }

          if (thetaB2 < 0)
             thetaB2 += 2*PI;
          else
             if (thetaB2 > 2*PI)
                thetaB2 -= 2*PI;




// aggiorno gli angoli rispetto al nuovo sistema di riferimento della prima palla
// con 0 in thetaB1-PI/2
          posOut[i].theta = posIn[i].theta + PI/2 - thetaB1;
          if (posOut[i].theta < 0)
             posOut[i].theta += 2*PI;
          else
              if (posOut[i].theta > 2*PI)
                 posOut[i].theta -= 2*PI;

          thetaO1 = posOut[i].theta;

// stessa cosa per la seconda palla con 0 in thetaB2-PI/2
          posOut[flagCollCorr[i]].theta = posIn[flagCollCorr[i]].theta + PI/2 - thetaB2;
          if (posOut[flagCollCorr[i]].theta < 0)
             posOut[flagCollCorr[i]].theta += 2*PI;
          else
              if (posOut[flagCollCorr[i]].theta > 2*PI)
                 posOut[flagCollCorr[i]].theta -= 2*PI;
          thetaO2 = posOut[flagCollCorr[i]].theta;



          thetaBarOld1 = thetaB1;
          thetaBarOld2 = thetaB2;
          thetaB1 = PI/2;
          thetaB2 = PI/2;




// Ho l'angolo formato dalle due palle => aggiorno gli angoli rispetto
// al nuovo sistema di riferimento



          if (cos(posOut[i].theta) <= 0)
             thetaV1 = PI - posOut[i].theta;
          else
              thetaV1 = -posOut[i].theta;
          if (thetaV1 < 0)
             thetaV1 = -thetaV1;


          if (cos(posOut[flagCollCorr[i]].theta) <= 0)
             thetaV2 = PI - posOut[flagCollCorr[i]].theta;
          else
              thetaV2 = -posOut[flagCollCorr[i]].theta;
          if (thetaV2 < 0)
             thetaV2 = -thetaV2;



          v1x = posIn[i].v * pow(cos(thetaV1), 2);
          v1y = posIn[i].v * pow(sin(thetaV1), 2);
          v2x = posIn[flagCollCorr[i]].v * pow(cos(thetaV2), 2);
          v2y = posIn[flagCollCorr[i]].v * pow(sin(thetaV2), 2);

// aggiusto i segni secondo il sistema della prima palla
          if (cos(posOut[i].theta) < 0)
             v1x = -v1x;
          if (sin(posOut[i].theta) < 0)
             v1y = -v1y;
          if (cos(posOut[flagCollCorr[i]].theta) > 0)
             v2x = -v2x;
          if (sin(posOut[flagCollCorr[i]].theta) > 0)
             v2y = -v2y;

          if (!v1y && v2y > 0) {
             v2y = 0;
          }

          if (v1y < 0 && v1y < v2y) {
             v2y = v1y;

          }


          // nuovo modulo della velocit… della palla 1
          posOut[i].v = sqrt(pow(v1x, 2) + pow(v2y, 2));


          if (v1x) {
             phi = atan (v2y / v1x);
             if (phi < 0)
                phi = -phi;
             }
          else
              phi = PI/2;

          if (v1x >= 0 && v2y >= 0) {
             // primo quadrante
                phi = phi;
          }
          else
              if (v1x <= 0 && v2y >= 0) {
                 // secondo quadrante
                    phi = PI/2 + (PI/2-phi);
              }
              else
                  if (v1x <= 0 && v2y <= 0)
                     // terzo quadrante
                     phi = PI + phi;
                  else
                      if (v1x >= 0 && v2y <= 0)
                         // quarto quadrante
                         phi = 3*PI/2 + (PI/2-phi);

          posOut[i].theta = phi;


          if (posOut[i].theta > 2*PI )
             posOut[i].theta = posOut[i].theta - 2*PI;
          else
             posOut[i].theta = posOut[i].theta;



// riporto tutto nel sistema di riferimento iniziale
          posOut[i].theta += -PI/2 + thetaBarOld1;
          if (posOut[i].theta < 0)
             posOut[i].theta += 2*PI;
          else
              if (posOut[i].theta > 2*PI)
                 posOut[i].theta -= 2*PI;
          posOut[flagCollCorr[i]].theta += (-PI/2 + thetaBarOld2);
          if (posOut[flagCollCorr[i]].theta < 0)
             posOut[flagCollCorr[i]].theta += 2*PI;
          else
              if (posOut[flagCollCorr[i]].theta > 2*PI)
                 posOut[flagCollCorr[i]].theta -= 2*PI;




          thetaB1 = thetaBarOld1;
          thetaB2 = thetaBarOld2;


/*               if (flag2 < 4) {

                  itoa (i, strTmp);
                  grx_text(strTmp,322,185+flag2*22, gray, black );
                  itoa (flagCollCorr[i], strTmp);
                  grx_text(strTmp,322,195+flag2*22, gray, black );

                  sprintf (strTmp, "%f", posIn[i].theta*360/(2*PI));
                  grx_text(strTmp,342,185+flag2*22, gray, black );
                  sprintf (strTmp, "%f", posIn[flagCollCorr[i]].theta*360/(2*PI));
                  grx_text(strTmp,342,195+flag2*22, gray, black );

                  sprintf (strTmp, "%f", posOut[i].theta*360/(2*PI));
                  grx_text(strTmp,432,185+flag2*22, gray, black );
                  sprintf (strTmp, "%f", posOut[flagCollCorr[i]].theta*360/(2*PI));
                  grx_text(strTmp,432,195+flag2*22, gray, black );

                  sprintf (strTmp, "%f", thetaB1*360/(2*PI));
                  grx_text(strTmp,522,185+flag2*22, gray, black );
                  sprintf (strTmp, "%f", thetaB2*360/(2*PI));
                  grx_text(strTmp,522,195+flag2*22, gray, black );
//       -----------------------
                  sprintf (strTmp, "%f", posIn[i].v);
                  grx_text(strTmp,322,290+flag2*22, gray, black );
                  sprintf (strTmp, "%f", posIn[flagCollCorr[i]].v);
                  grx_text(strTmp,322,300+flag2*22, gray, black );

                  sprintf (strTmp, "%f", v1x);
                  grx_text(strTmp,412,290+flag2*22, gray, black );
                  sprintf (strTmp, "%f", v2x);
                  grx_text(strTmp,412,300+flag2*22, gray, black );

                  sprintf (strTmp, "%f", v1y);
                  grx_text(strTmp,502,290+flag2*22, gray, black );
                  sprintf (strTmp, "%f", v2y);
                  grx_text(strTmp,502,300+flag2*22, gray, black );

                  sprintf (strTmp, "%f", posOut[i].v);
                  grx_text(strTmp,582,290+flag2*22, gray, black );
                  sprintf (strTmp, "%f", posOut[flagCollCorr[i]].v);
                  grx_text(strTmp,582,300+flag2*22, gray, black );
//       -----------------------
                  sprintf (strTmp, "%f", thetaV1*360/(2*PI));
                  grx_text(strTmp,322,390+flag2*22, gray, black );
                  sprintf (strTmp, "%f", thetaV2*360/(2*PI));
                  grx_text(strTmp,322,400+flag2*22, gray, black );

                  sprintf (strTmp, "%f", thetaO1*360/(2*PI));
                  grx_text(strTmp,402,390+flag2*22, gray, black );
                  sprintf (strTmp, "%f", thetaO2*360/(2*PI));
                  grx_text(strTmp,412,400+flag2*22, gray, black );

                  flag2++;
               }
*/


       } // fine if flag1coll





       // questo if fa i conti del movimento di ogni pallina
               if(posOut[i].v > 0) {

                  posOut[i].v -= acc * dt;

                  tratto = posOut[i].v * dt -0.5*acc*dt*dt;

                  dx = (float) (tratto * cos(posOut[i].theta));
                  dy = (float) (tratto * sin(posOut[i].theta));

                  posOut[i].x += dx;
                  posOut[i].y += dy;



                       if (posOut[i].x > BALL_XMAX) {
                               posOut[i].x = BALL_XMAX;
                               posOut[i].theta = PI - posOut[i].theta;
                  }

                       if (posOut[i].x < BALL_XMIN) {
                               posOut[i].x = BALL_XMIN;
                               posOut[i].theta = PI - posOut[i].theta;
                  }

                  if (posOut[i].y > BALL_YMAX) {
                     posOut[i].y = BALL_YMAX;
                     posOut[i].theta =  -posOut[i].theta;
                  }

                  if (posOut[i].y < 0) {
                     posOut[i].y = 0;
                     posOut[i].theta = -posOut[i].theta;
                  }
               }

         pos[i].x = posOut[i].x;
         pos[i].y = posOut[i].y;
         pos[i].v = posOut[i].v;
         pos[i].theta = posOut[i].theta;

    }  //fine ciclo for calcolo collisioni

   if (!pos[0].v && !pos[1].v && !pos[2].v && !pos[3].v && !pos[4].v && !pos[5].v &&
      !pos[6].v && !pos[7].v && !pos[8].v && !pos[9].v && !pos[10].v) {

      for (i=0; i<BALL_MAX_P; i++) {
          flagCollPrec[i] = -1;
      }

   }

   if (bRiposiz && flag) {
      mutex_lock(&mutex);
      grx_text("Modo riposizionamento palla bianca",322,85, white, black);
      mutex_unlock(&mutex);
      flag = 0;
   }

// posizionamento palla 0
    if (bRiposiz && curs) {
       if (curs == 77 && pos[0].x+R/2 <= BALL_XMAX) pos[0].x += 3;
       if (curs == 75 && pos[0].x-R >= BALL_XMIN) pos[0].x -= 3;
       curs = 0;
    }

// entra in modalit… calibrazione forza
    if (ch == ' ' && !bForza && (!pos[0].v && !pos[1].v && !pos[2].v
       && !pos[3].v && !pos[4].v && !pos[5].v && !pos[6].v &&
       !pos[7].v && !pos[8].v && !pos[9].v && !pos[10].v)) {

       bForza = 1;
       ch = 0, v0 = 3.5;
       xCurs = pos[0].x, yCurs = BALL_Y-pos[0].y+10;
       if (yCurs >= BALL_Y) yCurs = BALL_Y-pos[0].y;

            mutex_lock(&mutex);
       grx_text("Modo riposizionamento palla bianca",322,85, black, black);
       grx_text("Modo calibrazione forza",322,85, white, black);
       grx_text("Forza: ",322,95, white, black);
       sprintf (strTmp, "%2f", v0);
       grx_text(strTmp,402,95, red, black);
       grx_line(xCurs-2, yCurs, xCurs+2, yCurs, red);
       grx_line(xCurs, yCurs+2, xCurs, yCurs-2, red);
            mutex_unlock(&mutex);

       bRiposiz = 0;
    }

// calibrazione forza
    if (ch == 'a' && bForza) {
       if (v0 < 7.5)
          v0 += 0.3;
       if (v0 > 7.5)
          v0 = 7.5;
       ch = 0;

       mutex_lock(&mutex);
       grx_text("    ",402,95, black, black);
       sprintf (strTmp, "%2f", v0);
       grx_text(strTmp,402,95, red, black);
       mutex_unlock(&mutex);
    }
    else
        if (ch == 'z' && bForza) {
           if (v0 > 0)
              v0 -= 0.1;
           if (v0 < 0)
              v0 = 0;
           ch = 0;

           mutex_lock(&mutex);
           grx_text("    ",402,95, black, black);
           sprintf (strTmp, "%2f", v0);
           grx_text(strTmp,402,95, red, black);
           mutex_unlock(&mutex);

        }

// aggiusta il mirino
    if (bForza && curs) {
       mutex_lock(&mutex);
       grx_line(xCurs-2, yCurs, xCurs+2, yCurs, black);
       grx_line(xCurs, yCurs+2, xCurs, yCurs-2, black);
       if (curs == 72 && yCurs >= BALL_Y-BALL_YMAX-1) yCurs -= 2;
       if (curs == 80 && yCurs <= BALL_Y) yCurs += 2;
       if (curs == 77 && xCurs <= BALL_XMAX) xCurs += 2;
       if (curs == 75 && xCurs >= BALL_XMIN) xCurs -= 2;
       grx_line(xCurs-2, yCurs, xCurs+2, yCurs, red);
       grx_line(xCurs, yCurs+2, xCurs, yCurs-2, red);
       mutex_unlock(&mutex);
       curs = 0;
       bRiposiz = 0;

    }

// bevuta
    if (!pos[0].v && bBevuta) {
       pos[0].x = BALL_XMIN+100;
       pos[0].y = 50;
       pos[0].v = 0;
       pos[0].theta = 0;
       bRiposiz = 1;
       flag = 1;
       if (giocatore)
          giocatore = 0;
       else
           giocatore = 1;
       bBevuta = 0;
       mutex_lock(&mutex);
       grx_text("Modo riposizionamento palla bianca",322,85, white, black);
       mutex_unlock(&mutex);

    }

// scocca il colpo di stecca
    if (bForza && ch == ' ') {

//       mutex_lock(&palmutex);
       pos[0].v = v0;
       if (pos[0].x-xCurs)
          pos[0].theta = atan ((BALL_Y-pos[0].y-yCurs)/(pos[0].x-xCurs));
       else
           pos[0].theta = PI/2;

       if (pos[0].theta <0)
          pos[0].theta = -pos[0].theta;

       if (xCurs <= pos[0].x && yCurs >= BALL_Y-pos[0].y)
          // primo quadrante
          pos[0].theta = pos[0].theta;
       else
           if (xCurs >= pos[0].x && yCurs >= BALL_Y-pos[0].y)
              // secondo quadrante
              pos[0].theta = PI/2 + (PI/2-pos[0].theta);
           else
               if (xCurs >= pos[0].x && yCurs <= BALL_Y-pos[0].y)
                  // terzo quadrante
                  pos[0].theta = PI + pos[0].theta;
               else
                   if (xCurs <= pos[0].x && yCurs <= BALL_Y-pos[0].y)
                   // quarto quadrante
                   pos[0].theta = 3*PI/2 + (PI/2-pos[0].theta);


//       mutex_unlock(&palmutex);
       mutex_lock(&mutex);
       grx_line(xCurs-2, yCurs, xCurs+2, yCurs, black);
       grx_line(xCurs, yCurs+2, xCurs, yCurs-2, black);
       grx_text("Modo calibrazione forza",322,85, black, black);
       grx_text("Forza: ",322,95, black, black);
       grx_text("    ",402,95, black, black);
       mutex_unlock(&mutex);
       ch = bForza = 0;
       v0 = 0;
       bBevuta = 1;
    }

    if (ch == 'x') {
       for (i=0; i<BALL_MAX_P; i++) {
           flagCollPrec[i] = -1;
       }
       ch = 0;

    }

    itoa (giocatore, strTmp);
    mutex_lock(&mutex);
    grx_text(strTmp,432,110, red, black );
    itoa (punteggio[giocatore], strTmp);
    grx_text(strTmp,432,120, red, black );
    mutex_unlock(&mutex);


// aggiornamento della posizione delle palle
  mutex_lock(&palmutex);

      for (i=0; i<BALL_MAX_P; i++) {
         if (controlloBuche (pos[i].x, pos[i].y, i)) {

            if (i) {
               pos[i].x = -10;
               pos[i].y = 30;
               pos[i].v = 0;
               pos[i].theta = 0;
               punteggio[giocatore]++;
//                     itoa (npc, strTmp);
//                     grx_text(strTmp,322,285, black, red );
               if (punteggio[giocatore] >= 5) {

                  itoa (punteggio[giocatore], strTmp);

                  if (punteggio[giocatore] > 5) {
                     mutex_lock(&mutex);
                     grx_text(strTmp,432,120, red, black );
                     grx_text("Vittoria giocatore:",432,85, red, black);
                     itoa (giocatore, strTmp);
                     grx_text(strTmp,592,85, red, black );
                     mutex_unlock(&mutex);
                     killball ();
                  }
                  if (punteggio[giocatore] == 5 && npc == 2) {
                     mutex_lock(&mutex);
                     grx_text(strTmp,432,120, red, black );
                     grx_text("Pareggio",432,85, red, black);
                     mutex_unlock(&mutex);
                     killball ();
                  }
               }
            }
            else {
               pos[i].x = BALL_XMIN+100;
               pos[i].y = 50;
               pos[i].v = 0;
               pos[i].theta = 0;

               mutex_lock (&delmutex);
               ballexit[i] = 0;
               mutex_unlock (&delmutex);

               bRiposiz = 1;
               flag = 1;
               if (giocatore)
                  giocatore = 0;
               else
                  giocatore = 1;
               bBevuta = 0;

            }
         }

         PosPalla[i].x = pos[i].x;
         PosPalla[i].y = pos[i].y;
         if (pos[i].v >= 0) {
            PosPalla[i].v = pos[i].v;
            if (pos[i].theta > 2*PI )
               PosPalla[i].theta = pos[i].theta - 2*PI;
            else
                if (pos[i].theta < 0 )
                   PosPalla[i].theta = pos[i].theta + 2*PI;
                else
                    PosPalla[i].theta = pos[i].theta;
         }
         else {
            PosPalla[i].v = 0;
            PosPalla[i].theta = 0;
         }
      }

  mutex_unlock(&palmutex);


   }
   else {
        bRiposiz = 1, flag = 1;
        bBevuta = 0;
   }

      task_endcycle();
  }                 // fine ciclo while esterno

}

void inizioPartita () {
   if (!FlagPartita) {
      hardball();
      giocatore = 0;
      punteggio[0] = 0;
      punteggio[1] = 0;
      FlagPartita = 1;
   }
}


void killball() {
   int i;

   bForza = 0;
   mutex_lock (&delmutex);
   for (i=0; i<BALL_MAX_P; i++)
       ballexit[i] = 1;
   mutex_unlock (&delmutex);
   FlagPartita = 0;
}


void assegnaForza(KEY_EVT *k) {
      ch = k->ascii;
}

void movCursore (KEY_EVT *k) {
     curs = k->ascii;
}

/*
void ballfun(KEY_EVT *k)
{
  SOFT_TASK_MODEL mp;
  int r,g,b;
  PID pid;
  char palla_str[]="palla  ";

  soft_task_default_model(mp);
  soft_task_def_level(mp,1);
  soft_task_def_ctrl_jet(mp);
  soft_task_def_arg(mp);
  soft_task_def_group(mp, BALL_GROUP);
  soft_task_def_met(mp, WCET_BALL);
  soft_task_def_period(mp,PERIOD_BALL);
  soft_task_def_usemath(mp);
  pid = task_create(palla_str, palla, &mp, NULL);

  if (pid != NIL) {
    task_activate(pid);
  }
}
*/


// avvio dei task palla
void hardball()
{
   HARD_TASK_MODEL mp;

   PID pid;
   char pallaStr[]="palla   ";
   int i;

   if (npc == BALL_MAX_P) return;

   for(i=0;i<BALL_MAX_P;i++) {

      ballexit[i] = 0;

      itoa(i,pallaStr+6);

      hard_task_default_model(mp);
      hard_task_def_ctrl_jet(mp);
      hard_task_def_arg(mp, (void *)i);
      hard_task_def_wcet(mp, WCET_BALL);
      hard_task_def_mit(mp,PERIOD_BALL);
      hard_task_def_group(mp, BALL_GROUP);
      hard_task_def_usemath(mp);
      pid = task_create(pallaStr, palla, &mp, NULL);

      if (pid == NIL) {
         grx_close();
         perror("Could not create task <pallaEDF>");
              sys_end();
      }
      else {
         npc++;
      }
   }
   group_activate (BALL_GROUP);
}

// avvio del task di contollo
void hardSched()
{
  HARD_TASK_MODEL mp;

  PID pid;

  hard_task_default_model(mp);
  hard_task_def_ctrl_jet(mp);
//  hard_task_def_arg(mp, (void *)1);
  hard_task_def_wcet(mp, WCET_SCHED);
  hard_task_def_mit(mp, PERIOD_SCHED);
  hard_task_def_usemath(mp);
  pid = task_create("Schedular", sched, &mp, NULL);
  if (pid == NIL) {
        grx_close();
        perror("Could not create task <Schedulatore>");
        sys_end();
  }
  else
    task_activate(pid);
}



/*--------------------------------------------------------------*/
/*                      MAIN process                            */
/*--------------------------------------------------------------*/

void scenario_ball()
{
  int i;


//  Margine dello schermo
  grx_rect(0, 0, 639, 479, red);

  grx_line(320,78,639,78,red);
  grx_line(320,0,320,479,red);

//  Tavolo da biliardo
  grx_rect(60,30,260,430,lime);
  for (i=1; i<27; i++) {
        grx_rect(60-i,30-i,260+i,430+i,brown);
  }

// buche del tavolo
  grx_disc(62, 32, RB, black);
  grx_disc(258, 32, RB, black);
  grx_disc(62, 230, RB, black);
  grx_disc(258, 230, RB, black);
  grx_disc(62, 428, RB, black);
  grx_disc(258, 428, RB, black);

  grx_line(320,105,639,105,red);
  grx_line(320,130,639,130,red);
  grx_text("Giocatore:" ,322,110, red, black );
  grx_text("Punteggio:" ,322,120, red, black );

}

void init_ball(void)
{
    KEY_EVT k;

    k.flag = 0;
    k.scan = KEY_I;
    k.ascii = 'i';
    keyb_hook(k,assegnaForza);
    keyb_hook(k,inizioPartita);


/*  intercetta il tasto 'spazio' per passare in modo posizionamento
    e modo forza, mi serve per dare un colpo di stecca  */


    k.flag = 0;
    k.scan = KEY_SPC;
    k.ascii = ' ';
    keyb_hook(k,assegnaForza);

//  inizia una nuova partita
    k.flag = 0;
    k.scan = KEY_BKS;
    k.ascii = ' ';
    keyb_hook(k,killball);

    k.flag = 0;
    k.scan = KEY_X;
    k.ascii = 'x';
    keyb_hook(k,assegnaForza);


    k.flag = 0;
    k.scan = KEY_A;
    k.ascii = 'a';
    keyb_hook(k,assegnaForza);

    k.flag = 0;
    k.scan = KEY_Z;
    k.ascii = 'z';
    keyb_hook(k,assegnaForza);

    k.flag = COD_FRECCIA;
    k.scan = 72;
    k.ascii = 72;
    keyb_hook(k,movCursore);

    k.flag = COD_FRECCIA;
    k.scan = 75;
    k.ascii = 75;
    keyb_hook(k,movCursore);

    k.flag = COD_FRECCIA;
    k.scan = 77;
    k.ascii = 77;
    keyb_hook(k,movCursore);

    k.flag = COD_FRECCIA;
    k.scan = 80;
    k.ascii = 80;
    keyb_hook(k,movCursore);

}

// inizializzzazione task di schedulazione
void initSched(void) {

  hardSched();
}

// inizializzazione delle posizioni delle palle
void setPalla (int num) {

  int nPalla = num;

  nPalla++;

  switch(nPalla) {
    case 1:
                        PosPalla[nPalla-1].x = BALL_XMIN + 100;
                        PosPalla[nPalla-1].y = 50;
         PosPalla[nPalla-1].v = 0;
         PosPalla[nPalla-1].theta = 0;
         PosPalla[nPalla-1].col = white;
    break;
    case 2:
                        PosPalla[nPalla-1].x = BALL_XMIN + 100;
                        PosPalla[nPalla-1].y = 300;
         PosPalla[nPalla-1].v = 0;
         PosPalla[nPalla-1].theta = 0;
         PosPalla[nPalla-1].col = green;
    break;
    case 3:
                        PosPalla[nPalla-1].x = BALL_XMIN + 90;
                        PosPalla[nPalla-1].y = 310;
         PosPalla[nPalla-1].v = 0;
         PosPalla[nPalla-1].theta = 0;
         PosPalla[nPalla-1].col = green;
    break;
    case 4:
                        PosPalla[nPalla-1].x = BALL_XMIN + 110;
                        PosPalla[nPalla-1].y = 310;
         PosPalla[nPalla-1].v = 0;
         PosPalla[nPalla-1].theta = 0;
         PosPalla[nPalla-1].col = green;
    break;
    case 5:
                        PosPalla[nPalla-1].x = BALL_XMIN + 80;
                        PosPalla[nPalla-1].y = 320;
         PosPalla[nPalla-1].v = 0;
         PosPalla[nPalla-1].theta = 0;
         PosPalla[nPalla-1].col = green;
    break;
    case 6:
                        PosPalla[nPalla-1].x = BALL_XMIN + 100;
                        PosPalla[nPalla-1].y = 320;
         PosPalla[nPalla-1].v = 0;
         PosPalla[nPalla-1].theta = 0;
         PosPalla[nPalla-1].col = green;
    break;
    case 7:
                        PosPalla[nPalla-1].x = BALL_XMIN + 120;
                        PosPalla[nPalla-1].y = 320;
         PosPalla[nPalla-1].v = 0;
         PosPalla[nPalla-1].theta = 0;
         PosPalla[nPalla-1].col = green;
    break;
    case 8:
                        PosPalla[nPalla-1].x = BALL_XMIN + 70;
                        PosPalla[nPalla-1].y = 330;
         PosPalla[nPalla-1].v = 0;
         PosPalla[nPalla-1].theta = 0;
         PosPalla[nPalla-1].col = green;
    break;
    case 9:
                        PosPalla[nPalla-1].x = BALL_XMIN + 90;
                        PosPalla[nPalla-1].y = 330;
         PosPalla[nPalla-1].v = 0;
         PosPalla[nPalla-1].theta = 0;
         PosPalla[nPalla-1].col = green;
    break;
    case 10:
                        PosPalla[nPalla-1].x = BALL_XMIN + 110;
                        PosPalla[nPalla-1].y = 330;
         PosPalla[nPalla-1].v = 0;
         PosPalla[nPalla-1].theta = 0;
         PosPalla[nPalla-1].col = green;
    break;
    case 11:
                        PosPalla[nPalla-1].x = BALL_XMIN + 130;
                        PosPalla[nPalla-1].y = 330;
         PosPalla[nPalla-1].v = 0;
         PosPalla[nPalla-1].theta = 0;
         PosPalla[nPalla-1].col = green;
    break;
    default:
                        PosPalla[nPalla-1].x = BALL_XMIN;
                        PosPalla[nPalla-1].y = 0;
         PosPalla[nPalla-1].v = 0;
         PosPalla[nPalla-1].theta = 0;
         PosPalla[nPalla-1].col = green;
    break;
  }

}

// controllo quando una palla finisce in buca
int controlloBuche (float x, float yRel, int i) {

   float y;

   y = BALL_Y - yRel;
   if ((x <= 62+RB && y <= 32+RB) || (x >= 258-RB && y <= 32+RB) ||
      (x <= 62+RB && (y >= 230-RB && y <= 230+RB)) || (x >= 258-RB && (y >= 230-RB && y <= 230+RB)) ||
      (x <= 62+RB && y >= 428-RB) || (x >= 258-RB && y >= 428-RB)){

      // palla in buca
      mutex_lock (&delmutex);
      ballexit[i] = 1;
      mutex_unlock (&delmutex);

      return (1);
   }
   return (0);
}