Documentation développeur
Cliquez sur l'un des liens ci-dessous pour avoir plus d'informations sur le sujet en question.

Le Projet de base

Le projet se base sur le jeu de France 3, Questions Pour Un Champion (QPUP). Les auteurs de ce jeu ayant une préférence pour la politique Française, ils ont donc décidé de faire un spin-off de ce dernier : Question Pour Un Président (QPUP).

Le jeu fonctionne entièrement en JavaScript, mais les pages fonctionnent aussi en HTML, CSS, PHP, et JQuery (une librairie JavaScript)

La structure du Site

La structure est relativement simple.

A la racine du site, donc au début du site, nous pouvons trouver les différentes pages HTML. Attention toutefois, leur extension est en PHP : PHP permet de créer du contenu dynamique plus simplement et rapidement. Nous l'utilisons principalement pour la page où le jeu se situe : par conséquent, nous avons mis toutes les pages HTML en PHP pour se simplifier la tâche (histoire d'éviter les fichiers soit PHP, soit HTML).

Dans le dossier CSS, nous pouvons trouver les différents styles utilisés sur les pages. Le CSS correspondrait à l'agencement des meubles si le code HTML correspondait aux dits meubles.

Dans le dossier fonts, nous trouvons des polices d'écriture. Elles servent de pilier à certains fichiers CSS s'en servant.

Dans gameRes, nous pouvons trouver les fichiers de ressources externes au jeu (gameRes = Game Resources). Nous pouvons par exemple trouver les questions et les réponses du quizz.

Dans le dossier img, nous stockons les images dont nous nous servons tant pour le site que pour le jeu. Nous n'avons pas adopté de format en particulier.

Dans js, nous trouvons deux sous-parties : en premier lieu, les fichiers servant à faire fonctionner le site (ou le jeu, dans le cas échéant). Nous nous basons sur les fichiers de l'infrastructure BootStrap, nous utilisons donc leurs fichiers, libres de droits, ainsi que d'autres fichiers externes à Bootstrap. Cette sous-partie n'a pas été écrite par les auteurs de ce jeu. Le dossier game, quant à lui, correspond aux fichiers écrits par ces derniers faisant fonctionner le jeu uniquement. Ils sont répartis selon leur utilité : les fichiers servant aux évènements seront donc dans le fichier events.js. Ce dossier est automatiquement chargé par la page supportant le jeu.

Enfin, dans music, nous trouvons tout simplement la musique utilisée par le jeu.

Fonctionnement du jeu

Le jeu fonctionne selon une "séquence" de démarrage très précise.
  1. La page se charge, reçevant les éléments essentiels (à savoir la page HTML elle-même naturellement, et les fichiers dans js/game/). Puis...
  2. La page lance la fonction boot(), qui va vérifier l'intégrité du fichier de questions (voir la partie sur le fichier de questions). Puis...
  3. Elle lancera le jeu si ce dernier est sans problème en activant la liaison au canvas (voir partie canvas). Puis...
  4. Elle activera le menu de démarrage ainsi que ses animations. Puis...
  5. Elle activera les évènements et les autorisera afin de prendre en charge ces derniers. C'est tout !
L'avantage de fonctionner ainsi est une lisibilité du code incroyable et un débuggage bien plus rapide car le code suit le même chemin que celui du jeu (évidemment !). Le gros désavantage, en revanche, est de ne pas -ou difficilement- pouvoir "passer" une étape. Si une erreur en fin de jeu est trouvée, il faudra passer tout le jeu. Bien entendu, nous avons des commandes "secrètes" pour accélérer la manoeuvre ;-)

Le fichiers de questions

Le fichier de questions se situe dans js/gameRes. Il se nomme quans.txt (quans = QUestions ANSwers). Ce fichier se repose sur une architecture basique.

Le fichier se décompose pour chaque question en plusieurs parties :

  1. Le numéro de la question entre crochets : [N]
  2. La question : En quelle année [...] ?
  3. Les quatres réponses, une par ligne
  4. La bonne réponse (son numéro dans la liste des réponses de cette question), précédée d'une flèche : ->3
  5. La fin de la question N, entre crochets plus un slash : [/N]
Cette architecture pose un certain nombre de restrictions :
  • On ne peut pas séparer sa question par un retour à la ligne
  • On doit suivre ses questions selon leur numéro : 1,2,3... et pas 3, 5, 9...
  • Si un bug survient, il faut relire ligne par ligne ce fichier.
