Premier tuto pour faire un jeu en #Canvas: le #Morpion connu aussi sous le nom Tic-tac-toe.
Les choses sérieuses commencent!!! Premier tuto pour faire un jeu en Canvas: le Morpion connu aussi sous le nom Tic-tac-toe.
Le code est commenté, vous ne devriez pas avoir de problème a la comprendre.
Le code:
$(document).ready(function() { // Raccourcis pour avoir des log^^ function log(param) { console.log(param); } // ---------- ---------- ---------- ---------- ---------- // Canvas id: var canvas = $("#canvas"); // ---------- ---------- ---------- ---------- ---------- // Contient les cases pour savoir si elle sont déjà utilisées: var cases = {}; // ---------- ---------- ---------- ---------- ---------- // Pas besoin d'explication: NombreBloc = 3; // ---------- ---------- ---------- ---------- ---------- // Le nombre total de bloc de la grille: var NombreBlocGrille = NombreBloc * NombreBloc; // ---------- ---------- ---------- ---------- ---------- // On commence a 0: var NombreClick = 0; // ---------- ---------- ---------- ---------- ---------- // Détermine qui doit jouer: 1 pour le cercle, 2 pour la croix form = 1; // ---------- ---------- ---------- ---------- ---------- // La taille de chaque carré: taille = 250; // ---------- ---------- ---------- ---------- ---------- // La taille du texte quand on a gagné: // Si on change la taille des cases ne pas oublié de changer la taille du texte taille_texte = '35pt'; // ---------- ---------- ---------- ---------- ---------- // Contient le symbole du joueur pour l'afficher quand il a gagné: joueurs = { "1": 'O', "2": 'X', }; // ---------- ---------- ---------- ---------- ---------- // Contient la couleur pour le carré qui va empêcher de jouer quand quand un joueur a gagné ou si tout le monde a perdu: // Une couleur avec 0.3 de transparence couleurs = { "gagner": 'rgb(0, 255, 0, 0.3)', // Vert "perdu": 'rgb(255, 0, 0, 0.3)', // Rouge } // ---------- ---------- ---------- ---------- ---------- // On calcul la taille du canvas en fonction de la grille généré: // J'agrandis le canvas un tout petit peut plus width = (NombreBloc * taille) + 2; height = (NombreBloc * taille) + 2; // ---------- ---------- ---------- ---------- ---------- // On redimensionne le canvas a la bonne taille: canvas.attr('width', width + "px"); // Contient la hauteur du canvas pour bien l'afficher: canvas.attr('height', height + "px"); // ---------- ---------- ---------- ---------- ---------- // On va générer la grille: for (var x=1;x<=NombreBloc;x++) { for (var y=1;y<=NombreBloc;y++) { // On remplie le tableau qui va nous permettre de savoir si une case est joué ou non: cases[x + '_' + y] = { statut: false, // Si la case a déjà été joué form: 0 // Par qui elle a été joué }; // On trace la case: canvas.drawRect({ layer: true, // Ça je le met TOUT le temps ou problème^^ name: x + '_' + y, // Le nom de la case, c'est important pour la modifier plus tard fillStyle: '#F1F1F1', // Couleur de fond de la case strokeStyle: '#000000', // Couleur de la bordure strokeWidth: 2, // Taille de la bordure x: (x*taille-(taille/2)), y: (y*taille-(taille/2)), // Emplacement de la case // Taille de la case: width: taille, height: taille, // On utilise l'event click: click: function(layer) { // On ajoute 1 a chaque click sur une case: NombreClick++; // Quand on click sur une case et qu'elle n'a pas encore été utilisé, car elle vaut false: if(cases[layer.name]['statut'] == false) { // Une fois la case clické on la met a true pour pas qu'on puisse la réutilisé: cases[layer.name]['statut'] = true; // Condition qui permet d'alterner la forme circulaire ou de la croix: if(form == 1) { // On indique la forme joué: cases[layer.name]['form'] = form; // On change la valeur pour alterner la forme tracé au prochain click: form = 2; // Fonction qui trace le Cercle: traceCercle(layer); } else { // On indique la forme joué: cases[layer.name]['form'] = form; // On change la valeur pour alterner la forme tracé au prochain click: form = 1; // Fonction qui trace le Croix: traceCroix(layer); } } else // Si elle a déjà été utilisé on peut afficher une erreur ici: { log('Casé ' + layer.name + ' déja joué!!!'); } // Fonction qui test si un joueur a gagné: testGagnant(); } }); } } // ---------- ---------- ---------- ---------- ---------- // La fonction récup en paramètre les infos de la case cliqué: function traceCercle(data) { // log(data); // On récup la position de la case qu'on a cliqué: data_x = data.x; data_y = data.y; // On trace le cercle: canvas.drawArc({ layer: true, strokeStyle: '#000000', // Couleur de la bordure strokeWidth: 5, // Taille de la bordure // Position ou on va tracer le cercle: x: data_x, y: data_y, radius: (taille/2) // On divise la taille de la case par deux pour avoir le rayon du cercle à tracer }); } // ---------- ---------- ---------- ---------- ---------- // La fonction récup en paramètre les infos de la case cliqué: function traceCroix(data) { // log(data); // On récup la position de la case: data_x = data.x; data_y = data.y; // On va tracer la croix qui est en deux parties. // Pour cela ajoute a X ou Y la taille du carré divisé par deux pour trouver les angles opposés de notre case pour tracer nos deux droites ce qui va former au final notre croix. // Ici vu qu'on a besoin de deux positions pour tracer nos droites, les coordonnés on pour nom x1 x2... et non x et y. De cette manière on peut prolonger notre droite dans toute les directions en donnant une liste de point. canvas.drawLine({ layer: true, strokeStyle: '#000000', // Couleur de la bordure strokeWidth: 5, // Taille de la bordure x1: data_x+(taille/2), y1: data_y-(taille/2), // Haut droite x2: data_x-(taille/2), y2: data_y+(taille/2), // Bas gauche }); canvas.drawLine({ layer: true, strokeStyle: '#000000', // Couleur de la bordure strokeWidth: 5, // Taille de la bordure x1: data_x+(taille/2), y1: data_y+(taille/2), // Bas droite x2: data_x-(taille/2), y2: data_y-(taille/2), // Haut gauche }); } // ---------- ---------- ---------- ---------- ---------- // Fonction qui test si un joueur a gagné: function testGagnant() { // Vaut false t'en que personne a gagné: gagne = false; // On boucle pour vérifier les deux joueurs: for (var i=1;i<=2;i++) { // La fonction verifGagnant() vérifie pour chaque joueur si il a gagné: // 0 perdu, 1 ou 2 le joueur qui à gagné if(verifGagnant(i) > 0) { // On lui transmet la couleur voulu en param: carreGeant(couleurs['gagner']); // On lui transmet le texte en param: texteGagnant('Le joueur ' + joueurs[i] + ' a gagné!!!'); // Quelqu'un a gagné, donc on met true: gagne = true; } else { } } // Vu que la variable gagne vaut toujours false c'est que personne a gagné et si le nombre de case possible utilisable est atteint c'est que c'est perdu: if((gagne == false) && (NombreBlocGrille == NombreClick)) { // On lui transmet la couleur voulu en param: carreGeant(couleurs['perdu']); // On lui transmet le texte en param: texteGagnant('Personne a gagné'); } else { } } // ---------- ---------- ---------- ---------- ---------- // Test chaque possibilité de gagner: // La valeur de retour est le joueur gagnant qui...à été passé en param^^ function verifGagnant(i) { if( (cases['1_1']['form'] == i) && (cases['1_2']['form'] == i) && (cases['1_3']['form'] == i) ) // On test la colonne numéro 1: { return i; } else if( (cases['2_1']['form'] == i) && (cases['2_2']['form'] == i) && (cases['2_3']['form'] == i) ) // On test la colonne numéro 2: { return i; } else if( (cases['3_1']['form'] == i) && (cases['3_2']['form'] == i) && (cases['3_3']['form'] == i) ) // On test la colonne numéro 3: { return i; } else if( (cases['1_1']['form'] == i) && (cases['2_1']['form'] == i) && (cases['3_1']['form'] == i) ) // On test la ligne numéro 1 { return i; } else if( (cases['1_2']['form'] == i) && (cases['2_2']['form'] == i) && (cases['3_2']['form'] == i) ) // On test la ligne numéro 2 { return i; } else if( (cases['1_3']['form'] == i) && (cases['2_3']['form'] == i) && (cases['3_3']['form'] == i) ) // On test la ligne numéro 3 { return i; } else if( (cases['1_1']['form'] == i) && (cases['2_2']['form'] == i) && (cases['3_3']['form'] == i) ) // On test la diagonal de en haut a gauche a en bas a droite { return i; } else if( (cases['3_1']['form'] == i) && (cases['2_2']['form'] == i) && (cases['1_3']['form'] == i) ) // On test la diagonal de en haut a droite a en bas a gauche { return i; } else // Perdu: { return '0'; } } // ---------- ---------- ---------- ---------- ---------- // Affiche un carré qui couvre la grille pour empercher les joueurs de jouer une fois la partie terminé. function carreGeant(couleur) { // On trace le carré avec comme valeur x 0 et y 0, car on le trace ici pas par son centre, mais pas le coin en haut a gauche et comme on connait la taille de la grille qui est par la même occasion celle du canvas ça nous permet de tracer un carré a la bonne taille: canvas.drawRect({ layer: true, fromCenter: false, // On ne trace plus par le centre, mais par le coin supérieur gauche fillStyle: couleur, // Couleur de fond x: 0, y: 0, // Les coordonnées du coin // Taille de la case: width: width, height: height }); } // ---------- ---------- ---------- ---------- ---------- // Affiche le gagnant: function texteGagnant(texte) { // On affiche le texte pour dire qui à gagné: canvas.drawText({ layer: true, fillStyle: '#9cf', // Couleur de fond strokeStyle: '#25a', // Couleur de la bordure strokeWidth: 2, // Taille de la bordure x: width/2, y: height*0.8, // Coordonnées ou on va tracer notre texte fontSize: taille_texte, // Taille du texte fontFamily: 'Verdana, sans-serif', // La police du texte text: texte, // Le fameux texte align: 'left', // Va aligner le texte sur la gauche plutôt que le centre maxWidth: 600, // Taille max du texte sur la ligne, donc si le texte est trop long il revient a la ligne }); } // ---------- ---------- ---------- ---------- ---------- });
Comme prochain jeu, je peux vous faire le jeu de Hex si vous voulez!
Tous les codes sont testés et sont fonctionnels, si il arrive qu'un de ces codes ne fonctionne pas chez vous, merci de me le signaler.