[C] problemi gioco space invaders SYSTEM V -urgente!!!!
Inviato: dom lug 16, 2006 10:33 pm
Ciao ragazzi! Ancora una volta alle prese con lo stesso gioco ma con un diverso esercizio...
E' un programmino didattico: sarebbe una emulazione del gioco di space invaders (ma molto grezzo!),con grafica scarna.
Il programma è quasi analogo al classico problema dei "produttori-consumatori": creo dei processi, che accedono ad un buffer condiviso (protetto da semafori), basandomi sulle librerie lpthread e lncurses, utilizzando il sistema comunicazione interprocesso delle System V di linux.
Ho creato un sistema iniziale ma non capisco come mai quando sparo le bombe della navetta con il tasto "spazio" i processi della nave vengono duplicati e non funziona la funzione (scusate la ripetizione!) di collisione delle bombe nave con gli alieni..
Potete darmi una mano per favore? Ecco il codice, Grazie
E' un programmino didattico: sarebbe una emulazione del gioco di space invaders (ma molto grezzo!),con grafica scarna.
Il programma è quasi analogo al classico problema dei "produttori-consumatori": creo dei processi, che accedono ad un buffer condiviso (protetto da semafori), basandomi sulle librerie lpthread e lncurses, utilizzando il sistema comunicazione interprocesso delle System V di linux.
Ho creato un sistema iniziale ma non capisco come mai quando sparo le bombe della navetta con il tasto "spazio" i processi della nave vengono duplicati e non funziona la funzione (scusate la ripetizione!) di collisione delle bombe nave con gli alieni..
Potete darmi una mano per favore? Ecco il codice, Grazie
- Codice: Seleziona tutto
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <sys/signal.h>
#include <setjmp.h>
#include <stdlib.h>
#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <curses.h>
#include <time.h>
#define RMODE 0644
#define WMODE 0666
#define NUM_MAX_RIGHE 5
#define SINISTRA 68
#define DESTRA 67
#define N_INIZIALE_ALIENI 10
#define SPAZIO 3
#define SPAZIO_RIGHE 1
#define PASSO_X 2
#define PASSO_Y 1
#define BUFFER_DIM 10
#define MAX_BOMBE_NAVE 5
#define MAX_BOMBE_ALIENO N_INIZIALE_ALIENI * 2
struct pos {
char *c;
int x;
int y;
int index;
int xPrec;
int yPrec;
int pid;
};
int empty, full, mutex, buffer_id, mutexBombeNave, mutexBombeAlieni, livello;
key_t empty_t, full_t, mutex_t, mutex_nave, mutex_alieni; // le zone di memoria dei due semafori e del semaforo-mutex
void scrittore(struct pos *, struct pos );
void lettore(struct pos *);
void crea_proc(int, int);
void bomba(struct pos, struct pos *, int *);
void creaBomba(struct pos);
void sparaBomba(struct pos);
bool collisione_alieni(int);
bool collisione_nave(int);
// buffer che poi verrà condiviso //
struct BUF {
struct pos *info_elementi[BUFFER_DIM];
struct pos info_alieno[N_INIZIALE_ALIENI];
struct pos info_nave;
struct pos bombe_nave[MAX_BOMBE_NAVE];
struct pos bombe_alieno[MAX_BOMBE_ALIENO];
int vitaAlieni[N_INIZIALE_ALIENI];
int vitaNave;
int vitaBombeNave[MAX_BOMBE_NAVE];
int vitaBombeAlieno[MAX_BOMBE_ALIENO];
int in;
int out;
bool esci;
int posDisponibileAlieno;
int posDisponibileNave;
int nBombeNaveResidue;
int nBombeAlienoResidue;
} * bufferpointer;
union semun {
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;};
/* Function MutexCreate : create a mutex / semaphore */
int MutexCreate ( key_t ipc_key )
{
const union semun semunion={1}; /* semaphore union structure: mutex must be initialized with 1*/
int sem_id , ret;
sem_id = semget ( ipc_key , 1 , IPC_CREAT | WMODE); /* get semaphore ID */
if ( sem_id == -1) { /* if error return code */
return sem_id ;
}
ret = semctl (sem_id , 0 , SETVAL , semunion ); /* init semaphore */
if ( ret == -1) {
return ret;
}
return sem_id ;
}
/* Define sembuf structures to lock and unlock the mutex or to create wait and signal for semaphores */
struct sembuf sem_lock_or_wait ={ /* to lock mutex or wait for semaphore */
0, /* semaphore number ( only one so 0) */
-1, /* operation ( -1 to use resource ) */
SEM_UNDO }; /* flag ( set for undo at exit ) */
struct sembuf sem_ulock_or_signal ={ /* to unlock mutex or post a signal for semaphore */
0, /* semaphore number ( only one so 0) */
1, /* operation (1 to release resource ) */
SEM_UNDO }; /* flag ( in this case 0) */
/* Function Lock_Wait : to lock a mutex or wait for semaphore */
int Lock_Wait (int sem_id )
{
return semop (sem_id , & sem_lock_or_wait , 1);
}
/* Function Unlock_Signal : to unlock a mutex or signal for semaphore */
int Unlock_Signal (int sem_id )
{
return semop (sem_id , & sem_ulock_or_signal , 1);
}
/* Function SemRemove : remove a mutex / semaphore */
int SemRemove (int sem_id )
{
return semctl (sem_id , 0 , IPC_RMID );
}
void alieni(int index, int xIniz, int yIniz)
{
int i;
bufferpointer=(struct BUF *) shmat ( buffer_id , NULL , 0) ; // Attachment al buffer condiviso
struct pos pos_alieno, pos_bomba;
int dx, dy;
pos_alieno.x = xIniz * (SPAZIO + 1);
pos_alieno.y = yIniz * (SPAZIO_RIGHE + 1);
pos_alieno.c = "#";
pos_alieno.index = index;
pos_alieno.pid = getpid();
srand(pos_alieno.pid); //inizializziamo il generatore random
int dir = 1;
while(!bufferpointer->esci && bufferpointer->vitaAlieni[index])
{
pos_alieno.pid = getpid();
pos_alieno.yPrec = pos_alieno.y;
pos_alieno.xPrec = pos_alieno.x;
dx = PASSO_X * dir;
dy = 0;
if (pos_alieno.x + dx >= COLS -1 || pos_alieno.x + dx <= 0)
{
if(dir > 0)
pos_alieno.x = COLS - 1;
else
pos_alieno.x = 0;
dir = -dir;
dx = PASSO_X * dir;
dy = PASSO_Y;
}
pos_alieno.x += dx;
pos_alieno.y += dy;
scrittore(&bufferpointer->info_alieno[pos_alieno.index], pos_alieno);
double t = clock();
if((rand() % 100) >= 99 - 1) // 1 qui equivale al livello....da aggiornare!
{
Lock_Wait(mutexBombeAlieni);
if(bufferpointer->nBombeAlienoResidue > 0)
{
bufferpointer->nBombeAlienoResidue--;
bufferpointer->posDisponibileAlieno = (bufferpointer->posDisponibileAlieno + 1) % MAX_BOMBE_ALIENO;
pos_bomba.index = bufferpointer->posDisponibileAlieno;
pos_bomba.x = pos_bomba.xPrec = pos_alieno.x;
pos_bomba.y = pos_alieno.y + 1;
pos_bomba.c = "!";
creaBomba(pos_bomba);
}
Unlock_Signal(mutexBombeAlieni);
}
t = 1000000 - (clock() - t);
usleep(t);
}
shmdt (bufferpointer); //Detachment del buffer condiviso
shmctl (buffer_id, IPC_RMID , NULL); //Deallocazione del buffer condiviso
}
void nave()
{
bufferpointer=(struct BUF *) shmat (buffer_id , NULL , 0) ; // Attachment al buffer condiviso
struct pos pos_nave;
struct pos pos_bomba;
pos_nave.c = "^";
pos_nave.x = COLS / 2;
pos_nave.yPrec = pos_nave.y = LINES - 1;
pos_nave.index = 1; //per ora è inutile...
scrittore(&bufferpointer->info_nave, pos_nave);
while(!bufferpointer->esci && bufferpointer->vitaNave)
{
char c;
pos_nave.xPrec = pos_nave.x;
switch(c = getch())
{
case SINISTRA: if(pos_nave.x > 1) pos_nave.x -= 1;
break;
case DESTRA: if(pos_nave.x < COLS - 1) pos_nave.x += 1;
break;
case 'q': bufferpointer->esci = true;
break;
case ' ':
Lock_Wait(mutexBombeNave);
if(bufferpointer->nBombeNaveResidue > 0)
{
bufferpointer->nBombeNaveResidue--;
bufferpointer->posDisponibileNave = (bufferpointer->posDisponibileNave + 1) % MAX_BOMBE_NAVE;
pos_bomba.index = bufferpointer->posDisponibileNave;
pos_bomba.x = pos_bomba.xPrec = pos_nave.x;
pos_bomba.y = LINES - 2;
pos_bomba.c = "o";
creaBomba(pos_bomba);
}
Unlock_Signal(mutexBombeNave);
}
if (c == DESTRA || c == SINISTRA)
{
scrittore(&bufferpointer->info_nave, pos_nave);
}
}
shmdt(bufferpointer); //Detachment
shmctl(buffer_id, IPC_RMID , NULL);//Deallocazione
}
void creaBomba(struct pos pos_bomba)
{
switch(fork()) {
case -1: printf("Errore fork!");
break;
case 0:sparaBomba(pos_bomba);
break;
default: return;
}
}
void sparaBomba(struct pos pos_bomba)
{
pos_bomba.pid = getpid();
struct pos *posizione;
int *posizioneVita;
if(pos_bomba.c == "!") // è un alieno?
{
Lock_Wait(mutexBombeAlieni);
posizione = &bufferpointer->bombe_alieno[bufferpointer->posDisponibileAlieno];
posizioneVita = &bufferpointer->vitaBombeAlieno[bufferpointer->posDisponibileAlieno];
*posizioneVita = 1;
Unlock_Signal(mutexBombeAlieni);
bomba(pos_bomba, posizione, posizioneVita);
Lock_Wait(mutexBombeAlieni);
bufferpointer->nBombeAlienoResidue++;
Unlock_Signal(mutexBombeAlieni);
}
else
if(pos_bomba.c == "o") //è una nave?
{
Lock_Wait(mutexBombeNave);
posizione = &bufferpointer->bombe_nave[bufferpointer->posDisponibileNave];
posizioneVita = &bufferpointer->vitaBombeAlieno[bufferpointer->posDisponibileAlieno];
*posizioneVita = 1;
Unlock_Signal(mutexBombeNave);
bomba(pos_bomba, posizione, posizioneVita);
Lock_Wait(mutexBombeNave);
bufferpointer->nBombeNaveResidue++;
Unlock_Signal(mutexBombeNave);
}
}
void bomba(struct pos pos_bomba, struct pos *posizione, int *posVita)
{
int limite = (pos_bomba.c == "!") ? LINES - 1 : 0;
int dir = (pos_bomba.c == "!") ? 1 : -1;
scrittore(posizione, pos_bomba);
while(pos_bomba.y != limite && *posVita)
{
usleep(100000);
pos_bomba.yPrec = pos_bomba.y;
pos_bomba.y += dir;
scrittore(posizione,pos_bomba);
}
pos_bomba.c = " ";
scrittore(posizione, pos_bomba);
}
void controllo()
{
struct pos valore_letto;
int nAlieni = N_INIZIALE_ALIENI;
int statoGioco = 0;
int punteggio = 0;
int puntiKiller = 10;
int dimAlieni = 1;
int nAlieniRiga = COLS / (dimAlieni + SPAZIO);
bufferpointer=(struct BUF *) shmat ( buffer_id , NULL , 0) ; // Attachment al buffer condiviso
livello = 1;
do {
statoGioco = 1;
do {
lettore(&valore_letto);
if(valore_letto.c == "#")
{
if(valore_letto.y == bufferpointer->info_nave.y - SPAZIO_RIGHE)
{
bufferpointer->vitaNave--;
bufferpointer->info_nave.xPrec = bufferpointer->info_nave.x;
bufferpointer->info_nave.x = LINES / 2;
statoGioco = -1;
}
}
else
if(valore_letto.c == "o")
{
if (collisione_alieni(valore_letto.index))
{
punteggio += puntiKiller;
nAlieni--;
if(nAlieni == 0) statoGioco = 0;
valore_letto.c = " ";
}
}
else
if(valore_letto.c == " ")
{
if(collisione_nave(valore_letto.index))
{
bufferpointer->vitaNave--;
bufferpointer->info_nave.xPrec = bufferpointer->info_nave.x;
bufferpointer->info_nave.x = LINES / 2;
statoGioco = -1;
valore_letto.c = "^";
}
}
move(valore_letto.yPrec, valore_letto.xPrec);
printw(" ");
move(valore_letto.y, valore_letto.x);
printw("%s",valore_letto.c);
move(0,0); // colloca nelle coordinate 0,0 il punteggio
printw("Punteggio %d",punteggio);
move(0,15);
printw("\tlivello %d",livello);
move(0,27);
printw("\tvite %d",bufferpointer->vitaNave);
move(1,0);
printw("nAlieni %d",nAlieni);
refresh();
}
while (statoGioco > 0 && !bufferpointer->esci);
if(statoGioco == -1) //vita persa
{
move(COLS - 10, 0);
printw("Vita Persa!!!!");
refresh();
usleep(1000000);
move(COLS - 10, 0);
deleteln(); //cancella vita persa
insertln();
move(bufferpointer->info_nave.y, bufferpointer->info_nave.x);
printw(" ");
refresh();
}
else if(statoGioco == 0)
{
livello++;
nAlieni = N_INIZIALE_ALIENI;
crea_proc(0, nAlieniRiga);
}
}
while(bufferpointer->vitaNave > 0 && !bufferpointer->esci);
shmdt (bufferpointer);
shmctl (buffer_id, IPC_RMID , NULL );
}
bool collisione_alieni(int index)
{
int i;
int status;
for(i=0; i< N_INIZIALE_ALIENI; i++)
{
Lock_Wait(mutex);
if(bufferpointer->bombe_nave[index].x == bufferpointer->info_alieno[i].x && bufferpointer->bombe_nave[index].y == bufferpointer->info_alieno[i].y && bufferpointer->vitaAlieni[i] && bufferpointer->vitaBombeNave[index])
{
bufferpointer->vitaAlieni[i] -= 1;
bufferpointer->vitaBombeNave[index] -= 1;
if (bufferpointer->vitaAlieni[i] == 0)
{
kill(bufferpointer->info_alieno[i].pid, 1);
}
if (bufferpointer->vitaBombeNave[index] == 0)
{
kill(bufferpointer->bombe_nave[index].pid, 1);
}
return true;
}
Unlock_Signal(mutex);
}
return false;
}
bool collisione_nave(int index)
{
return(bufferpointer->bombe_alieno[index].x == bufferpointer->info_nave.x && bufferpointer->bombe_alieno[index].y == LINES - 1);
}
void crea_proc(int n, int nAlieniRiga)
{
int i,j;
i = n % nAlieniRiga;
j = (n / nAlieniRiga) + 1;
switch(fork())
{
case -1: printf("Errore nell'esecuzione della fork");
case 0: alieni(n, i, j);
break;
default:if (n < N_INIZIALE_ALIENI - 1)
crea_proc(n + 1, nAlieniRiga);
}
}
void scrittore(struct pos *posizione, struct pos item)
{
Lock_Wait(empty);
Lock_Wait(mutex);
bufferpointer->info_elementi[bufferpointer->in] = posizione;
*posizione = item;
bufferpointer->in = (bufferpointer->in + 1) % BUFFER_DIM;
Unlock_Signal(mutex);
Unlock_Signal(full);
}
void lettore(struct pos *item)
{
Lock_Wait(full); //Segnala che è stata letta una posizione dal buffer
Lock_Wait(mutex);
*item = *bufferpointer->info_elementi[bufferpointer->out];
bufferpointer->out = (bufferpointer->out + 1) % BUFFER_DIM;
Unlock_Signal(mutex);
Unlock_Signal(empty);
}
int dimAlieni = 1;
int main()
{
union semun arg1, arg2; // argomento per semctl per indicare il valore del semaforo
int i;
initscr();
noecho();
curs_set(0);
// creazione semaforo empty //
if ((empty = semget(empty_t, 1, IPC_CREAT | IPC_EXCL | WMODE)) == (-1))
printf("Errore semaforo empty\n");
// inizializzazione del semaforo empty con la dimensione del buffer //
arg1.val = BUFFER_DIM;
semctl (empty, 0, SETVAL, arg1);
// creazione semaforo full //
if ((full = semget(full_t, 1, IPC_CREAT | IPC_EXCL | WMODE)) == (-1))
printf("Errore semaforo full\n");
// inizializzazione del semaforo full a zero //
arg2.val = 0;
semctl (full, 0, SETVAL, arg2);
// creazione del mutex //
mutex=MutexCreate(mutex_t);
mutexBombeNave = MutexCreate(mutex_nave);
mutexBombeAlieni = MutexCreate(mutex_alieni);
// creazione della memoria condivisa per il buffer //
buffer_id = shmget ( IPC_PRIVATE , sizeof(struct BUF) , IPC_CREAT | IPC_EXCL | WMODE ); /* Ottiene l'ID della Shared memory */
bufferpointer=(struct BUF *) shmat ( buffer_id , NULL , 0) ; // Attachment al buffer condiviso
Lock_Wait(mutex);
bufferpointer->in = 0;
bufferpointer->out = 0;
bufferpointer->vitaNave = 3;
for(i = 0;i < N_INIZIALE_ALIENI; i++)
bufferpointer->vitaAlieni[i] = 1;
bufferpointer->posDisponibileAlieno = 0;
bufferpointer->posDisponibileNave = 0;
bufferpointer->nBombeNaveResidue = MAX_BOMBE_NAVE;
bufferpointer->nBombeAlienoResidue = MAX_BOMBE_ALIENO;
Unlock_Signal(mutex);
shmdt(bufferpointer);
int nAlieniRiga = COLS / (dimAlieni + SPAZIO);
pid_t pid;
int status; // conterra' lo stato
crea_proc(0, nAlieniRiga);
switch(fork()){
case 0:nave();
break;
default:controllo();
break;
}
SemRemove(empty);
SemRemove(full);
SemRemove(mutex);
SemRemove(mutexBombeNave);
SemRemove(mutexBombeAlieni);
clear();
endwin();
wait(&status);
exit(0);
}