On arrive à un total de 8 lignes par question. Par conséquent, si le fichier ne fait pas 8 lignes, c'est que ce dernier est endommagé. C'est ce que contrôle le boot.

Le Canvas

Le canvas permet de gérer les dessins, animations et tout l'aspect graphique du jeu. Nous utilisons des fonctions définies dans boot() et le fichier ui.js. Nous utilisons des fonctions permettant de dessiner des images, des lignes, des rectangles, etc., grâce à un principe vectoriel.

Voici un exemple utilisé:

function drawImage(vec,src) { //Affiche une image
    var img = new Image();
    img.src = src;
    img.onload = function() {
        ctx.drawImage(img, vec[0], vec[1], vec[2], vec[3]);
    }
}

function clear(vec) { //Efface l'écran selon le vecteur vec.
    ctx.clearRect(vec[0], vec[1], vec[2], vec[3]);
} 
                            

La fonction drawImage a deux arguments : vec et src. En vrai, vec doit être un tableau (array) ayant 4 paramètres : X0, Y0, X1, Y1. Le principe vectoriel est simplement d'aller du point A (<X0;Y0>) au point B (<X1;Y1>). Quant à src, c'est simplement le chemin vers l'image par rapport à la page que l'utilisateur. Comme les pages sont à la racine, il suffit de préciser que src = "img/julien.png".

Voici un autre exemple, cette fois pratique mais à nouveau utilisé dans notre code :

drawImage([-100,julienPos,900,600], 'img/julien.png', 20);
                            
julienPos correspond ici à une variable pour "déplacer" l'image petit à petit.

Le problème avec Canvas

La tâche la plus ardue se trouve justement dans cet élément dans le canvas. En effet, canvas ne peut accepter que de dessiner quelque chose...et il ne connaît pas les couches. Concrètement, cela signifie que non seulement il est impossible d'effacer quelque chose simplement sans effacer tout le canvas (et donc on devra redessiner tout le canvas). Le second problème découle du premier...il est impossible de sélectionner un objet dans le canvas. En effet, une fois paint, il s'agit d'un seul et même élément. Le côté positif ? On peut, grâce à ce système, enregistrer notre partie en enregistrant le canvas.
Après le boot, on affiche l'écran de démarrage.

Ecran de démarrage

L'écran de démarrage se décompose en plusieurs parties :

  1. Le passage de Julien Lepers
  2. L'apparition du titre
  3. L'apparition des commandes
Ces dernières dépendent de la fonction
drawStartupMenu
Cette fonction a un argument : step. Soit step un nombre entre 0 et 3. Une fois le boot effectué (boot()), on appelle drawStartupMenu(0), qui va s'occuper de faire apparaître petit à petit J.L. . Cela fait (quand la tête est à la hauteur maximale), la fonction va s'appeller elle-même :
drawStartupMenu(1)
L'argument = 1 dessine les commandes. Une fois cela fait, elle se rappelle à nouveau, etc. etc. jusqu'à arriver à
drawStartupMenu(3)
Une fois step = 3, la fonctionne cesse de se rappeller.

Note

La fonction drawStartupMenu utiise un système de timers, tant pour déplacer la tête de Julien Lepers (efface l'écran, redessine la tête en vec, attends N ms, recommence jusqu'à une certaine hauteur) que pour l'affichage des commandes. Cela permet de fixer avec précision la vitesse des animations, leur direction, comment elles vont fonctionner, etc. Une fois le menu dessiné, et seulement à la fin, notre fonction va déclencher l'évènement suivant :
document.onkeydown = inputKey;
Ce code permet de déclencher l'une des plus grosses fonctions dans notre système : la gestion des évènements. Cette fonction, dans events.js va gérer les touches que l'utilisateur utilise. Cette fonction fonctionne sur un principe simple : déterminer la touche, déterminer si elle est utile dans ce niveau, déterminer si on peut l'utiliser dans ce niveau dans le contexte actuel.

Cette dernière gèrant tout le jeu, elle est particulièrement massive. Elle n'autorise pourtant que deux touches sur l'écran de démarrage : J et S (Jouer et couper le Son).

Le premier niveau

