codice:
/** Funzione NEMICO2 **/
void * nemico2_func(void * arg)
{
pos pos_nemico2;
args *p = (args *)arg;
args pos;
int i = p->i;
int x = p->x;
int y = p->y;
int j;
int dx,dy;
int SOGLIAX;
int SOGLIA_GIU=10*(0+rand()%4)+i*5; // soglia per far scendere il nemico di una riga
int time_giu=0;
int time_bomb=1;
int SOGLIA_BOMB=30+i*(0+rand()%5); // soglia per far sganciare la bomba
pthread_t bomba_id;
pos_nemico2.c='H';
pos_nemico2.xi=x;
pos_nemico2.xf=x+G-1;
pos_nemico2.y=y;
pos_nemico2.p=i;
pos_nemico2.pid=pthread_self();
for(j=0;j<G;j++)
pos_nemico2.nem_vivi[j]=2;
if(!(i%2)) // se il numero assegnato al nemico è pari
{
pos_nemico2.DIRX=1; // vÃ_ a destra
SOGLIAX=MAXX-1; // e la soglia max in x è MAXX-1
}
else // altrimenti
{
pos_nemico2.DIRX=-1; // vÃ_ a sinistra
SOGLIAX=1; // e la soglia max in x è 1
}
sem_wait(&disponibili);
pthread_mutex_lock(&mutex);
buffer[IN] = pos_nemico2;
IN=(IN+1)%BUFFER_DIM;
sem_post(&presenti); // incrementa il semaforo
pthread_mutex_unlock(&mutex);
while(1)
{
if(pos_nemico2.xf>=MAXX-1 || pos_nemico2.xi<=1) // se il nemico sbatte contro una parete laterale
{
pos_nemico2.DIRX*=-1; // cambio la direzione
if(SOGLIAX==MAXX-1) // se la nuova direzione è destra
SOGLIAX=1; // la soglia è MAXX-1
else // altrimenti
SOGLIAX=MAXX-1; // la soglia è 1
}
if(pos_nemico2.DIRX==1) // se la direzione è destra
dx=PASSO; // il suo spostamento sarÃ_ di PASSO
else // altrimenti
dx=-PASSO; // il suo spostamento sarÃ_ di -PASSO
pos_nemico2.xi+=dx; // scriviamo la posizione in x del primo nemico
pos_nemico2.xf+=dx; // scriviamo la posizione in x dell'ultimo nemico
if(!(time_giu%SOGLIA_GIU)) // ad intervalli regolari
{
dy=PASSO; // il nemico avanza di PASSO verso la soglia massima in Y
time_giu=1; // riazzero il contatore
}
else
{
dy=0; // il nemico non avanza verso la soglia massima in Y
time_giu++; // aggiorno il contatore per la discesa del nemico
}
pos_nemico2.y+=dy; // scriviamo la posizione in y del nemico
// aggiorniamo la posizione del nemico e la comunichiamo al controllo
sem_wait(&disponibili);
pthread_mutex_lock(&mutex);
buffer[IN] = pos_nemico2;
IN=(IN+1)%BUFFER_DIM;
sem_post(&presenti); // incrementa il semaforo
pthread_mutex_unlock(&mutex);
if(!(time_bomb%SOGLIA_BOMB)){ // ad intervalli regolari
pos.x = pos_nemico2.x;
pos.y = pos_nemico2.y;
pthread_create(&bomba_id, NULL, &bomba_func, &pos);
//pthread_join(bomba_id, NULL);
}
time_bomb++; // aggiorno il contatore per la bomba
usleep(300000);
} // fine while
} // fine funzione Nemico2
/** Funzione CONTROLLO **/
void * controllo_func(void * arg)
{
pos astronave, missile[2], bomba, nemico[M], nem2[M], valore_letto;
args pos;
int GAME_OVER=0; // se game_over=-1 l'astronave è stata uccisa, se game_over=1 l'astronave ha vinto, se game_over=0 il gioco prosegue
int NEM_VIVI=M+M*G; // segna quanti nemici vivi ci sono
int vita_gruppo[M]; // vettore che indica lo stato di vita del gruppo iesimo
int i,j;
int vite[M][G];
pthread_t nemico2_id[M];
init_pair(1,COLOR_GREEN,COLOR_BLACK);
init_pair(2,COLOR_CYAN,COLOR_BLACK);
init_pair(3,COLOR_YELLOW,COLOR_BLACK);
init_pair(4,COLOR_RED,COLOR_BLACK);
init_pair(5,COLOR_BLUE,COLOR_BLACK);
init_pair(6,COLOR_MAGENTA,COLOR_BLACK);
astronave.x=-1;
for(i=0;i<2;i++)
missile[i].x=-1;
for(i=0;i<M;i++)
{
nemico[i].x=-1;
nemico[i].vita=1;
nem2[i].xf=-1;
nem2[i].vita=2;
vita_gruppo[i]=4;
}
for(i=0;i<M;i++)
for(j=0;j<G;j++)
vite[i][j]=2;
do
{
sem_wait(&presenti);
pthread_mutex_lock(&mutex);
valore_letto = buffer[OUT];
OUT=(OUT+1)%BUFFER_DIM;
sem_post(&disponibili); // incrementa il semaforo
pthread_mutex_unlock(&mutex);
switch(valore_letto.c) {
case '#': /** CASO ASTRONAVE **/
if(astronave.x>=0) // se l'astronave è giÃ_ entrata in scena
{
// cancello la "vecchia" posizione dell'astronave
mvaddch(astronave.y,astronave.x,' ');
}
astronave=valore_letto; // aggiorno la sua nuova posizione
attron(COLOR_PAIR(5));
mvaddch(astronave.y,astronave.x,astronave.c); // e la visualizzo
break;
case '*': /** CASO MISSILE **/
missile[valore_letto.p]=valore_letto; // aggiorno la sua nuova posizione
if(valore_letto.p%2)
mvaddch(missile[valore_letto.p].y+1,missile[valore_letto.p].x-1,' '); //cancello la "vecchia" posizione del missile
else
mvaddch(missile[valore_letto.p].y+1,missile[valore_letto.p].x+1,' '); //cancello la "vecchia" posizione del missile
/** ----------------------------------- Controllo collisioni ----------------------------------- **/
/** missile -> pareti **/
if(missile[valore_letto.p].x>MAXX-1 || missile[valore_letto.p].x<0 || missile[valore_letto.p].y<0) // se il missile raggiunge uno dei bordi laterali o quello superiore
{
mvaddch(missile[valore_letto.p].y,missile[valore_letto.p].x,' '); // lo cancello
pthread_cancel(missile[valore_letto.p].pid); // e uccido il processo
pthread_detach(missile[valore_letto.p].pid); // e libero la memoria
}
else // altrimenti
{
attron(COLOR_PAIR(2));
mvaddch(missile[valore_letto.p].y,missile[valore_letto.p].x,missile[valore_letto.p].c); // lo visualizzo
}
/** missile->nemico **/
for(i=0;i<M;i++)
if((missile[valore_letto.p].x==nemico[i].x)&&(missile[valore_letto.p].y==nemico[i].y)&&nemico[i].vita<1)
{
mvaddch(nemico[i].y,nemico[i].x,' '); // nascondo il nemico colpito
mvaddch(missile[valore_letto.p].y,missile[valore_letto.p].x,' '); // nascondo il missile che ha colpito il nemico
pthread_cancel(nemico[i].pid); // uccido il processo del nemico
pthread_detach(nemico[i].pid); // e libero la memoria
pthread_cancel(missile[valore_letto.p].pid); // uccido il processo del missile
pthread_detach(missile[valore_letto.p].pid); // e libero la memoria
NEM_VIVI--; // decremento il numero dei nemici vivi
nemico[i].vita=0; // metto lo stato di vita del nemico colpito a 0
pos.x = nemico[i].x;
pos.y = nemico[i].y;
pos.i = nemico[i].p;
pthread_create(&nemico2_id[nemico[i].p], NULL, &nemico2_func, &pos);
//pthread_join(nemico2_id[nemico[i].p], NULL);
}
/** missile -> nemico2 **/
for(i=0;i<M;i++) // per ogni nemico di secondo livello
{
if(nem2[i].xf!=-1) // entrato in scena
{
if((missile[valore_letto.p].x>= nem2[i].xi && missile[valore_letto.p].x<=nem2[i].xf) &&(missile[valore_letto.p].y==nem2[i].y)) // controllo se il nemico2 è stato colpito dal nemico
{
j=missile[valore_letto.p].x-nem2[i].xi; // verifico quale nemico del proprio gruppo è stato colpito
if(vite[i][j]>0) // verifico che il nemico abbia ancora vite
{
vite[i][j]--; // decremento il valore delle sue vite
if(vite[i][j]<1) // se il valore delle sue vite è arrivato a zero
{
vita_gruppo[i]--; // la vita del suo gruppo viene decrementata
NEM_VIVI--; // e anche il numero dei nemici vivi
}
} // fine controllo sulla vita del nemico colpito
if(vita_gruppo[i]<1){ // se la vita del gruppo è minore di 1
pthread_cancel(nem2[i].pid); // uccido il thread del gruppo dei nemici di 2° livello
pthread_detach(nem2[i].pid); // e libero la memoria allocata
} // fine controllo sulla vita del gruppo
} // fine controllo sullo scontro missile->nemico2[i]
} // fine controllo sull'entrata in scena del nemico2[i]
} // fine for
break;
case 'H': /** CASO NEMICO2 **/
if(nem2[valore_letto.p].xf>=0)
for(i=0;i<G;i++)
mvaddch(nem2[valore_letto.p].y,nem2[valore_letto.p].xi+i,' '); // cancello la vecchia posizione
nem2[valore_letto.p]=valore_letto; // assegno il nuovo valore al nemico2
for(i=0;i<G;i++)
{
if(vite[valore_letto.p][i]>0) // se il singolo nemico nel gruppo è ancora vivo
{
if(vite[valore_letto.p][i]==2)
attron(COLOR_PAIR(6));
else
attron(COLOR_PAIR(3));
mvaddch(nem2[valore_letto.p].y,nem2[valore_letto.p].xi+i,nem2[valore_letto.p].c); // lo disegno
}
else // altrimenti
mvaddch(nem2[valore_letto.p].y,nem2[valore_letto.p].xi+i,' '); // no
}
/** ----------------------------------- Controllo collisioni ----------------------------------- **/
// nemico2 -> astronave
if(nem2[valore_letto.p].y==astronave.y) // se il nemico raggiunge la linea dell'astronave
{
pthread_cancel(nemico[valore_letto.p].pid); // uccido il nemico2
pthread_detach(nemico[valore_letto.p].pid); // e libero la memoria
pthread_cancel(astronave.pid); // uccido l'astronave
pthread_detach(astronave.pid); // e libero la memoria
GAME_OVER=-1; // l'astronave ha perso
}
break;
(continua...)