|
| [Tuto] Tetris | |
| | Auteur | Message |
---|
Asraroth Disciple de la Grande Tasse Bleue
Nombre de messages : 1468
Age : 49
Date d'inscription : 20/10/2006
| Sujet: [Tuto] Tetris Ven 22 Mai 2009 - 20:33 | |
| Voici un tutoriel pour réaliser un TETRIS tout simple sous AGS. Le résultat final va donner çà : Le jeu complet est téléchargeable ici : tetris.zipEt le template : TemplateTetris.zipJe n'ai pas tout détaillé ligne par ligne. N'hesitez pas à demander plus d'explications si besoin
Dernière édition par Asraroth le Lun 25 Mai 2009 - 8:56, édité 1 fois |
| | | Asraroth Disciple de la Grande Tasse Bleue
Nombre de messages : 1468
Age : 49
Date d'inscription : 20/10/2006
| Sujet: I - Le moteur Ven 22 Mai 2009 - 20:33 | |
| I - Le Moteura) La matrice AGS ne gère pas les tableaux à plusieurs dimensions. Voici, donc, un petit module matint110 qui permet de gérer une matrice de taille variable d'entiers (Int). Ce module comprend 3 fonctions : - matint_init(longueur, hauteur) = création de la matrice - matint_set(int x, int y, int valeur) = positionne une valeur dans la case X,Y de la matrice - matint_get(int x, int y) = renvoie la valeur de la case X,Y Pour initialiser notre matrice de jeu, on fera un : matint_init(10, 20); // 10 cases de large, par 20 cases de haut b) La pièce La pièce qui chute a plusieurs propriétés tel que : - sa forme - sa couleur - sa position Voici la structure que j'ai adopté pour gérer tout çà : - Code:
-
struct Piece { int type; // Type de piece int pos_x; // Coordonnées de la piece dans la matrice int pos_y; int couleur; // Couleur de la piece int structure[16]; // Structure de la piece (4 * 4) int structavp[16]; // Sauvegarde de la structure avant de pivoter la piece (permet d'annuler la rotation)
import function creer_structure(); // Créer la structure en fonction du type import function pivoter(); // Pivote la structure import function annuler_pivoter(); // Annule le pivot import function get_structure(int x, int y); // renvoie la valeur d'une case de la structure en X,Y }; La pièce est représentée par une petite matrice de 4 * 4 (int structure[16]). La fonction "creer_structure()" permet de remplir cette structure à partir du type de pièce (7 types de pièce différents). Elle calcule la position de départ "px" dans le dessin que forme les 4 lignes, et recopie un carré de 4 * 4 dans la structure en fonction des "X" et des "." Les "X" sont remplacés par le numéro de la couleur de la pièce alors que les "." sont remplacés par des 0. - Code:
-
function Piece::creer_structure() {
String ligne[4]; // Dessin des 7 types de pièces ligne[0] = ".... .X.. .... .XX. .XX. .... ...."; ligne[1] = ".XX. .X.. .X.. .X.. ..X. .XX. .XX."; ligne[2] = ".XX. .X.. XXX. .X.. ..X. XX.. ..XX"; ligne[3] = ".... .X.. .... .... .... .... ....";
if ((this.type > 0) && (this.type <= 7)) {
// Choix de la couleur de la pièce en fonction de sa forme. if (this.type == 1) this.couleur = 9; if (this.type == 2) this.couleur = 40; if (this.type == 3) this.couleur = 14; if (this.type == 4) this.couleur = 37; if (this.type == 5) this.couleur = 10; if (this.type == 6) this.couleur = 11; if (this.type == 7) this.couleur = 36;
int px = (this.type - 1) * 5; // Remplissage de la structure à partir du dessin des 4 lignes int l = 0; int i = 0; while (l < 4) { int c = 0; while (c < 4) { if (ligne[l].Chars[px + c] == 'X') { // un "X" = la couleur de la piece, sinon = 0 this.structure[i] = this.couleur; } else { this.structure[i] = 0; } i++; c++; } l++; } } else { // Si type inconnu, on vide la structure int i = 0; while (i < 16) { this.structure[i] = 0; i++; } } } c) La rotationAlors là, ma façon de faire est un peu tordue, mais çà marche. Il y a surement plus simple pour parvenir au même résultat. Dans un premier temps, on sauvegarde la mini-matrice de la structure (4 * 4) pour pouvoir annuler rapidement la rotation. Ensuite, on recopie la mini-matrice dans une autre mini-matrice temporaire en appliquant la rotation. Puis, on recopie le résultat de cette matrice temporaire dans la structure. - Code:
-
function Piece::pivoter() { // Sauvegarde la structure dans "structavp" int i = 0; while (i < 16) { this.structavp[i] = this.structure[i]; i++; } // Pivote la structure dans "structbis" int structbis[16]; int xs = 0; int ys = 0; int xd = 3; int yd = 0; while (ys < 4) { xs = 0; yd = 0; while (xs < 4) { structbis[yd * 4 + xd] = this.structure[ys * 4 + xs]; yd++; xs++; } ys++; xd--; } // Recopie "structbis" dans la structure i = 0; while (i < 16) { this.structure[i] = structbis[i]; i++; } } La fonction qui annule la rotation est toute bête. On recopie la sauvegarde de la structure dans la structure elle-même. Çà va servir si la rotation n'est finalement pas possible (trop prêt d'un bord, par exemple). - Code:
-
function Piece::annuler_pivoter() { // Recopie "structavp" dans la structure int i = 0; while (i < 16) { this.structure[i] = this.structavp[i]; i++; } } d) La chuteVoici le cœur du jeu: la fonction qui fait tomber la pièce. Elle appelle tout un tas d'autres fonctions. - Code:
-
function chutte_piece(){ // fait tomber la pièce d'une case if (jeu_encours) { // boolean qui indique si le jeu a commencé supprime_structure_dans_matrice(); // Efface la pièce de la grille if (controle_structure_dans_matrice(piece_active.pos_x, piece_active.pos_y + 1) == 0) { // Controle des collisions si la grille descend d'une case piece_active.pos_y++; // Pas de collision, la pièce peut descendre copie_structure_dans_matrice(); // Insère la piece dans la grille à sa nouvelle position } else { // Collision = la pièce ne peut plus bouger = nouvelle pièce copie_structure_dans_matrice(); // replace la pièce sans la deplacer controle_lignes(); // Lance le contrôle des lignes complètes + scoring
// Recopie de la piece "suivante" dans la piece "active" piece_active.type = piece_suivante.type; piece_active.pos_x = piece_suivante.pos_x; piece_active.pos_y = piece_suivante.pos_y; piece_active.couleur = piece_suivante.couleur; int i = 0; while (i < 16) { piece_active.structure[i] = piece_suivante.structure[i]; piece_active.structavp[i] = piece_suivante.structavp[i]; i++; }
// Préparation de la pièce suivante piece_suivante.type = Random(6) + 1; piece_suivante.creer_structure(); piece_suivante.pos_x = 3; if ((piece_suivante.type == 1) || (piece_suivante.type == 3) || (piece_suivante.type == 6) || (piece_suivante.type == 7)) { piece_suivante.pos_y = -1; } else { piece_suivante.pos_y = 0; } // Contrôle que la nouvelle pièce n'est pas en collision avec une autre pièce if (controle_structure_dans_matrice(piece_active.pos_x, piece_active.pos_y) != 0) { // PERDU jeu_encours = false; piece_active.type = 0; } copie_structure_dans_matrice(); // Insère la pièce dans la grille } affiche_matrice(); // Affichage de la matrice } } Les fonctions suivantes permettent d'insérer et de supprimer la structure (mini matrice 4*4) de la pièce dans la matrice de jeu. - Code:
-
function copie_structure_dans_matrice(){ // Insertion de la pièce en cours, dans la grille int j = 0; while (j < 4) { int i = 0; while (i < 4) { int c = piece_active.get_structure(i, j); if (c > 0) { matint_set(piece_active.pos_x + i, piece_active.pos_y + j, c); } i++; } j++; } }
function supprime_structure_dans_matrice(){ // Efface la pièce de la grille int j = 0; while (j < 4) { int i = 0; while (i < 4) { int c = piece_active.get_structure(i, j); if (c > 0) { matint_set(piece_active.pos_x + i, piece_active.pos_y + j, 0); } i++; } j++; } } e) Les collisions Cette fonction qui est appelée à chaque fois que la pièce se déplace (chute, ou déplacement gauche - droite par l'action du joueur) ou qu'elle pivote. Elle vérifie que la structure de la pièce n'entre pas en collision avec un bord ou le tas d'autres pièce en bas de la matrice. - Code:
-
function controle_structure_dans_matrice(int x, int y){ // Contrôle des collisions de la pièce int j = 0; while (j < 4) { int i = 0; while (i < 4) { int c = piece_active.get_structure(i, j); if (c > 0) { if (matint_get(x + i, y + j) == -1) return -1; // Collision avec un bord if (matint_get(x + i, y + j) > 0) return 1; // Collision avec une autre pièce } i++; } j++; } return 0; } f) Les lignes remplies et la gestion du scoreCette fonction est appelée à chaque fois qu'une pièce arrive en bas de la matrice et s'immobilise. Elle balaye la matrice ligne par ligne et contrôle que la ligne est remplie. Si c'est le cas, la ligne est effacée, et toutes les lignes du dessus sont décalées vers le bas. En même temps, on compte le nombre de lignes formées (4 maxi avec les pièces standard = Tetris) pour gérer le score. - Code:
-
function controle_lignes() { // Contrôle et efface les lignes complètes int nb_lignes = 0; // Nombre de lignes complètes (0 à 4 = TETRIS) int j = 0; while (j < MAX_Y) { // Parcours de la grille de haut en bas bool ligne = true; int i = 0; while ((i < MAX_X) && (ligne)) { // Controle si la ligne "j" est complète if (matint_get(i, j) == 0) ligne = false; // un 0 => pas complète i++; } if (ligne) { // Si la ligne est complète nb_lignes++; int v = 0; while (v < MAX_X) { // Efface la ligne (utile que pour la 1ère ligne tout en haut) matint_set(v, j, 0); v++; } int dy = j; while (dy > 0) { // Décale toutes les lignes vers le bas int dx = 0; while (dx < MAX_X) { matint_set(dx, dy, matint_get(dx, dy - 1)); dx++; } dy--; } } j++; } // Gestion du changement de niveau et du Score passniveau = passniveau + nb_lignes; if (passniveau > 10) { passniveau = 0; niveau++; LabelNiveau.Text = String.Format("Niveau : %d" , niveau); if (vitesse > 10) vitesse = vitesse - 5; } if (nb_lignes == 1) score = score + 10; if (nb_lignes == 2) score = score + 30; if (nb_lignes == 3) score = score + 60; if (nb_lignes == 4) score = score + 100; LabelScore.Text = String.Format("Score : %d" , score); }
Dernière édition par Asraroth le Ven 22 Mai 2009 - 21:01, édité 2 fois |
| | | Asraroth Disciple de la Grande Tasse Bleue
Nombre de messages : 1468
Age : 49
Date d'inscription : 20/10/2006
| Sujet: II - L''''interface Ven 22 Mai 2009 - 20:34 | |
| II - L'interfaceCette partie est très courte et assez simple. Je n'entre pas dans le détail du GUI qui affiche le score et qui permet de lancer le jeu ou d'en sortir. Le contrôle du jeu se fait par la fonction "on_key_press". Dès que le joueur appuie sur une touche, cette fonction est appelée par le moteur d'AGS. Dans notre cas, il suffit de tester si l'une des 4 touches qui nous intéresse a été actionné, et de faire l'action appropriée : - flèche bas = accélère la chute de la pièce - flèche gauche = déplace la pièce d'une case vers la gauche - flèche droite = déplace la pièce d'une case vers la droite - barre d'espace = fait pivoter la pièce de 90° vers la droite - Code:
-
function on_key_press(int keycode) {
if (keycode == 380) { // Fleche bas chutte_piece(); }
if (keycode == 375) { // Fleche gauche supprime_structure_dans_matrice(); if (controle_structure_dans_matrice(piece_active.pos_x - 1, piece_active.pos_y) == 0) { piece_active.pos_x--; } copie_structure_dans_matrice(); affiche_matrice(); }
if (keycode == 377) { // Fleche droite supprime_structure_dans_matrice(); if (controle_structure_dans_matrice(piece_active.pos_x + 1, piece_active.pos_y) == 0) { piece_active.pos_x++; } copie_structure_dans_matrice(); affiche_matrice(); }
if (keycode == 32) { // Barre d'espace = pivoter supprime_structure_dans_matrice(); piece_active.pivoter(); if (controle_structure_dans_matrice(piece_active.pos_x, piece_active.pos_y) != 0) { piece_active.annuler_pivoter(); } copie_structure_dans_matrice(); affiche_matrice(); }
}
Dernière édition par Asraroth le Ven 22 Mai 2009 - 21:29, édité 1 fois |
| | | Asraroth Disciple de la Grande Tasse Bleue
Nombre de messages : 1468
Age : 49
Date d'inscription : 20/10/2006
| Sujet: III - L''''affichage Ven 22 Mai 2009 - 20:34 | |
| III - L'affichageIl n'existe pas de fonction AGS pour dessiner un rectangle vide (une case de la matrice). Il y a une fonction pour dessiner un rectangle plein (DrawRectangle), et une fonction pour dessiner un traie (DrawLine). Voici une petite fonction pour combler ce manque : - Code:
-
function DrawBox(this DrawingSurface*, int x1, int y1, int x2, int y2){ // Dessine une boite this.DrawLine(x1, y1, x1, y2); this.DrawLine(x1, y2, x2, y2); this.DrawLine(x2, y2, x2, y1); this.DrawLine(x2, y1, x1, y1); } Pour l'affichage de la matrice, tout se passe dans cette fonction : - Code:
-
#define MAT_X 220 // Position X de la grille #define MAT_Y 20 // Position Y de la grille #define CEL_W 16 // Largeur d'une case #define CEL_H 16 // Hauteur d'une case #define GAP_H 1 // Espacement horizontal entre chaque case #define GAP_V 1 // Espacement vertical entre chaque case #define MAX_X 10 // Nombre de cases horizontales #define MAX_Y 20 // Nombre de cases verticales
function affiche_matrice(){ // Affichage de la matrice DrawingSurface *surface = Room.GetDrawingSurfaceForBackground(); surface.UseHighResCoordinates = true; // Parcours de la matrice int j = 0; while (j < MAX_Y){ int i = 0; while (i < MAX_X){ // Dessin de la petite boite surface.DrawingColor = 15; surface.DrawBox(MAT_X + (i * CEL_W) + (i * GAP_H), MAT_Y + (j * CEL_H) + (j * GAP_V), MAT_X + ((i + 1) * CEL_W) + ((i + 1) * GAP_H) , MAT_Y + ((j + 1) * CEL_H) + ((j + 1) * GAP_V)); // Coloriage de la boite en fonction du contenu de la matrice surface.DrawingColor = matint_get(i, j); surface.DrawRectangle(MAT_X + (i * CEL_W) + (i * GAP_H) + GAP_H, MAT_Y + (j * CEL_H) + (j * GAP_V) + GAP_V, MAT_X + ((i + 1) * CEL_W) + ((i + 1) * GAP_H) - GAP_H , MAT_Y + ((j + 1) * CEL_H) + ((j + 1) * GAP_V) - GAP_V); i++; } j++; } surface.DrawingColor = 255; surface.DrawBox(MAT_X, MAT_Y, MAT_X + (MAX_X * (CEL_W + GAP_H)), MAT_Y + (MAX_Y * (CEL_H + GAP_V))); surface.Release(); } Au lancement du jeu, on efface l'écran en traçant un rectangle noir de la taille de l'écran. - Code:
-
function room_AfterFadeIn() { // Efface l'écran DrawingSurface *surface = Room.GetDrawingSurfaceForBackground(); surface.UseHighResCoordinates = true; surface.DrawingColor = 0; surface.DrawRectangle(0, 0, surface.Width, surface.Height); surface.Release(); // Vide et affiche la matrice matint_init(MAX_X, MAX_Y, 0); affiche_matrice(); } |
| | | Asraroth Disciple de la Grande Tasse Bleue
Nombre de messages : 1468
Age : 49
Date d'inscription : 20/10/2006
| Sujet: IV - Le reste Ven 22 Mai 2009 - 21:44 | |
| |
| | | Asraroth Disciple de la Grande Tasse Bleue
Nombre de messages : 1468
Age : 49
Date d'inscription : 20/10/2006
| Sujet: Re: [Tuto] Tetris Lun 25 Mai 2009 - 8:58 | |
| J'ai ajouté le lien pour télécharger le template dans le 1er message. |
| | | Shai-la Ouvrière en Chef de la Grande Tasse Bleue
Nombre de messages : 6018
Age : 46
Localisation : Montpellier
Date d'inscription : 17/04/2006
| | | | Godzillu Grand Cliqueur Royal
Nombre de messages : 1658
Date d'inscription : 11/03/2007
| Sujet: Re: [Tuto] Tetris Lun 25 Mai 2009 - 10:27 | |
| Excellent! |
| | | Kromagnon Disciple de la Grande Tasse Bleue
Nombre de messages : 1015
Age : 40
Localisation : Finistère
Date d'inscription : 19/09/2006
| Sujet: Re: [Tuto] Tetris Lun 25 Mai 2009 - 14:16 | |
| Carrement extra B) Shai-La et toi vous êtes des grands malades pour reussir a programmer des trucs comme ça sur AGS O_O |
| | | Shai-la Ouvrière en Chef de la Grande Tasse Bleue
Nombre de messages : 6018
Age : 46
Localisation : Montpellier
Date d'inscription : 17/04/2006
| Sujet: Re: [Tuto] Tetris Lun 25 Mai 2009 - 17:37 | |
| Je rappelle que c'est lui aussi qui a conçu le moteur de jeu match-3, moi j'ai seulement fait l'enrobage |
| | | Crazy Legs Grand Cliqueur Royal
Nombre de messages : 1513
Age : 31
Localisation : La Rochelle
Date d'inscription : 09/01/2008
| Sujet: Re: [Tuto] Tetris Lun 25 Mai 2009 - 18:47 | |
| Salut tout le monde. Bravo Asraroth pour ce joli Tetris ; ton code source va approfondir mes connaissances - Spoiler:
De mon côté je programme un jeu de Poker avec AGS.
_________________ VOUS POURREZ BIENTÔT RÉAPPRENDRE À UTILISER AGS SUR LE SITE DU ZÉRO ! Le tuto est actuellement en refonte totale activement depuis le 20 juillet, prochaine sortie en août ou septembre si tout se passe bien. |
| | | Asraroth Disciple de la Grande Tasse Bleue
Nombre de messages : 1468
Age : 49
Date d'inscription : 20/10/2006
| Sujet: Re: [Tuto] Tetris Lun 25 Mai 2009 - 19:45 | |
| - Crazy Legs a écrit:
- ]De mon côté je programme un jeu de Poker avec AGS.
J'en ai fait un en C++ (sous DOS) il y a + de 15 ans quand j'étais étudiant, et un autre, il y a 3 ans en Visual Basic avant de découvrir AGS. Et bien, tu as de longues heures de programmation en perspective Bon courage ! Surtout quand tu vas attaquer l"IA" du bluff : Faudra pas trop abuser du Random pour rester cohérent. |
| | | Crazy Legs Grand Cliqueur Royal
Nombre de messages : 1513
Age : 31
Localisation : La Rochelle
Date d'inscription : 09/01/2008
| Sujet: Re: [Tuto] Tetris Lun 25 Mai 2009 - 19:51 | |
| Merci ! Ouais je vais essayer de bien gérer l' IA parce qu'on ne pourra jouer que contre l'ordinateur (du moins je pense m'arrêter là). Le random n'est appelé que pour le tirage des cartes ; l' IA je pense que je vais faire quelques calculs de probabilité dans un premier temps puis j'ajouterai un coefficient Bluff effectivement (même si les meilleurs joueurs sont les joueurs serrés selon moi ). En tout cas coder avec AGS est un grand plaisir _________________ VOUS POURREZ BIENTÔT RÉAPPRENDRE À UTILISER AGS SUR LE SITE DU ZÉRO ! Le tuto est actuellement en refonte totale activement depuis le 20 juillet, prochaine sortie en août ou septembre si tout se passe bien. |
| | | jpcr Cliqueur Amateur
Nombre de messages : 230
Age : 57
Localisation : Region Parisienne
Date d'inscription : 01/10/2006
| Sujet: Re: [Tuto] Tetris Sam 21 Aoû 2010 - 9:49 | |
| salut Asraroth ,
impossble de telecharger le jeu ou le template .
pourrais tu revoir les liens, stp ?
edit : c'est bon , ,jai reussi... merci
merci jp |
| | | Asraroth Disciple de la Grande Tasse Bleue
Nombre de messages : 1468
Age : 49
Date d'inscription : 20/10/2006
| Sujet: Re: [Tuto] Tetris Sam 21 Aoû 2010 - 13:45 | |
| Apparemment, il y a eu un changement sur le forum qui fait qu'on ne peut plus mettre d'URL avec des "?"... Ca vient de forumactif ou de Kozzy ? |
| | | Contenu sponsorisé
| Sujet: Re: [Tuto] Tetris | |
| |
| | | | [Tuto] Tetris | |
|
Sujets similaires | |
|
| Permission de ce forum: | Vous ne pouvez pas répondre aux sujets dans ce forum
| |
| |
| |