ciao a tutti!Io e la mia collega abbiamo un nuovo problema da risolvere. Dobbiamo fare una versione di Space Invaders utilizzando la SystemV con i semafori. Il problema č che i nemici non si muovono in modo fluido, vanno a scatti e non capiamo dove stiamo sbagliando..potete aiutarci? grazie anticipatamente!
codice:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <curses.h>
#include <signal.h>
#include <semaphore.h>
#include <unistd.h>
#define PASSO 1 //entita' dello spostamento del nemico
#define SINISTRA 68 // freccia sx
#define DESTRA 67 // freccia dx
#define SGANCIA 32 // spazio
#define MAXX 80 // numero di colonne dello schermo
#define MAXY 24 // numero di righe dello schermo
#define M 3 // numero di nemici di 1° livello
#define G 4 // numero di nemici di 2° livello per gruppo
/* chiavi per l'identificazione dei segmenti di memoria da creare */
key_t mem_key; // chiave memoria
key_t sem_key; // chiave set di semafori
/* identificatori per i segmenti di memoria allocati */
int seg_mem; // identificatore segmento di memoria
int semid; // identificatore set di semafori
/* Struttura union semun */
union semun {
int val; // per SETVAL
struct semid_ds *buf; // per IPC_STAT e IPC_SET
unsigned short *array; // per GETALL e SETALL
struct seminfo * __buf ; /* buffer for IPC_INFO */
};
/* Struttura per la comunicazione fra figli e padre */
typedef struct pos
{
char c; // soggetto che invia il dato: astronave, nemico, bomba o missile
int x; // coordinata x
int xi; // coordinata x del primo nemico di secondo livello
int xf; // coordinata x dell'ultimo nemico di secondo livello
int y; // coordinata y
int DIRX; // direzione del nemico di 2° livello
int p; // posizione del nemico all'interno del vettore v[] che rappresenta il gruppo di nemici di primo livello
int pid; // pid del processo
int vita; // 0: il nemico č morto; 1: il nemico č vivo
int nem_vivi[G]; // vettore che indica lo stato di vita dei nemici di secondo livello all'interno di ciascun gruppo
int g; // rappresenta il numero del gruppo a cui appartiene il nemico di secondo livello
int n; // rappresenta il numero assegnato al nemico di 2° livello all'interno del proprio gruppo
} pos;
/* Puntatori alla memoria condivisa */
pos* pos_mem;
/* Prototipi funzioni */
void astronave ();
void missile (int i, int x1, int y1);
void nemico(int i);
void nemico2(int i,int x, int y);
void bomba(int x1, int y1);
void sem_iniz(int semaforino);
void wait_sem(int semaforino);
void post_sem(int semaforino);
void controllo();
void gestione_mem();
void libera_mem();
main()
{
initscr(); // inizializzazione dello schermo
start_color(); // per l'utilizzazione dei colori
noecho(); // i caretteri corrispondenti ai tasti premuti non saranno visualizzati sullo schermo del terminale
curs_set(0); // nasconde il cursone
int pid_astronave, pid_nemico, i;
/* Chiamate per l'inizializzazione della memoria condivisa e dei semafori */
gestione_mem();
sem_iniz(0);
/* Creazione processi */
switch(pid_astronave=fork()) {
case -1: perror("Errore nell'esecuzione della fork astronave");
exit(1);
case 0: astronave();
}
for(i=0;i<M;i++)
{
switch(pid_nemico=fork()) {
case -1: perror("Errore nell'esecuzione della fork nemico");
exit(1);
case 0: nemico(i);
}
}
controllo();
libera_mem();
/** Siamo usciti dal controllo e si terminano i procssi figli. Ripristina il normale modo operativo dello schermo **/
endwin();
return(0);
}
/**Funzione GESTIONE_MEM - per la gestione della memoria **/
void gestione_mem()
{
int i;
/* creazione delle chiavi per i segmenti di memoria e per il set di semafori */
if((mem_key = ftok(".",0)) == -1) {
perror ("\nErrore ftok memoria!");
exit (1);
}
if((sem_key = ftok(".",1)) == -1) {
perror ("\nErrore ftok set di semafori!");
exit (1);
}
/* Allocazione dei segmenti di memoria condivisa e del set di semafori */
if((seg_mem = shmget(mem_key,sizeof(pos),IPC_CREAT | 0666)) < 0) {
perror ("Errore shmget memoria!");
exit (1);
}
if((semid = semget(sem_key,1,IPC_CREAT | 0600)) < 0) {
perror ("Errore semget set di semafori!");
exit (1);
}
/* Attachment dei segmenti di memoria */
if((int) (pos_mem = shmat(seg_mem, NULL, SHM_RND)) == -1) {
perror ("Errore shmat memoria!");
exit (1);
}
} // fine funzione GESTIONE_MEM
/** Funzione SEM_INIZ - per l'inizializzazione dei semaforini **/
void sem_iniz(int semaforino)
{
union semun arg;
unsigned short values[2];
values[0] = 1;
values[1] = 0;
arg.array = values;
if(semctl(semid,semaforino,SETALL,arg) == -1) {
perror ("Errore semctl semaforino!");
exit (1);
}
} // fine funzione SEM_INIZ
/** Funzione WAIT_SEM **/
void wait_sem(int semaforino)
{
struct sembuf op[1];
op[0].sem_num = semaforino;
op[0].sem_op = -1;
op[0].sem_flg = SEM_UNDO;
semop(semid,op,1);
} // fine funzione WAIT_SEM
/** Funzione POST_SEM **/
void post_sem(int semaforino)
{
struct sembuf op[1];
op[0].sem_num = semaforino;
op[0].sem_op = 1;
op[0].sem_flg = SEM_UNDO;
semop(semid,op,1);
} // fine funzione POST_SEM
/** Funzione LIBERA_MEM - per il detachment e la deallocazione dei segmenti di memoria **/
void libera_mem()
{
/* Detachment dei segmenti di memoria*/
if(shmdt(pos_mem) == -1) {
perror ("Errore shmdt memoria!");
exit (1);
}
/* Deallocazione dei segmenti di memoria e del semaforo */
if(shmctl(seg_mem,IPC_RMID,0) == -1) {
perror ("Errore deallocazione nemico di primo livello!");
exit (1);
}
if(semctl(semid,1,IPC_RMID) == -1) {
perror ("Errore deallocazione semaforo!");
exit (1);
}
} // fine funzione LIBERA_MEM
/** Funzione ASTRONAVE **/
void astronave ()
{
pos pos_astronave;
int pid_missile[2]; // l'astronave spara contemporaneamente due missili:uno a destra e uno a sinistra
int i;
pos_astronave.c='#';
pos_astronave.x=MAXX/2;
pos_astronave.y=MAXY-1;
pos_astronave.pid=getpid();
wait_sem(0);
*pos_mem = pos_astronave;
post_sem(1);
while(1)
{
char c;
switch(c=getch()) { //gestione movimento o sgancio dei missili da parte dell'astronave
case SINISTRA: if(pos_astronave.x>0)
pos_astronave.x-=1;
break;
case DESTRA: if(pos_astronave.x<MAXX-1)
pos_astronave.x+=1;
break;/*
case SGANCIA: for(i=0;i<2;i++)
switch(pid_missile[i]=fork()) {
case -1: perror("Errore nell'esecuzione della fork");
exit(1);
case 0: missile(pipeout,i,pos_astronave.x,pos_astronave.y);
}
break;*/
} // fine switch gestione movimento
wait_sem(0);
*pos_mem = pos_astronave;
post_sem(1);
}
} // fine Funzione Astronave
/** Funzione NEMICO **/
void nemico(int i)
{
pos pos_nemico;
int dx,dy; // spostamenti in x e y;
int SOGLIAX; // soglia oltre la quale il nemico non puō andare - puō essere 1 o MAXX-1
int DIRX; // direzione in x - se dirx=1 vā a destra, se dirx=-1 va a sinistra
int time_giu=0; // contatore per far scendere il nemico
int SOGLIA_GIU=10*(0+rand()%4)+i*5; // soglia per far scendere il nemico di una riga
int time_bomb=1; // contatore per far sganciare una bomba
int SOGLIA_BOMB=30+i*(0+rand()%5); // soglia per far sganciare la bomba
int pid_bomba;
pos_nemico.c='$';
pos_nemico.p=i;
pos_nemico.pid=getpid();
pos_nemico.y=1; // i nemici partono tutti sulla stessa riga
pos_nemico.x=9+(i*20); // ma distanziati
if(!(i%2)) // se il numero assegnato al nemico č pari
{
DIRX=1; // vā a destra
SOGLIAX=MAXX-1; // e la soglia max in x č MAXX-1
}
else // altrimenti
{
DIRX=-1; // vā a sinistra
SOGLIAX=1; // e la soglia max in x č 1
}
wait_sem(0);
*pos_mem = pos_nemico;
post_sem(1);
while(1)
{
if(pos_nemico.x==SOGLIAX) // se il nemico sbatte contro una parete laterale
{
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(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_nemico.x+=dx; // scriviamo la posizione in x del 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_nemico.y+=dy; // scriviamo la posizione in y del nemico
// aggiorniamo la posizione del nemico e la comunichiamo al controllo
wait_sem(0);
*pos_mem = pos_nemico;
post_sem(1);
/*
if(!(time_bomb%SOGLIA_BOMB)) // ad intervalli regolari
switch(pid_bomba=fork()) { // il nemico sgancia la bomba
case -1: perror("Errore nella creazione del processo bomba");
exit(1);
case 0: bomba(pipeout,pos_nemico.x,pos_nemico.y);
}
time_bomb++; // aggiorno il contatore per la bomba
*/
usleep(300000);
} // fine while;
} // fine Funzione Nemico
(continua)