Avant de pouvoir commencer à jouer, le premier niveau est particulier dans le sens qu'il ne correspond pas vraiment au niveau 1 du jeu. En réalité, ce niveau correspond au niveau de tutoriel rapide pour le joueur : c'est dans ce niveau que J.L. présentera le jeu ainsi que comment jouer.

La transition entre ce niveau et l'écran de démarrage est faite grâce à une musique et au dessin de l'écran pour les questions. La musique, une fois terminée, va déclencher un autre évènement. Cet évènement autorisera Julien Lepers à faire son explication. En somme, en démarrant le niveau, la musique s'active. Une fois cette dernière terminée, elle va activer un évènement : ce dernier va vérifier quelle musique vient de se terminer, va voir que c'est celle d'introduction (grâce au nom de fichier) et déclenchera la fonction tutorial(). Elle utilise elle aussi une variable step. Cette fois, elle sera activée uniquement grâce à l'appui sur la touche entrée. Une fois le tutoriel passé (qui consiste simplement à effacer l'écran, redessiner le plateau et afficher le texte de tutoriel suivant jusqu'au bout), on passe au vrai niveau un.

Le premier niveau (le vrai promis)

Le niveau un est plus complexe. Il se base sur un système de vies, de compte à rebours, de score, d'atouts et de questions. Malgré le nombre d'éléments à gérer, c'est encore ridiculement simple : chaque élément est géré par une fonction (en général nommée draw<Nom de l'élément>). Les questions vont se suivre selon ce système :

  1. On appelle la fonction newQuestion() dans le fichier questions.js.
  2. La fonction prend un nombre aléatoire entre 1 et le numéro de la dernière question.
  3. Elle prend la question en question (ha ha ha) et charge la structure de cette dernière en mémoire
  4. Elle affiche la question et les réponses. Ici, on n'a besoin que d'une réponse correcte et une fausse, qu'on choisit aléatoirement.
  5. On déclare au système quelle touche déclenchera la bonne réponse. Exemple si A est la bonne réponse, la touche correspondante sera 65 (le code de A).
  6. On attend que l'utilisateur appuye soit sur A, soit sur B (les deux réponses valides) ou 1, 2, 3 (les jokers). Attendre jusqu'à la fin du temps imparti déclenchera une réponse fausse.
  7. Joker ou pas, on vérifie la réponse, on déduit des vies ou on augmente le score.
  8. On continue jusqu'au Game Over ou au passage au niveau 2.
En résumé : on affiche une question, on attend de voir si l'utilisateur répond correctement ou pas (ou ne répond pas), et on prend l'action appropriée. Une grosse partie de ce système est géré par le système d'événements : après tout, appuyer sur une touche est un événement. On affiche ensuite la nouvelle question en effacant l'écran et en le redessinant avec la nouvelle question, etc. etc.

Note

Le chronomètre, les vies, le score et les atouts sont redessinés automatiquement. En vrai, il suffit d'appeller la fonction playLvl1(), qui va appeller toutes les fonctions nécessaires en plus de redessiner l'écran.

Le passage du niveau 1 (le vrai) au niveau 2

Il est automatiquement géré par le système d'évènements. De façon simple, d'ailleurs : si l'utilisateur a réussi à répondre correctement à une question ET que le score nécessaire est suffisant pour passer au niveau deux, alors on y passe.

Le niveau deux

C'est exactement la même chose que le niveau un. La seule chose qui change est que nous mettons toutes les réponses. On utilise pour cela la fonction shuffle() sur les réponses de façon à les mélanger. On les affiche et on déclare au système quelle est la bonne réponse.

L'écran de fin

Une fois qu'on a assez de points, on affiche l'écran de victoire.

Les variables

Les variables importantes sont déclarées dans le fichier variables.js. Elles sont automatiquement déclarées une fois le fichier HTML déclaré.

Sources (remerciements)

Un grand merci à ces personnes (ou entreprises, communautés, etc) :
  • Monsieur Gisin, qui nous a permis de réaliser le projet dans le cadre du Collège
  • Les librairies JQuery, Humane, faisant fonctionner ce projet de façon splendide
  • L'algorithme de Fisher-Yates (aka Knuth), permettant de mélanger rapidement nos questions (voir questions.js)
  • Bootstrap, pour l'apparence du site qui est splendide jusqu'au plus petit détail il faut bien l'avouer
  • Tous les éléments audiovisuels
Les ressources appartiennent à leurs proprios respectifs. Voir la page documentation pour la partie developpeurs et les sources.