Vu que le dernier exercice a intéressé quelques personnes, je me suis dis que ça pourrait être intéressant de l'étendre à une lib graphique -> la SDL.
La SDL, car c'est la bibliothèque qui est la plus connue sur ce forum, mais si vous êtes tentés par une autre bibliothèque, ne vous privez pas.
Le but de cet exercice est exactement le même que son homologue en console, à savoir réaliser un morpion 2 joueurs.
Les différences?
Le déroulement du jeu, et l'affichage. Le déroulement:
Ici, plutôt que rentrer un numéro, ou les coordonnées de la case, le joueur doit cliquer sur la case désirée.
On affiche le nouvel état du plateau, et on passe au joueur suivant. L'affichage:
On n'est pas en console, et vous avez 2 choix:
-vous dessinez vos croix et vos cercles avec un logiciel de dessin, et vous les importez.
-Vous dessinez ces formes dans votre programme(plus drôle : diable: )
Si vous avez besoin de précisions, sur l'énoncé, la méthode, la SDL(ou autre), vous pouvez les poser ici.
En espérant vous voir nombreux .
Si ce genre de topics vous intéresse on, pourrait voir à ponctuellement proposer la réalisation de jeux 2d simples.
edit:
Quelques conseil pour démarrer, si vraiment vous vous sentez bloqué.
- Se rappeler que l'utilisation d'une lib graphique ne change rien à la logique du jeu. La manière de tester une grille est identique à ce qu'on fait avec l'exercice zMorp en console.
- Pour afficher des messages, pensez à utiliser la barre de titre de la fenètre(SDL_WM_SetCaption).
- Le morpion n'est pas un jeu en temps réel(on attend des action utilisateurs), SDL_WaitEvent est très approprié ici.
- Pour représenter les joueurs, des rectangles de couleurs différentes suffisent
Malgré que je ne fais pas partis de la communauté des codeurs C en "mode graphique" ( ) ce sujet est très intéressant pour les concernés.
De plus, proposer un exercice avec l'appel d'une librairie graphique est je pense plus qu'un bon entraînement.
(Parce que les Mario Sokoban tout ça, ras le bol hein )
coyote60 > L'IA n'a rien à voir avec le mode graphique ou console, tu peux très bien le faire à part.
Pour ceux qui ont fait un code console, c'est un bon moyen de voir si votre code est facilement transposable (bien découpé en fonctions) pour que vous n'ayez que quelques fonctions à changer sans changer tout le code.
j ai compris (un peut tare ) la remarque que tu ma fait sur l'autre sujet (zMorp 1ére partie). sur mai fonction qui font plusieurs chose, la je suis entrain de luté avec mai Fprint que j ai mi partout
Tu veux dire que dans le titre de la fenêtre, on écrit par exemple "Joueur 1, à vous" ou "Joueur 2 a "gagné"?
Exactement.
Citation : Nasta
Moi, j'ai pas trop de problème avec, mais ça m'embête de devoir charger des surfaces.
Charger des surfaces n'est pas une obligation.
Avoir un truc qui tourne rapidement avec des SDL_FillRect est plus intéressant à mon avis. Après, il est facile, je mettre de l'enrobage.
tu peux tout faire sans charger d'image : un fond noir avec 9 cases blanches + SDL_TTF
mais sinon penser à vérifier les retours des fonction sinon vous aurez de grave problème pour trouver l'erreur. mais encore c'est pas grand grand comme programme
Personnellement, j'ai préféré utiliser 3 image : la grille, la croix et le rond.
Quand je dis que je ne veux pas charger les surfaces, je parle de SDL_TTF. Je n'ai pas envie de devoir passer pas 3 fonctions juste pour afficher un message.
Je sais que je peut me faire une fonction perso, mais je pense que je ferais mieux de mettre ça en amélioration.
Sinon, je viens de me rendre compte que ma fenêtre est plus grande que mon écran...
Sinon, je viens de me rendre compte que ma fenêtre est plus grande que mon écran...
C'est effectivement un peu embêtant.
Perso, comme, je n'utilises pas d'image, j'ai déterminé la taille des cases en fonction de la taille de l'écran.
J'avoue, pour un morpion 100 x 100 les cases sont petites.
Citation : Nasta
Quand je dis que je ne veux pas charger les surfaces, je parle de SDL_TTF. Je n'ai pas envie de devoir passer pas 3 fonctions juste pour afficher un message.
Tout à fait.
Afficher dans la barre de titre pour un morpion est suffisant, je pense.
Le but, est de ne pas avoir une usine à gaz.
Fini le mien. Y'a sûrement des améliorations à faire mais il fonctionne normallement et je n'ai pas de warning...
main.c :
/**
main.c
Rôle : contient les fonctions "de base"
Note : Dans tout le projet, les ligne suivies d'un double-slash '//' sont à modifier dans le cas d'un agrandissement de la grille
*/
#include <stdbool.h>
#include <SDL/SDL.h>
#include "constantes.h"
/* prototypes */
void jeu (Surfaces *surfs);
/* fonctions */
void freeSurfs (Surfaces *surfs) // Libère toutes les surfaces
{
SDL_FreeSurface(surfs->grid);
SDL_FreeSurface(surfs->cross);
SDL_FreeSurface(surfs->circle);
}
void Quit (Surfaces *surfs)
{
freeSurfs(surfs);
SDL_Quit();
}
void initSurfs (Surfaces *surfs) // Initialise la structure surfaces
{
// chargements
surfs->grid = SDL_LoadBMP("Grille.bmp");
surfs->cross = SDL_LoadBMP("croix.bmp");
surfs->circle = SDL_LoadBMP("rond.bmp");
// vérifications
if (surfs->grid == NULL || surfs->cross == NULL || surfs->circle == NULL) // Si un des surfaces n'a pas été chargée
{
fprintf (stderr, "Erreur lors du chargement des images bmp : %s\n", SDL_GetError());
exit (EXIT_FAILURE);
}
// Transparance
SDL_SetColorKey(surfs->cross, SDL_SRCCOLORKEY, SDL_MapRGB(surfs->cross->format, 255, 255, 255));
SDL_SetColorKey(surfs->circle, SDL_SRCCOLORKEY, SDL_MapRGB(surfs->circle->format, 255, 255, 255));
}
int main (int argc, char *argv[]) // Se charge de toutes les initialisations
{
SDL_Surface *ecran = NULL;
Surfaces surfs;
/* Initialisation SDL */
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf (stderr, "Erreur lors du chargement de la SDL : %s\n", SDL_GetError());
exit (EXIT_FAILURE);
}
/* Création de la surface de rendu vidéo */
ecran = SDL_SetVideoMode(L_FENETRE, H_FENETRE, 32, SDL_HWSURFACE | SDL_DOUBLEBUF );
if (ecran == NULL)
{
fprintf (stderr, "Erreur lors de la création de la fenêtre avec 'SDL_SetVideoMode' : %s\n", SDL_GetError());
exit (EXIT_FAILURE);
}
initSurfs(&surfs);
jeu(&surfs);
Quit(&surfs);
return EXIT_SUCCESS;
}
bool gagne (const SDL_Rect lastPlayP, const Signe LastPlayS, Signe grille [][H_GRILLE]) // Cette fonction renvoie tru s'il y a une victoire. Le contexte d'appel permet de définir le gagnant
{
/* On regarde si la ligne du dernier coup est remplie du dernier signe à avoir joué */
if (grille[lastPlayP.x][0] == LastPlayS && grille[lastPlayP.x][1] == LastPlayS && grille[lastPlayP.x][2] == LastPlayS) //
{
return true;
}
if (grille[0][lastPlayP.y] == LastPlayS && grille[1][lastPlayP.y] == LastPlayS && grille[2][lastPlayP.y] == LastPlayS) //
{
return true;
}
/* test des diagnales */
if (grille[0][0] == LastPlayS && grille[1][1] == LastPlayS && grille[2][2] == LastPlayS) //
{
return true;
}
if (grille[0][2] == LastPlayS && grille[1][1] == LastPlayS && grille[2][0] == LastPlayS) //
{
return true;
}
return false;
}
void estGagnant (Signe joueur) // affiche le gagnant
{
SDL_Surface *ecran = SDL_GetVideoSurface();
if (joueur == Cross)
{
SDL_Flip(ecran); // Un flip pour montrer l'état du jeu avant la fermeture
SDL_WM_SetCaption("Les croix ont gagnees ! Bravo !", NULL);
SDL_Delay(2000);
}
else
{
SDL_Flip(ecran);
SDL_WM_SetCaption("Les cercles ont gagnes ! Bravo !", NULL);
SDL_Delay(2000);
}
}
bool recommencer () // Retourne true si le joueur veut recommencer
{
SDL_Event event;
SDL_WM_SetCaption("Voulez-vous rejouer ? (o)ui/(n)on", NULL);
while(1)
{
SDL_WaitEvent(&event);
if (event.type == SDL_QUIT)
return false;
if (event.type == SDL_KEYDOWN)
{
if (event.key.keysym.sym == SDLK_o)
return true;
if (event.key.keysym.sym == SDLK_n)
return false;
if (event.key.keysym.sym == SDLK_ESCAPE) // Petite pensée à ceux qui n'ont pas de souris (sisi, ça arrive...)
return false;
}
}
return false; // pour éviter un warning
}
void jeu (Surfaces *surfs) // Fonction principale du jeu
{
SDL_Rect posZero;
SDL_Rect caseClique, caseBlit; // Indique sur quelle case on a cliqué et la position du blit d'un signe
SDL_Surface *ecran = SDL_GetVideoSurface();
SDL_Surface *signeActuel; // Cette surface est celle que l'on blittera sur l'ecran. Elle prendra une des valeurs des surfaces de notre structure
SDL_Event event;
Signe tourDeJeu = Cross; // Les croix jouent en premier
bool continuer = true;
int nbCoups = NB_CASES;
Signe grille[L_GRILLE][H_GRILLE] = {{Vide, Vide, Vide},//
{Vide, Vide, Vide},//
{Vide, Vide, Vide}};//
posZero.x = 0;
posZero.y = 0;
SDL_BlitSurface(surfs->grid, NULL, ecran, &posZero); // On blitte la grille à l'écran
while (continuer)
{
if (tourDeJeu == Cross) // On dit qui doit jouer
{
SDL_WM_SetCaption("Aux croix de jouer", NULL);
signeActuel = surfs->cross;
}
else
{
SDL_WM_SetCaption("Aux cercles de jouer", NULL);
signeActuel = surfs->circle;
}
SDL_WaitEvent(&event); // On attend l'évênement
if (event.type == SDL_QUIT)
continuer = 0;
else if ((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_ESCAPE)) // Toujours pour ceux qui n'ont pas de souris (voir plus haut^^)
continuer = 0;
else if ((event.type == SDL_MOUSEBUTTONDOWN) && (event.button.button == SDL_BUTTON_LEFT)) // Si on a cliqué
{
caseClique.x = event.button.x / TA_SIGNE;
caseClique.y = event.button.y / TA_SIGNE;
caseBlit.x = (caseClique.x * TA_SIGNE) + (LARG_LIGNE_GRILLE * caseClique.x); // Le deuxième terme permet de tenir compte de la ligne noire
caseBlit.y = (caseClique.y * TA_SIGNE) + (LARG_LIGNE_GRILLE * caseClique.y);
if(grille[caseClique.x][caseClique.y] == Vide) // Si la case cliquée est vide
{
grille[caseClique.x][caseClique.y] = tourDeJeu; // On la remplis avec le bon signe
SDL_BlitSurface(signeActuel, NULL, ecran, &caseBlit);
nbCoups --; // On a le doit à 1 coup de moins
if (gagne(caseClique, tourDeJeu, grille))
{
estGagnant(tourDeJeu);
continuer = 0;
if (recommencer())
jeu(surfs); // Si on veut recommencer, on fait un appel récursif
}
if (nbCoups == 0) // Si nbCoups est égal à 0, c'est que a grille est pleine
{
SDL_Flip(ecran);
SDL_WM_SetCaption("Match nul...", NULL);
SDL_Delay(2000);
continuer = 0;
if (recommencer())
jeu(surfs);
}
/* On change la valeur de tourDeJeu */
if (tourDeJeu == Cross)
tourDeJeu = Circle;
else
tourDeJeu = Cross;
}
else
{
SDL_WM_SetCaption("Desole, cette case est prise", NULL);
SDL_Delay(1000);
}
}
SDL_Flip(ecran);
}
}
constante.h
/**
constantes.h
Rôle : Contient toutes les constantes du jeu
*/
#define H_FENETRE 512
#define L_FENETRE 512
#define H_GRILLE 3//
#define L_GRILLE 3//
#define NB_CASES H_GRILLE*L_GRILLE
#define TA_GRILLE 512
#define TA_SIGNE 165 // taille de la croix et du rond
#define LARG_LIGNE_GRILLE 9 // Largeur de la ligne séparant les cases, à prendre en compte lors du blit
typedef enum {Vide, Cross, Circle} Signe; // Indique ce que contient une case du plateau ainsi que le joueur qui doit jouer
typedef struct
{
SDL_Surface *grid;
SDL_Surface *cross;
SDL_Surface *circle;
} Surfaces;
Lien de téléchargement du code, de l'executable et des ressources : zmorpsdl.zip
Pour info, j'avais pas codé le mode console. Ca m'a quand-même pas mal entrainé...
Sinon, Ouah !
J'adore les couleurs que tu as choisis pouet_forever.
nasta > Tu vois, c'est pour ça que j'avais proposé le zMorp console avant celui graphique.
Tu t'es concentré sur la partie graphique et du coup tu as laissé le reste du code. C'est le piège de beaucoup de gens, dommage que tu n'aies pas fait celui en console avant.
Tu peux refaire ton code en console sur le topic que j'ai créé histoire que je commente ton code ? une fois que ce sera fait, normalement ton passage console->graphique se fera rapidement si ton code est bien structuré.
@Nasta: J'ai chargé ton projet pour essayer et chapeau, le résultat final est plutôt sympa.
Je ne regrette pas d'avoir conseillé d'afficher les messages avec SDL_WM_SetCaption, car à l'arrivée ça permet d'avoir une interface honorable sans trop s'embêter.
J'ai fait un screenshot de ton jeu, histoire de.
Après, pour le code, même remarque que celle faite par Pouet_Forever, la logique du jeu est mélangée avec des choses propres à la SDL.
Par exemple.
if(grille[caseClique.x][caseClique.y] == Vide) // Si la case cliquée est vide
{
grille[caseClique.x][caseClique.y] = tourDeJeu; // On la remplis avec le bon signe
SDL_BlitSurface(signeActuel, NULL, ecran, &caseBlit);
Tu maintiens ta grille à jour, et tu blittes par la même occasion.
Selon moi, tu devrais maintenir ta grille à jour, et seulement au moment de l'affichage, blitter les bons signes.
@Pouet:
Je confirme mon enthousiasme, ton code est vraiment bien, j'ai pas grand chose à redire.
Juste, cette manière de faire.
/* affiche(NULL); pour free la surface static */
tu te prend un peu la tête en procédant ainsi, je pense...
Si tu créais tes(ta) surfaces à l'init de ton programme, tu n'aurais pas besoin de ce static.
Mais bon, peut être une question de gouts.
Bah, en fait, je voulais pas passer juste 1 surface à mes fonctions, ça aurait fait dégeux. J'aurais dû utiliser une variable globale, mais sur un forum pour débutant, il vaut mieux éviter de montrer cette pratique.
Mais je suis entièrement d'accord avec toi.
Edit : Et on peut aussi modifier la taille de la grille facilement, sympa, regardez :
Le gagnant, c'est celui qui a la ligne en bas à droite ?
Je trouve que 5 cases, c'est pas assez.
Changement de mon programme pour bien séparer la SDL du reste.
/**
main.c
Rôle : contient les fonctions "de base"
Note : Dans tout le projet, les ligne suivies d'un double-slash '//' sont à modifier dans le cas d'un agrandissement de la grille
*/
#include <stdbool.h>
#include <SDL/SDL.h>
#include "constantes.h"
/* prototypes */
void jeu (Surfaces *surfs);
/* fonctions */
void freeSurfs (Surfaces *surfs) // Libère toutes les surfaces
{
SDL_FreeSurface(surfs->grid);
SDL_FreeSurface(surfs->cross);
SDL_FreeSurface(surfs->circle);
}
void Quit (Surfaces *surfs)
{
freeSurfs(surfs);
SDL_Quit();
}
void initSurfs (Surfaces *surfs) // Initialise la structure surfaces
{
// chargements
surfs->grid = SDL_LoadBMP("Grille.bmp");
surfs->cross = SDL_LoadBMP("croix.bmp");
surfs->circle = SDL_LoadBMP("rond.bmp");
// vérifications
if (surfs->grid == NULL || surfs->cross == NULL || surfs->circle == NULL) // Si un des surfaces n'a pas été chargée
{
fprintf (stderr, "Erreur lors du chargement des images bmp : %s\n", SDL_GetError());
exit (EXIT_FAILURE);
}
// Transparance
SDL_SetColorKey(surfs->cross, SDL_SRCCOLORKEY, SDL_MapRGB(surfs->cross->format, 255, 255, 255));
SDL_SetColorKey(surfs->circle, SDL_SRCCOLORKEY, SDL_MapRGB(surfs->circle->format, 255, 255, 255));
}
int main (int argc, char *argv[]) // Se charge de toutes les initialisations
{
SDL_Surface *ecran = NULL;
Surfaces surfs;
/* Initialisation SDL */
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf (stderr, "Erreur lors du chargement de la SDL : %s\n", SDL_GetError());
exit (EXIT_FAILURE);
}
/* Création de la surface de rendu vidéo */
ecran = SDL_SetVideoMode(L_FENETRE, H_FENETRE, 32, SDL_HWSURFACE | SDL_DOUBLEBUF );
if (ecran == NULL)
{
fprintf (stderr, "Erreur lors de la création de la fenêtre avec 'SDL_SetVideoMode' : %s\n", SDL_GetError());
exit (EXIT_FAILURE);
}
initSurfs(&surfs);
jeu(&surfs);
Quit(&surfs);
return EXIT_SUCCESS;
}
bool gagne (const SDL_Rect lastPlayP, const Signe LastPlayS, Signe grille [][H_GRILLE]) // Cette fonction renvoie tru s'il y a une victoire. Le contexte d'appel permet de définir le gagnant
{
/* On regarde si la ligne du dernier coup est remplie du dernier signe à avoir joué */
if (grille[lastPlayP.x][0] == LastPlayS && grille[lastPlayP.x][1] == LastPlayS && grille[lastPlayP.x][2] == LastPlayS) //
{
return true;
}
if (grille[0][lastPlayP.y] == LastPlayS && grille[1][lastPlayP.y] == LastPlayS && grille[2][lastPlayP.y] == LastPlayS) //
{
return true;
}
/* test des diagnales */
if (grille[0][0] == LastPlayS && grille[1][1] == LastPlayS && grille[2][2] == LastPlayS) //
{
return true;
}
if (grille[0][2] == LastPlayS && grille[1][1] == LastPlayS && grille[2][0] == LastPlayS) //
{
return true;
}
return false;
}
void estGagnant (Signe joueur) // affiche le gagnant
{
if (joueur == Cross)
{
SDL_WM_SetCaption("Les croix ont gagnees ! Bravo !", NULL);
SDL_Delay(2000);
}
else
{
SDL_WM_SetCaption("Les cercles ont gagnes ! Bravo !", NULL);
SDL_Delay(2000);
}
}
bool recommencer () // Retourne true si le joueur veut recommencer
{
SDL_Event event;
SDL_WM_SetCaption("Voulez-vous rejouer ? (o)ui/(n)on", NULL);
while(1)
{
SDL_WaitEvent(&event);
if (event.type == SDL_QUIT)
return false;
if (event.type == SDL_KEYDOWN)
{
if (event.key.keysym.sym == SDLK_o)
return true;
if (event.key.keysym.sym == SDLK_n)
return false;
if (event.key.keysym.sym == SDLK_ESCAPE) // Petite pensée à ceux qui n'ont pas de souris (sisi, ça arrive...)
return false;
}
}
return false; // pour éviter un warning
}
void affiche (Signe grille[][H_GRILLE], Surfaces *surfs)
{
SDL_Surface *ecran = SDL_GetVideoSurface();
SDL_Rect posBlit;
int i, j;
for (i = 0; i < L_GRILLE; i++)
{
for(j = 0; j < H_GRILLE; j++)
{
posBlit.x = (i * TA_SIGNE) + (i * LARG_LIGNE_GRILLE); // Le deuxième terme permet de tenir compte de la ligne noire
posBlit.y = (j * TA_SIGNE) + (j * LARG_LIGNE_GRILLE);
if (grille[i][j] == Cross)
SDL_BlitSurface(surfs->cross, NULL, ecran, &(posBlit));
else if (grille[i][j] == Circle)
SDL_BlitSurface(surfs->circle, NULL, ecran, &(posBlit));
}
}
SDL_Flip(ecran);
}
void jeu (Surfaces *surfs) // Fonction principale du jeu
{
SDL_Rect posZero;
SDL_Rect caseClique; // Indique sur quelle case on a cliqué
SDL_Surface *ecran = SDL_GetVideoSurface();
SDL_Surface *signeActuel; // Cette surface est celle que l'on blittera sur l'ecran. Elle prendra une des valeurs des surfaces de notre structure
SDL_Event event;
Signe tourDeJeu = Cross; // Les croix jouent en premier
bool continuer = true;
int nbCoups = NB_CASES;
Signe grille[L_GRILLE][H_GRILLE] = {{Vide, Vide, Vide},//
{Vide, Vide, Vide},//
{Vide, Vide, Vide}};//
posZero.x = 0;
posZero.y = 0;
SDL_BlitSurface(surfs->grid, NULL, ecran, &posZero); // On blitte la grille à l'écran
while (continuer)
{
if (tourDeJeu == Cross) // On dit qui doit jouer
{
SDL_WM_SetCaption("Aux croix de jouer", NULL);
signeActuel = surfs->cross;
}
else
{
SDL_WM_SetCaption("Aux cercles de jouer", NULL);
signeActuel = surfs->circle;
}
SDL_WaitEvent(&event); // On attend l'évênement
if (event.type == SDL_QUIT)
continuer = 0;
else if ((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_ESCAPE)) // Toujours pour ceux qui n'ont pas de souris (voir plus haut^^)
continuer = 0;
else if ((event.type == SDL_MOUSEBUTTONDOWN) && (event.button.button == SDL_BUTTON_LEFT)) // Si on a cliqué
{
caseClique.x = event.button.x / TA_SIGNE;
caseClique.y = event.button.y / TA_SIGNE;
if(grille[caseClique.x][caseClique.y] == Vide) // Si la case cliquée est vide
{
grille[caseClique.x][caseClique.y] = tourDeJeu; // On la remplis avec le bon signe
nbCoups --; // On a le doit à 1 coup de moins
if (gagne(caseClique, tourDeJeu, grille))
{
affiche(grille, surfs); // On montre bien la situation
estGagnant(tourDeJeu);
continuer = 0;
if (recommencer())
jeu(surfs); // Si on veut recommencer, on fait un appel récursif
}
if (nbCoups == 0) // Si nbCoups est égal à 0, c'est que a grille est pleine
{
affiche(grille, surfs);
SDL_WM_SetCaption("Match nul...", NULL);
SDL_Delay(2000);
continuer = 0;
if (recommencer())
jeu(surfs);
}
/* On change la valeur de tourDeJeu */
if (tourDeJeu == Cross)
tourDeJeu = Circle;
else
tourDeJeu = Cross;
}
else
{
SDL_WM_SetCaption("Desole, cette case est prise", NULL);
SDL_Delay(1000);
}
}
affiche(grille, surfs);
}
}
J'ai pas trouvé d'autres endroits à changer. Le fichier constantes est le même que plus haut.
Maintenant, je vais voir si le passage en console sera difficile ou pas.
(Je sais, je fais tout à l'envers, mais le passage devrais se faire dans les 2 ses si j'ai bien fait non ? )
@Nasta:
tu n'imagines même pas, comment je suis content te voir que tu proposes une seconde version!
Mais, plusieurs trucs ne vont pas.
Mon but pour cet exercice, c'est
->voir que si tu codes un truc console, tu sais le faire avec une autre lib
tu n'as pas séparé grand chose en fait.
Je vais essayé d'être concret, parce que je crois que tu ne vois pas l'intérêt de ce qu'on te dit.(et c'est compréhensible).
Je code pas mal de jeux(petits),et j'ai un objectif de programmeur du Dimanche, qui est :
Si je change de lib graphique:
-SDL
-SFML
-Conio
-etc, etc
mon code doit pouvoir le faire...
et là tu n'as pas le choix, tu dois séparer la logique du jeu, de tout l'enrobage.
j'aime pas la pub, mais regarde le code de Pouet_Forever, je pense, qu'il fait ça(sans être un killer en SDL!))
Encore une fois, je vois bien que je suis un peu sec, touça...
Mais je le répète, Nasta, je suis très content de te voir participer...
et, on va pas me changer en 2011!
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.