This commit is contained in:
2026-10-06 11:41:45 +02:00
parent 639ac7a377
commit 45e6551299
4 changed files with 255 additions and 0 deletions
+175
View File
@@ -0,0 +1,175 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <assert.h>
#include <X11/Xlib.h>
#define NB_BILLES 20
#define LARGEUR 640
#define HAUTEUR 480
#define RAYON 12
#define FPS_DELAY_US 16000
/* =========================================================
* ÉTAT D'UNE BILLE + MESSAGE D'AFFICHAGE + ZONE PARTAGÉE
* ========================================================= */
typedef struct {
float x, y, vx, vy; /* position + vitesse */
} etat_bille_t;
typedef struct {
int id;
float x, y; /* position sur la grille */
} msg_bille_t;
typedef struct {
etat_bille_t billes[NB_BILLES];
sem_t sem_shm; /* protège billes[] */
} zone_partagee_t;
/* =========================================================
* PROCESSUS "BILLE" (fils)
* ========================================================= */
void processus_bille(int id, int fd_ecriture, zone_partagee_t *zone) {
while (1) {
sem_wait(&zone->sem_shm);
etat_bille_t *b = &zone->billes[id];
b->x += b->vx;
b->y += b->vy;
if (b->x - RAYON < 0) { b->x = RAYON; b->vx = -b->vx; }
if (b->x + RAYON > LARGEUR) { b->x = LARGEUR - RAYON; b->vx = -b->vx; }
if (b->y - RAYON < 0) { b->y = RAYON; b->vy = -b->vy; }
if (b->y + RAYON > HAUTEUR) { b->y = HAUTEUR - RAYON; b->vy = -b->vy; }
for (int j = id + 1; j < NB_BILLES; j++) {
etat_bille_t *autre = &zone->billes[j];
float dx = autre->x - b->x;
float dy = autre->y - b->y;
float dist = sqrtf(dx * dx + dy * dy);
if (dist > 0.0f && dist < 2.0f * RAYON) {
float nx = dx / dist, ny = dy / dist;
float overlap = 2.0f * RAYON - dist;
b->x -= nx * overlap / 2.0f;
b->y -= ny * overlap / 2.0f;
autre->x += nx * overlap / 2.0f;
autre->y += ny * overlap / 2.0f;
float v1n = b->vx * nx + b->vy * ny;
float v2n = autre->vx * nx + autre->vy * ny;
float diff = v2n - v1n;
b->vx += diff * nx;
b->vy += diff * ny;
autre->vx -= diff * nx;
autre->vy -= diff * ny;
}
}
msg_bille_t m = ; /* <- TODO */
sem_post(&zone->sem_shm);
write(); /* <- TODO */
usleep(FPS_DELAY_US);
}
}
/* =========================================================
* PROCESSUS SUPERVISEUR (parent)
* ========================================================= */
void processus_superviseur(int fd_lecture) {
Display *dpy = XOpenDisplay(NULL);
assert(dpy != 0);
int screen = DefaultScreen(dpy);
Window win = XCreateSimpleWindow(dpy, RootWindow(dpy, screen),
0, 0, LARGEUR, HAUTEUR, 1,
BlackPixel(dpy, screen), WhitePixel(dpy, screen));
XSelectInput(dpy, win, ExposureMask | KeyPressMask);
XMapWindow(dpy, win);
GC gc = XCreateGC(dpy, win, 0, NULL);
float px[NB_BILLES] = {0}, py[NB_BILLES] = {0};
msg_bille_t m;
while (read(fd_lecture, &m, sizeof(m)) == (ssize_t)sizeof(m)) {
if (m.id >= 0 && m.id < NB_BILLES) {
px[m.id] = m.x;
py[m.id] = m.y;
}
XClearWindow(dpy, win);
for (int i = 0; i < NB_BILLES; i++) {
XFillArc(dpy, win, gc,
(int)px[i] - RAYON, (int)py[i] - RAYON,
RAYON * 2, RAYON * 2, 0, 360 * 64);
}
XFlush(dpy);
}
XFreeGC(dpy, gc);
XCloseDisplay(dpy);
}
int main(int argc, char *argv[])
{
int fd[2]; /* --- tube : billes -> superviseur --- */
assert(pipe(fd) != -1);
/* --- zone partagée : billes + sémaphore, créée AVANT les fork() --- */
zone_partagee_t *zone = mmap(NULL, sizeof(zone_partagee_t),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
assert(zone != MAP_FAILED);
assert(sem_init(&zone->sem_shm, 1 , 1) != -1); /* --- semaphore --> section critique --- */
srand(time(NULL));
for (int i = 0; i < NB_BILLES; i++) {
zone->billes[i].x = RAYON + rand() % (LARGEUR - 2 * RAYON);
zone->billes[i].y = RAYON + rand() % (HAUTEUR - 2 * RAYON);
zone->billes[i].vx = (rand() % 5 + 2) * (rand() % 2 ? 1 : -1);
zone->billes[i].vy = (rand() % 5 + 2) * (rand() % 2 ? 1 : -1);
}
for (int i = 0; i < NB_BILLES; i++) {
pid_t pid = fork();
assert(pid >= 0);
if (pid == 0) {
close(fd[0]); /* le fils ne lit pas le tube */
processus_bille(i, fd[1], zone);
close(fd[1]);
munmap(zone, sizeof(zone_partagee_t));
exit(0);
}
}
close(fd[1]); /* le parent n'écrit pas le tube */
processus_superviseur(fd[0]);
close(fd[0]);
for (int i = 0; i < NB_BILLES; i++) wait(NULL);
sem_destroy(&zone->sem_shm);
munmap(zone, sizeof(zone_partagee_t));
return 0;
}