\documentclass[tikz,border=30pt]{standalone}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{tikz}
\usepackage{tikz-uml}
\usepackage[french]{babel}

\begin{document}
\begin{tikzpicture}
    %%%%%%%%%%%%%%%%%%%%%%%
    %% CLASSES GÉNÉRALES %%
    %%%%%%%%%%%%%%%%%%%%%%%

    % Spécifications du gestionnaire de jeu
    \umlclass{Manager}{
        window : fenêtre\\
        resource\_manager : \texttt{ResourceManager}\\
        clock : horloge\\
        states : pile de \texttt{State}
    }{
        start() : vide\\
        pushState(state : \texttt{State}) : vide\\
        popState() : vide
    }

    % Spécifications du gestionnaire de ressources
    \umlclass[x=4,y=-4.5]{ResourceManager}{
        textures : dictionnaire \texttt{string -> texture}\\
        fonts : dictionnaire \texttt{string -> police}
        music : musique
    }{
        getTexture(name : string) : texture\\
        getFont(name : string) : texture\\
        getLevelPath(name : string) : string\\
        playMusic(name : string) : vide\\
        stopMusic() : vide
    }
    \umluniassoc{Manager}{ResourceManager}

    % Spécfications d'un état de jeu
    \umlabstract[x=-4,y=-4.5]{State}{
        manager : \texttt{Manager}
    }{
        \umlvirt{enable() : vide}\\
        \umlvirt{processEvent(event : événement) : vide}\\
        \umlvirt{frame() : vide}
    }
    \umlunicompo{Manager}{State}

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %% ÉTATS DE JEU PRINCIPAUX %%
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    % Spécifications de l'état de jeu abstrait "niveau"
    % qui est une collection d'objets
    \umlabstract[y=-11]{Level}{
        name : string\\
        background : sprite\\
        music : string\\
        camera : vue\\
        gravity\_direction : direction\\
        total\_time : entier\\
        players : \texttt{[Player]}\\
        objects : \texttt{[Object]}\\
        zone : \texttt{[vecteur]}
    }{
        enable() : vide\\
        processEvent(event : événement) : vide\\
        load(file : string) : vide\\
        save(file : string) : vide\\
        \umlvirt{frame() : vide}\\
        draw() : vide\\
        addObject(object : \texttt{Object})\\
        removeObject(object : \texttt{Object})
    }
    \umlinherit{State}{Level}

    % Spécifications de l'état de jeu "éditeur" qui permet
    % de modifier des niveaux de jeu
    \umlclass[x=-3.5,y=-18]{Editor}{
        selection : \texttt{[Object]}
    }{
        enable() : vide\\
        processEvent(event : événement) : vide\\
        frame() : vide\\
        select(objet: \texttt{Object}) : vide\\
        selectAll() : vide\\
        clearSelection() : vide\\
    }
    \umlinherit{Level}{Editor}

    % Spécifications de l'état de jeu "jeu" qui permet
    % de jouer aux niveaux créés
    \umlclass[x=3.5,y=-18]{Game}{
        mode : mode\\
        next\_frame\_time : temps\\
        pending\_kill : \texttt{[Object]}\\
        time\_left : flottant
    }{
        enable() : vide\\
        processEvent(event : événement) : vide\\
        frame() : vide\\
        update() : vide\\
        kill(objet : \texttt{Object}) : vide
    }
    \umlinherit{Level}{Game}

    % Spécifications des objets du jeu
    \umlabstract[y=-25]{Object}{
        acceleration : vecteur\\
        velocity : vecteur\\
        position : vecteur\\
        mass : flottant\\
        charge : flottant\\
        restitution : flottant\\
        static\_friction : flottant\\
        dynamic\_friction : flottant\\
        layer : entier
    }{
        \umlvirt{getForces(game : \texttt{Game}) : vecteur}\\
        \umlvirt{activate(game : \texttt{Game}, object : \texttt{Object}) : vecteur}\\
        \umlvirt{getAABB() : boîte}\\
        \umlvirt{getRadius() : flottant}\\
        \umlvirt{draw(level : \texttt{Level}) : vide}\\
        updateVelocity(game : \texttt{Game}) : vide\\
        updatePosition() : vide\\
        solveCollision(game : \texttt{Game}, object : \texttt{Object}, normal : vecteur) : vide\\
        positionalCorrection(object : \texttt{Object}, normal : vecteur, depth : flottant) : vide\\
    }
    \umlunicompo{Level}{Object}

    % Spécifications de l'objet "joueur"
    \umlclass[x=-4,y=-31.5]{Player}{
        player\_number : entier non-signé
    }{
        getForces(game : \texttt{Game}) : vecteur\\
        draw(level : \texttt{Level}) : vide\\
        activate(game : \texttt{Game}, object : \texttt{Object}) : vecteur\\
        getAABB() : boîte\\
        getRadius() : flottant\\
    }
    \umlinherit{Object}{Player}

    % Spécifications de l'objet "bloc"
    \umlclass[x=4,y=-31.5]{Block}{}{
        draw(level : \texttt{Level}) : vide\\
        prepareDraw(resources : \texttt{ResourceManager}) : vide\\
        activate(game : \texttt{Game}, object : \texttt{Object}) : vecteur\\
        getAABB() : boîte\\
        getRadius() : flottant\\
    }
    \umlinherit{Object}{Block}

    % Spécifications de l'objet "bloc de fin" permettant
    % quand il est activé de terminer le niveau
    \umlclass[x=0,y=-35]{FinishBlock}{}{
        prepareDraw(resources : \texttt{ResourceManager}) : vide\\
        activate(game : \texttt{Game}, object : \texttt{Object}) : vecteur
    }
    \umlinherit{Block}{FinishBlock}

    % Spécifications de l'objet "bloc de gravité" permettant
    % quand il est activé de réorienter la gravité du niveau
    \umlclass[x=8,y=-35]{GravityBlock}{
        gravity\_direction : direction
    }{
        prepareDraw(resources : \texttt{ResourceManager}) : vide\\
        activate(game : \texttt{Game}, object : \texttt{Object}) : vecteur
    }
    \umlinherit{Block}{GravityBlock}

    % Spécifications de l'objet "bloc tueur" permettant
    % quand il est activé par un joueur de le tuer
    \umlclass[x=0,y=-37.5]{KillBlock}{}{
        prepareDraw(resources : \texttt{ResourceManager}) : vide\\
        activate(game : \texttt{Game}, object : \texttt{Object}) : vecteur
    }
    \umlinherit{Block}{KillBlock}

    % Spécifications de l'objet "bloc d'échange" permettant
    % quand il est activé par un joueur d'échanger sa charge
    \umlclass[x=8,y=-37.5]{SwitchBlock}{}{
        prepareDraw(resources : \texttt{ResourceManager}) : vide\\
        activate(game : \texttt{Game}, object : \texttt{Object}) : vecteur
    }
    \umlinherit{Block}{SwitchBlock}

    %%%%%%%%%%%%%%%%%%%%%%%%%%
    %% ÉTATS DE JEU DU MENU %%
    %%%%%%%%%%%%%%%%%%%%%%%%%%

    % Spécifications de l'état de jeu "menu"
    % qui est le premier état au démarrage et permet
    % d'afficher les différents choix de jeu
    \umlclass[x=-7,y=-11]{Menu}{
        background : sprite\\
        choices : \texttt{[string]}\\
        actions : \texttt{[callback]}\\
        selection : entier non-signé
    }{
        loadMainMenu() : vide\\
        loadLevelMenu() : vide\\
        loadEditorMenu() : vide\\
        launchGame(path : string) : vide\\
        launchEditor(path : string) : vide\\
        launchRules() : vide\\
        quit() : vide\\
        enable() : vide\\
        processEvent(event : événement) : vide\\
        frame() : vide
    }
    \umlinherit{State}{Menu}

    % Spécifications de l'état de jeu "règles" qui
    % affiche l'image décrivant les règles
    \umlclass[x=-14,y=-11]{Rules}{
        background : sprite\\
    }{
        processEvent(event : événement) : vide\\
        frame() : vide
    }
    \umlinherit{State}{Rules}
\end{tikzpicture}
\end{document}
