> Tutoriel OCaml SDL : installez OCamlSDL, ouvrez une fenêtre, écrivez une boucle de rendu et animez une balle qui rebondit avec une physique simple.

*Source : https://coder-studio.com/tutoriels/ocaml-sdl-bouncing-ball/*

---

[// Fonctionnel](https://coder-studio.com/tutoriels/)

# OCaml + SDL : coder une balle rebondissante

Par **Kévin Papot** · publié le 10 mars 2026

Associer **OCaml** et **SDL** est un excellent exercice pour découvrir la programmation graphique dans un langage fonctionnel. On y touche à tout : gestion d’une fenêtre, boucle d’affichage, événements clavier et un soupçon de physique. Dans ce tutoriel, nous allons construire pas à pas une petite balle qui rebondit sur les bords de la fenêtre. Le résultat est classique, mais chaque brique se réutilise dans des projets bien plus ambitieux.

## Pourquoi OCaml et SDL ?

**SDL** (Simple DirectMedia Layer) est une bibliothèque C bas niveau qui donne accès à la fenêtre, au rendu 2D, au son et aux périphériques d’entrée. C’est le socle de nombreux jeux indépendants. Côté OCaml, le binding historique s’appelle **OCamlSDL** : il expose l’API de SDL sous une forme adaptée au langage, avec le typage fort et le filtrage par motifs qui font la force d’OCaml.

L’intérêt pédagogique est double. On garde la simplicité de SDL — quelques appels suffisent pour dessiner à l’écran — tout en profitant de la rigueur d’OCaml : une boucle de rendu s’écrit naturellement comme une fonction récursive prenant l’état courant en paramètre.

## Installer OCamlSDL

Le plus simple est de passer par **opam**, le gestionnaire de paquets d’OCaml. Sur une machine où opam est déjà configuré :

```
opam install ocamlsdl
```

Cette commande installe le binding ainsi que les dépendances système SDL 1.2 si votre distribution les fournit. Sous Debian ou Ubuntu, il peut être nécessaire d’installer d’abord les en-têtes :

```
sudo apt install libsdl1.2-dev libsdl-gfx1.2-dev
opam install ocamlsdl
```

Pour compiler, on lie le programme au module `sdl`. Avec `ocamlfind`, cela donne une ligne du type :

```
ocamlfind ocamlopt -package sdl -linkpkg balle.ml -o balle
```

## Ouvrir une fenêtre

Toute application SDL commence par initialiser la bibliothèque, puis par créer une surface d’affichage. En OCaml, cela tient en quelques lignes.

```
let () =
  Sdl.init [`VIDEO];
  let largeur = 640 and hauteur = 480 in
  let ecran =
    Sdlvideo.set_video_mode
      ~w:largeur ~h:hauteur ~bpp:32 [`DOUBLEBUF]
  in
  (* ... boucle de rendu ici ... *)
  Sdl.quit ()
```

`Sdl.init` réveille le sous-système vidéo. `set_video_mode` demande une fenêtre de 640×480 pixels en 32 bits par pixel. Le drapeau `DOUBLEBUF` active le **double buffering** : on dessine dans un tampon caché, puis on l’échange d’un coup avec l’écran visible. C’est ce qui évite le scintillement d’une animation.

## Représenter l’état de la balle

En programmation fonctionnelle, on évite les variables mutables globales. On modélise plutôt l’état de la balle comme une valeur immuable qu’on transforme à chaque image. Un enregistrement fait parfaitement l’affaire.

```
type balle = {
  x  : float;   (* position horizontale *)
  y  : float;   (* position verticale *)
  vx : float;   (* vitesse horizontale *)
  vy : float;   (* vitesse verticale *)
}

let rayon = 15.
```

Les positions et vitesses sont en flottants : cela évite les erreurs d’arrondi qui rendraient le mouvement saccadé. On arrondira seulement au moment de dessiner.

## La physique du rebond

La mise à jour est étonnamment simple. À chaque image, on déplace la balle selon sa vitesse, puis on inverse la composante de vitesse concernée si la balle sort d’un bord.

```
let maj_balle b largeur hauteur =
  let nx = b.x +. b.vx and ny = b.y +. b.vy in
  let vx =
    if nx -. rayon < 0. || nx +. rayon > float largeur
    then -. b.vx else b.vx
  in
  let vy =
    if ny -. rayon < 0. || ny +. rayon > float hauteur
    then -. b.vy else b.vy
  in
  { x = b.x +. vx; y = b.y +. vy; vx; vy }
```

Le principe : quand la balle touche un mur vertical, on inverse `vx` (elle repart dans l’autre sens horizontalement) ; quand elle touche le sol ou le plafond, on inverse `vy`. On recalcule ensuite la position à partir de la vitesse corrigée, ce qui évite que la balle ne reste « collée » au bord. Pour simuler la gravité, il suffirait d’ajouter une constante à `vy` à chaque image.

## Dessiner et échanger les tampons

Reste à afficher la balle. On efface l’écran en le remplissant de noir, on dessine un disque à la position courante, puis on bascule le double buffer.

```
let dessine ecran b =
  let noir = Sdlvideo.map_RGB ecran (0, 0, 0) in
  Sdlvideo.fill_rect ecran noir;
  Sdlgfx.filledCircleRGBA ecran
    (Int32.of_int (int_of_float b.x))
    (Int32.of_int (int_of_float b.y))
    (Int32.of_int (int_of_float rayon))
    255 120 0 255;             (* balle orange *)
  Sdlvideo.flip ecran
```

`fill_rect` peint le fond, `filledCircleRGBA` (fourni par SDL\_gfx) trace un disque plein, et `flip` échange les tampons pour afficher le résultat.

## La boucle de rendu

Le cœur du programme est une fonction récursive qui, à chaque tour, lit les événements, met à jour l’état, dessine, puis se rappelle avec le nouvel état.

```
let rec boucle ecran b largeur hauteur =
  match Sdlevent.poll () with
  | Some (Sdlevent.QUIT)
  | Some (Sdlevent.KEYDOWN { Sdlevent.keysym = Sdlkey.KEY_ESCAPE; _ }) ->
      ()                       (* on quitte *)
  | _ ->
      dessine ecran b;
      Sdltimer.delay 16;       (* ~60 images par seconde *)
      let b' = maj_balle b largeur hauteur in
      boucle ecran b' largeur hauteur
```

Cette structure est très idiomatique en OCaml : l’état passe explicitement d’un appel au suivant, sans mutation cachée. Le `delay 16` plafonne l’animation autour de 60 images par seconde. Un appui sur Échap ou la fermeture de la fenêtre termine proprement la récursion.

Il ne reste qu’à initialiser une balle et à lancer la boucle depuis notre `main` :

```
let depart = { x = 320.; y = 240.; vx = 4.; vy = 3. } in
boucle ecran depart largeur hauteur;
```

## Pour aller plus loin

Vous disposez maintenant d’un squelette complet : fenêtre, boucle, physique et rendu. Les prolongements naturels sont nombreux — plusieurs balles gérées dans une liste, gravité et frottement, collisions entre objets, ou passage à SDL 2 pour un rendu accéléré. Chacun se greffe sur la même architecture fonctionnelle.

## À lire ensuite

-   Consolidez vos bases avec [débuter avec Haskell sans prise de tête](https://coder-studio.com/tutoriels/demarrer-haskell-platform/), un autre langage fonctionnel.
-   Découvrez l’approche globale dans notre guide de la [programmation fonctionnelle](https://coder-studio.com/tutoriels/programmation-fonctionnelle/).
-   Envie de 3D ? Passez à [votre premier triangle en OpenGL](https://coder-studio.com/tutoriels/tutoriel-opengl-premier-triangle/).
