Blame |
Last modification |
View Log
| RSS feed
/*--------------------------------------------------------------*/
/* GIUOCO DEL PING - PONG */
/*--------------------------------------------------------------*/
#include <kernel/kern.h>
#include <drivers/glib.h>
#include <drivers/keyb.h>
#include <semaphore.h>
#include <stdlib.h>
#include <math.h>
#include <drivers/mouse.h>
#define YMENU 10 /* menu level */
#define XMIN 50
#define XMAX 600
#define YMIN 100
#define YMAX 450
#define D 3 /* raggio pallina */
#define ESC 27 /* ASCII code of ESCAPE key */
#define FLYGROUP 1
#define sinistra 1
#define destra 0
double tick
= 1.0; /* system tick = 1 ms */
int fly_period
= 40000; /* task period */ /*Siamo a circa 25Hz --> ok per l'occhio umano*/
int avv_period
= 40000; /* task period */ /*Siamo a circa 25Hz --> ok per l'occhio umano*/
int fly_wcet
= 5000; /* task wcet pallina *//*12000 ok per un PIII a 450 MHz*//*700 ok per Athlon Xp 2000+*/
int avv_wcet
=3000; /*task wcet avversario*/ /*1000 ok per un PIII a 450 MHz*//*200 ok per Athlon Xp 2000+*/
PID pid
,pid_av
;
sem_t mutex_av
,mutex_gi
; //semafori per mutua avversario e giocatore
int indice
=0; //controllo per numero palline lanciate
float inerzia_av
=0.3; //incremento passo avversario
int veloc_pallina
=8; //velocità pallina
int punteggio
=0;
int vmax_av
=10; //velocità massima avversario
char s2
[100]; //scrittura punteggio su monitor
float passo
=0;//passo avversario
/*Nella struttura dati condivisa sono elencate quelle varabili che, trovandosi in sezione critica, devono essere utilizzate in mutua esclusione per garantire la perfetta funzionalità del programma. */
struct dati_condivisi
{
int x
; //coordinata della pallina
int y
; //coordinata della pallina
int yvecchio
;//coordinate del mouse per cancellare il cursore giocatore
int xvecchio
;//coordinate del mouse per cancellare il cursore giocatore
int yattuale
;//coordinate del mouse per disegnare il cursore giocatore
int xattuale
;//coordinate del mouse per disegnare il cursore giocatore
int yvecchio_av
;//coordinate del mouse per cancellare il cursore avversario
int xvecchio_av
;//coordinate del mouse per cancellare il cursore avversario
int yattuale_av
;//coordinate del mouse per disegnare il cursore avversario
int xattuale_av
;//coordinate del mouse per disegnare il cursore avversario
int direzione_mouse
; /*mouse proveniente da destra o sinistra per rilanciare la pallina nella stessa direzione*/
} str_cond
;
void my_mouse_handler
(MOUSE_EVT
*m
)
{ sem_wait
(&mutex_gi
);
/*Calcolo direzione di provenienza del cursore giocatore*/
if (m
->x
> str_cond.
xattuale) str_cond.
direzione_mouse =destra
;
if (m
->x
< str_cond.
xattuale) str_cond.
direzione_mouse=sinistra
;
/*scrittura delle coordinate del mouse nella struttura dati*/
str_cond.
xattuale=m
->x
;
str_cond.
yattuale=m
->y
;
/*disegno del cursore*/
grx_box
(str_cond.
xvecchio,str_cond.
yvecchio,str_cond.
xvecchio+50,str_cond.
yvecchio+15,BLACK
);
grx_box
(m
->x
,m
->y
,m
->x
+50,m
->y
+15,RED
);
str_cond.
xvecchio=m
->x
;
str_cond.
yvecchio=m
->y
;
sem_post
(&mutex_gi
);
}
/*--------------------------------------------------------------*/
void draw_fly
(int x
, int y
, int c
)
{
grx_disc
(x
, y
, D
, c
);
}
/******************************************************************/
TASK avversario
(void *arg
)
{
while (1){
sem_wait
(&mutex_av
);
/*Inseguimento traiettoria pallina con con simulazione inerzia*/
if ((str_cond.
xattuale_av + 25) < str_cond.
x)
{
passo
= passo
+ inerzia_av
;
if (passo
>=vmax_av
) //limite velocità avversario
{passo
=vmax_av
;}
str_cond.
xattuale_av += passo
;//incremento passo avversario
}
if ((str_cond.
xattuale_av + 25) > str_cond.
x)
{
passo
=passo
- inerzia_av
;
if (passo
<= -vmax_av
)
{
passo
=-vmax_av
;
}
str_cond.
xattuale_av += passo
;
}
/* CONTROLLO SULLO SFONDAMNETO DEI BORDI DELL'AVVERSARIO*/
if (str_cond.
xattuale_av < (XMIN
+2))
{
str_cond.
xattuale_av = XMIN
+2;
passo
=0;
}
if (str_cond.
xattuale_av > (XMAX
-52))
{
str_cond.
xattuale_av = XMAX
-52;
passo
=0;
}
/*disegno del cursore avversario*/
grx_box
(str_cond.
xvecchio_av,str_cond.
yvecchio_av,str_cond.
xvecchio_av+50,str_cond.
yvecchio_av+15,BLACK
);
grx_box
(str_cond.
xattuale_av,str_cond.
yattuale_av,str_cond.
xattuale_av+50,str_cond.
yattuale_av+15,YELLOW
);
str_cond.
yvecchio_av = str_cond.
yattuale_av;
str_cond.
xvecchio_av = str_cond.
xattuale_av;
sem_post
(&mutex_av
);
task_endcycle
();
}
}
/*task pallina*/
TASK fly
(void *arg
)
{
int timer
=0;//contatore pausa prima del rilancio pallina
int xold
;//per controllo direzione provenienza pallina (destra - sinistr)
int direzione
;//direzione provenienzaa pallina (destra - sinistra)
int ox
, oy
;// coordinate per cancellare la pallina
int dx
, dy
;//passo della pallina
int col
;//colore pallina
double r
;//angolo iniziale per lancio pallina
int i
= (int)arg
;
r
= rand()%(120) + 30; /* angolo iniziale random*/
grx_text
("GIUOCO DEL PING-PONG ", XMIN
, YMENU
+10, 13, 0);
grx_text
("SPACE TO LUNCH A BALL " , XMIN
, YMENU
+20, 12, 0);
grx_text
("ESC exit to DOS " , XMIN
, YMENU
+30, 12, 0);
grx_text
(" ", XMIN
, YMENU
+40, 12, 0);
punteggio
=0;
str_cond.
x = ox
= (XMIN
+XMAX
)/2;
str_cond.
y = oy
= (YMIN
+YMAX
)/2;
col
= 2 + i
; /* colore pallina */
dx
= 5;
dy
= 5;
dx
= (int)(veloc_pallina
* cos(r
*PI
/180));
dy
= (int)(veloc_pallina
* sin(r
*PI
/180));
while (1) {
sem_wait
(&mutex_av
);
sem_wait
(&mutex_gi
);
/*timer per pausa pallina se l'avversario subisce goal*/
timer
--;
if (timer
< 0) timer
=0;
/*Per calcolare la provenienza della pallina utile per il rimbalzo sull'avversario*/
xold
=str_cond.
x;
/*calcolo nuova posizione della pallina*/
str_cond.
x = str_cond.
x + dx
;
str_cond.
y = str_cond.
y + dy
;
/*controllo provenienza pallina*/
if (xold
< str_cond.
x)
{
direzione
=sinistra
;
}
else direzione
=destra
;
/*Game over: se il giocatore subisce goal*/
if (str_cond.
y >= YMAX
-4)
{
indice
--;//do la possibilità di lanciare una nuova pallina
/*ripristino valori iniziali*/
inerzia_av
=0.3;
veloc_pallina
= 8;
draw_fly
(ox
, oy
, 0);
vmax_av
=10;
/*rilascio i semafori presi*/
sem_post
(&mutex_gi
);
sem_post
(&mutex_av
);
break;
}
/*gol subito dall'avversario*/
if (str_cond.
y <= YMIN
+4)
{
veloc_pallina
++;
punteggio
++;
timer
=50;/*timer per pausa dopo il goal*/
if (punteggio
== 18) vmax_av
= 11;
grx_text
("IL TUO PUNTEGGIO E' ", XMIN
, YMENU
+40, WHITE
, 0);
sprintf(s2
,"%3d",punteggio
);
grx_text
(s2
, XMIN
+150, YMENU
+40, WHITE
, 0);
if (veloc_pallina
>= 14) veloc_pallina
=14;//limite velocità pallina
inerzia_av
= inerzia_av
+ 0.33;
dy
= -dy
;
}
/*Rimbalzo sulle pareti laterali*/
if (str_cond.
x <= XMIN
+4)
{
dx
= abs(dx
);
str_cond.
x +=dx
;
}
if (str_cond.
x >= XMAX
-4)
{
dx
= -abs(dx
);
str_cond.
x +=dx
;
}
/*Rimbalzo sul cursore giocatore*/
/*lATO ESTERNO SINISTRO*/
if ((str_cond.
y>=str_cond.
yattuale-5) && (str_cond.
y<=str_cond.
yattuale+5) && (str_cond.
x>=str_cond.
xattuale-3) && (str_cond.
x<str_cond.
xattuale))
{
dx
= (int)(veloc_pallina
* cos(20*PI
/180));
dy
= (int)(veloc_pallina
* sin(20*PI
/180));
dy
= -abs(dy
);
if (str_cond.
direzione_mouse == sinistra
)
{
dx
=-abs(dx
);
str_cond.
x +=dx
;
}
else {dx
=abs(dx
);
str_cond.
x +=dx
;
}
str_cond.
y +=dy
;
}
/*Lato ESTERNO destro del cursore*/
if ((str_cond.
y>=str_cond.
yattuale-5) && (str_cond.
y<=str_cond.
yattuale +5)&&(str_cond.
x>str_cond.
xattuale+50) && (str_cond.
x<=str_cond.
xattuale+53))
{
dx
= (int)(veloc_pallina
* cos(20*PI
/180));
dy
= (int)(veloc_pallina
* sin(20*PI
/180));
dy
= -abs(dy
);
if (str_cond.
direzione_mouse == sinistra
){
dx
=-abs(dx
);
str_cond.
x +=dx
;
}
else {dx
=abs(dx
);
str_cond.
x +=dx
;
}
str_cond.
y +=dy
;
}
/*Lato sinistro del cursore*/
if ((str_cond.
y>=str_cond.
yattuale-5) && (str_cond.
y<=str_cond.
yattuale+5) && (str_cond.
x>=str_cond.
xattuale) && (str_cond.
x<=str_cond.
xattuale+16))
{
dx
= (int)(veloc_pallina
* cos(30*PI
/180));
dy
= (int)(veloc_pallina
* sin(30*PI
/180));
dy
= -abs(dy
);
if (str_cond.
direzione_mouse == sinistra
)
{
dx
=-abs(dx
);
str_cond.
x +=dx
;
}
else {dx
=abs(dx
);
str_cond.
x +=dx
;
}
str_cond.
y +=dy
;
}
/*Lato destro del cursore*/
if ((str_cond.
y>=str_cond.
yattuale-5) && (str_cond.
y<=str_cond.
yattuale+5)&&(str_cond.
x>=str_cond.
xattuale+34) && (str_cond.
x<=str_cond.
xattuale+50))
{
dx
= (int)(veloc_pallina
* cos(30*PI
/180));
dy
= (int)(veloc_pallina
* sin(30*PI
/180));
dy
= -abs(dy
);
if (str_cond.
direzione_mouse == sinistra
){
dx
=-abs(dx
);
str_cond.
x +=dx
;
}
else {dx
=abs(dx
);
str_cond.
x +=dx
;
}
str_cond.
y +=dy
;
}
/*Lato centrale del cursore*/
if ((str_cond.
y>=str_cond.
yattuale-5) && (str_cond.
y<=str_cond.
yattuale+5)&&(str_cond.
x>str_cond.
xattuale+16) && (str_cond.
x<str_cond.
xattuale+34))
{
dx
= (int)(veloc_pallina
* cos(45*PI
/180));
dy
= (int)(veloc_pallina
* sin(45*PI
/180));
if (str_cond.
direzione_mouse == sinistra
){
dx
=-abs(dx
);
str_cond.
x +=dx
;
}
else {dx
=abs(dx
);
str_cond.
x +=dx
;
}
dy
= -abs(dy
);
str_cond.
y +=dy
;
}
sem_post
(&mutex_gi
);
/*Controllo posizione avversario*/
/*lato sinistro avversario*/
if ((str_cond.
y>=str_cond.
yattuale_av+10) && (str_cond.
y<=str_cond.
yattuale_av+20)&&(str_cond.
x>=str_cond.
xattuale_av) && (str_cond.
x<=str_cond.
xattuale_av+16))
{
dx
= (int)(veloc_pallina
* cos(30*PI
/180));
dy
= (int)(veloc_pallina
* sin(30*PI
/180));
dy
= abs(dy
);
if (direzione
== destra
)
{
dx
=-dx
;
str_cond.
x +=dx
;
}
str_cond.
y +=dy
;
}
/*lato esterno sinistro*/
if ((str_cond.
y>=str_cond.
yattuale_av+10) && (str_cond.
y<=str_cond.
yattuale_av+20)&&(str_cond.
x>=str_cond.
xattuale_av-3) && (str_cond.
x<=str_cond.
xattuale_av))
{
dx
= (int)(veloc_pallina
* cos(30*PI
/180));
dy
= (int)(veloc_pallina
* sin(30*PI
/180));
dy
= abs(dy
);
if (direzione
== destra
)
{
dx
=-dx
;
str_cond.
x +=dx
;
}
str_cond.
y +=dy
;
}
/*lato destro avversario*/
if ((str_cond.
y>=str_cond.
yattuale_av+10) && (str_cond.
y<=str_cond.
yattuale_av+20)&&(str_cond.
x>=str_cond.
xattuale_av+34) && (str_cond.
x<=str_cond.
xattuale_av+50))
{
dx
= (int)(veloc_pallina
* cos(30*PI
/180));
dy
= (int)(veloc_pallina
* sin(30*PI
/180));
dy
= abs(dy
);
if (direzione
== destra
){
dx
=-dx
;
str_cond.
x +=dx
;
}
str_cond.
y +=dy
;
}
/*lato destro esterno avversario*/
if ((str_cond.
y>=str_cond.
yattuale_av+10) && (str_cond.
y<=str_cond.
yattuale_av+20)&&(str_cond.
x>str_cond.
xattuale_av+50) && (str_cond.
x<=str_cond.
xattuale_av+53))
{
dx
= (int)(veloc_pallina
* cos(30*PI
/180));
dy
= (int)(veloc_pallina
* sin(30*PI
/180));
dy
= abs(dy
);
if (direzione
== destra
){
dx
=-dx
;
str_cond.
x +=dx
;
}
str_cond.
y +=dy
;
}
/*lato centrale avversario*/
if ((str_cond.
y>=str_cond.
yattuale_av+10) && (str_cond.
y<=str_cond.
yattuale_av+20)&&(str_cond.
x>=str_cond.
xattuale_av+16) && (str_cond.
x<=str_cond.
xattuale_av+34))
{
dx
= (int)(veloc_pallina
* cos(45*PI
/180));
dy
= (int)(veloc_pallina
* sin(45*PI
/180));
if (direzione
== destra
){
dx
=-dx
;
str_cond.
x +=dx
;
}
dy
= abs(dy
);
str_cond.
y +=dy
;
}
if (timer
>0)//lascia la pallina bloccata davanti all'avversario e scrive gol
{
str_cond.
x=str_cond.
xattuale_av+25;
str_cond.
y=str_cond.
yattuale_av+30;
grx_text
("GOAL!!! ", (XMAX
-XMIN
)/2+XMIN
, (YMAX
-YMIN
)/2+YMIN
, WHITE
, 0);
}
if (timer
==1) grx_text
("GOAL!!! ", (XMAX
-XMIN
)/2+XMIN
, (YMAX
-YMIN
)/2+YMIN
, BLACK
, 0);//cancella la scritta gol prima di rilanciare la pallina
draw_fly
(ox
, oy
, 0);
draw_fly
(str_cond.
x, str_cond.
y, col
);
sem_post
(&mutex_av
);
ox
= str_cond.
x; oy
= str_cond.
y;
task_endcycle
();
}
i
--;
grx_text
("HAI PERSO!! (Ah! Ah! Ah!) GAME OVER", XMIN
, YMENU
+10, 13, 0);
grx_text
("SPACE TO START A NEW MATCH" , XMIN
, YMENU
+20, 12, 0);
grx_text
("ESC exit to DOS" , XMIN
, YMENU
+30, 12, 0);
grx_text
("IL TUO PUNTEGGIO E' ", XMIN
, YMENU
+40, WHITE
, 0);
sprintf(s2
,"%3d",punteggio
);
grx_text
(s2
, XMIN
+150, YMENU
+40, WHITE
, 0);
}
/****************************************************************/
/* This function is called when the system exits */
void byebye
(void *arg
)
{
grx_close
();
cprintf
("Bye Bye!\n");
}
/****************************** MAIN ******************************/
int main
(int argc
, char **argv
)
{str_cond.
x=0;
str_cond.
y=0;
str_cond.
yvecchio = 150;
str_cond.
xvecchio =150;
str_cond.
yattuale=150;
str_cond.
xattuale=150;
str_cond.
yvecchio_av=110;
str_cond.
xvecchio_av=110;
str_cond.
yattuale_av=110;
str_cond.
xattuale_av=110;
str_cond.
direzione_mouse=sinistra
;
sem_init
(&mutex_av
,0,1);
sem_init
(&mutex_av
,0,1);
HARD_TASK_MODEL m
;
MOUSE_PARMS mouse
= BASE_MOUSE
;
char c
; /* character from keyboard */
TIME seme
; /* used to init the random seed */
int i
= 0; /* number of tasks created */
/* Set the closing function */
sys_atrunlevel
(byebye
, NULL
, RUNLEVEL_BEFORE_EXIT
);
/* graphic card Initialization */
if (grx_init
() < 1)
{
sys_abort
(1);
}
if (grx_open
(640, 480, 8) < 0)
{
cprintf
("GRX Err\n");
sys_abort
(1);
}
/* The scenario */
grx_rect
(XMIN
-D
-1, YMIN
-D
-1, XMAX
+D
+1, YMAX
+D
+1, 14);
grx_text
("GIUOCO DEL PING-PONG", XMIN
, YMENU
+10, 13, 0);
grx_text
("SPACE TO LUNCH A BALL" , XMIN
, YMENU
+20, 12, 0);
grx_text
("ESC exit to DOS" , XMIN
, YMENU
+30, 12, 0);
/* randomize!!!! */
seme
= sys_gettime
(NULL
);
srand(seme
);
/*Inizalizzazione del mouse*/
mouse_def_ps2
(mouse
);
mouse_init
(&mouse
);
mouse_limit
(53, 430,547,430);
mouse_position
(150,430);
mouse_threshold
(3);
mouse_grxcursor
(ENABLE
);
mouse_hook
(my_mouse_handler
);
/* The program waits a space to create a fly */
c
= keyb_getch
(BLOCK
);
/*inizializzazione e attivazione del task avversario*/
hard_task_default_model
(m
);
hard_task_def_ctrl_jet
(m
);
hard_task_def_arg
(m
, (void *)i
);
hard_task_def_wcet
(m
, avv_wcet
);
hard_task_def_mit
(m
, avv_period
);
hard_task_def_group
(m
, FLYGROUP
);
hard_task_def_usemath
(m
);
pid_av
= task_create
("avversario", avversario
, &m
, NULL
);
if (pid_av
== NIL
) {
grx_close
();
perror("Could not create task <fly>");
sys_abort
(1);
}
task_activate
(pid_av
);
do {
if ((c
== ' ') && (indice
== 0))
{
indice
++;
hard_task_default_model
(m
);
hard_task_def_ctrl_jet
(m
);
hard_task_def_arg
(m
, (void *)i
);
hard_task_def_wcet
(m
, fly_wcet
);
hard_task_def_mit
(m
, fly_period
);
hard_task_def_group
(m
, FLYGROUP
);
hard_task_def_usemath
(m
);
pid
= task_create
("fly", fly
, &m
, NULL
);
if (pid
== NIL
) {
grx_close
();
perror("Could not create task <fly>");
sys_abort
(1);
}
task_activate
(pid
);
i
++;
}
c
= keyb_getch
(BLOCK
);
} while (c
!= ESC
);
mouse_end
();
grx_close
();
sys_end
();
return 0;
}
/*------------------------------------THE END--------------------------------------------*/