Accueil­FAQ­Rechercher­S'enregistrer­Membres­Groupes­Connexion
Poster un nouveau sujet   Répondre au sujetPartager | 
 

 [C][SDL]Demander une chaîne de caractère à l'utilisateur

Voir le sujet précédent Voir le sujet suivant Aller en bas 
AuteurMessage
Rayman3640
Experimenté
Experimenté


Masculin Nombre de messages: 429
Age: 15
Programme utilisé (Gm/RmXp/...): GM7 Pro/gcc/Vim/RM2003/
Etudes: Collégien
Loisirs: Informatique, tennis, lecture, écriture, jeux vidéo, handball
Date d'inscription: 29/04/2008

MessageSujet: [C][SDL]Demander une chaîne de caractère à l'utilisateur   Sam 30 Mai - 13:41

Bonjour,

Dans le cadre de mon projet (voir signature), j'ai dû créer un système permettant de simuler une zone de texte avec la SDL. Comme je l'ai fini, je vous le propose ici, afin que vous puissiez l'utiliser dans vos projets. Je suis ouvert à tout commentaire !

Prérequis
Avoir installé la SDL, SDL_Image et SDL_TTF.

Installation
Ajoutez ces deux fichiers à votre projet :

Code:
/*
zonetexte.c
Par Rayman3640
Rôle : permettre au créateur de simuler des zones de texte avec la SDL
*/

#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <SDL/SDL_image.h>
#include "zonetexte.h"

void lireDonneeZoneTexte(SDL_Surface *surface, TTF_Font *police, char *chaineEntree, char *introductionInitiale, char *texteDePreremplissage, long nombreDeCaracteresMaximal)
{
   int continuer = 1, majuscule = 0;
   char introduction[100] = "", chaineFinale[100] = "";
   SDL_Surface *texte, *barre = NULL;
   SDL_Color noir = {0,0,0};
   SDL_Rect positionTexte;
   long positionCaractere = 0;
   SDL_Event event;
   barre = IMG_Load("Curseur.png");
   detecterErreurs(surface,barre,police,chaineEntree,texteDePreremplissage,nombreDeCaracteresMaximal);
   strcpy(introduction,introductionInitiale);
   strcpy(chaineEntree,texteDePreremplissage);
   positionCaractere = strlen(chaineEntree);
   SDL_FillRect(surface,NULL,SDL_MapRGB(surface->format,255,255,255));
   SDL_EnableKeyRepeat(100,100);
   SDL_Flip(surface);
   while(continuer)
   {
      SDL_WaitEvent(&event);
      switch(event.type)
      {
         case SDL_QUIT:
            continuer = 0;
            break;
         case SDL_KEYDOWN:
            lireCaractereZoneTexte(event,&majuscule,chaineEntree,&positionCaractere,&continuer,nombreDeCaracteresMaximal);
            strcat(introduction,chaineEntree);
            strcpy(chaineFinale,introduction);
            strcpy(introduction,introductionInitiale);
            break;
      }
      if(strlen(chaineFinale) <= 0)
      {
         strcat(introduction,chaineEntree);
         strcpy(chaineFinale,introduction);
         strcpy(introduction,introductionInitiale);
      }
      texte = TTF_RenderUTF8_Solid(police,chaineFinale,noir);
      positionTexte.x = 0;
      positionTexte.y = 0;
      SDL_BlitSurface(texte,NULL,surface,&positionTexte);
      blitterCurseur(chaineFinale,&positionTexte,police,introduction,chaineEntree,surface,barre, positionCaractere);
      SDL_Flip(surface);
      SDL_FillRect(surface,NULL,SDL_MapRGB(surface->format,255,255,255));
   }
   SDL_FreeSurface(texte);
   SDL_FreeSurface(barre);

}

void detecterErreurs(SDL_Surface *surface, SDL_Surface *barre, TTF_Font *police, char *chaineEntree, char *texteDePreremplissage, long nombreDeCaracteresMaximal)
{
   if(surface == NULL)
   {
      fprintf(stderr,"Le pointeur sur surface vaut NULL, donc le texte ne peut pas être affiché à l'écran.\n");
      exit(EXIT_FAILURE);
   }
   if(barre == NULL)
   {
      fprintf(stderr,"Erreur lors de l'ouverture de l'image Curseur.png: %s\n",SDL_GetError());
      exit(EXIT_FAILURE);
   }
   if(police == NULL)
   {
      fprintf(stderr,"Le pointeur sur police vaut NULL, donc aucune police ne peut être ouverte.\n");
      exit(EXIT_FAILURE);
   }
   if(chaineEntree == NULL)
   {
      fprintf(stderr,"La chaîne entrée vaut NULL, donc l'utilisateur ne peut rentrer aucune chaîne.\n");
      exit(EXIT_FAILURE);
   }
   if(nombreDeCaracteresMaximal < 1)
   {
      fprintf(stderr,"La taille maximale est nulle, donc l'utilisateur ne peut entrer aucune chaîne.\n");
      exit(EXIT_FAILURE);
   }
   if(texteDePreremplissage != NULL && strlen(texteDePreremplissage) > nombreDeCaracteresMaximal)
   {
      fprintf(stderr,"Le nombre de caractères du texte de préremplissage est supérieur au nombre de caractères maximal.\n");
      exit(EXIT_FAILURE);
   }

}

void blitterCurseur(char *chaineFinale, SDL_Rect *positionTexte, TTF_Font *police, char *introduction, char *chaineEntree, SDL_Surface *surface, SDL_Surface *barre, long positionCaractere)
{
   int longueurSurfaceTexte = 0, longueurSurfaceTexte2 = 0, longueurSurfaceTexte3 = 0, largeurSurfaceTexte = 0;
   SDL_Rect positionBarre;
   if(strlen(chaineFinale) > 0)
   {
      positionBarre.x = positionTexte->x;
      if(TTF_SizeUTF8(police,introduction,&longueurSurfaceTexte,&largeurSurfaceTexte) == 0)
      {
         positionBarre.x += longueurSurfaceTexte;
         longueurSurfaceTexte = 0;
      }
      if(TTF_SizeUTF8(police,chaineEntree,&longueurSurfaceTexte2,&largeurSurfaceTexte) == 0)
      {
         if(TTF_SizeUTF8(police,&chaineEntree[positionCaractere],&longueurSurfaceTexte3,&largeurSurfaceTexte) == 0)
         {
            longueurSurfaceTexte = longueurSurfaceTexte2 - longueurSurfaceTexte3;
         }
         positionBarre.x += longueurSurfaceTexte;
      }
      positionBarre.y = positionTexte->y;
      SDL_BlitSurface(barre,NULL,surface,&positionBarre);
   }

}

void lireCaractereZoneTexte(SDL_Event event, int *majuscule, char *chaine, long *positionCaractere, int *continuer, long nombreDeCaracteresMaximal)
{
   char caractereEntre = 0;
   int lettreEntree = 0, diminuerPositionCaractere = 1;
   long i = 0;
   if(event.key.keysym.mod & KMOD_SHIFT)
   {
      *majuscule = 1;
   }
   else
   {
      *majuscule = 0;
   }
   switch(event.key.keysym.sym)
   {
      case SDLK_LEFT:
         if(*positionCaractere > 0)
            *positionCaractere -= 1;
         break;
      case SDLK_RIGHT:
         if(*positionCaractere < strlen(chaine))
            *positionCaractere += 1;
         break;
      case SDLK_BACKSPACE:
         if(*positionCaractere > 0)
         {
            for(i = *positionCaractere - 1; i < strlen(chaine); i++)
            {
               if(i > -1)
                  chaine[i] = chaine[i+1];
               else
                  diminuerPositionCaractere = 0;
            }
            if(diminuerPositionCaractere)
               *positionCaractere -= 1;
            else
               *positionCaractere = 1;
         }
         break;
      case SDLK_ESCAPE:
         *continuer = 0;
         break;
      case SDLK_RETURN:
         *continuer = 0;
         break;
      default:
         break;
   }
   detecterLettre(event,&lettreEntree,&caractereEntre,majuscule);
   if(lettreEntree == 1 && strlen(chaine) <= nombreDeCaracteresMaximal)
   {
      insererCaractereDansChaine(*positionCaractere,chaine,caractereEntre);
      *positionCaractere += 1;
   }
}

void detecterLettre(SDL_Event event, int *lettreEntree, char *caractereEntre, int *majuscule)
{
   long i = 0;
   for(i = 0; i < 26; i++) //Lettres sans accents minuscules et majuscules
   {
      if(event.key.keysym.sym == SDLK_a + i)
      {
         entrerLettre(lettreEntree,65 + i,caractereEntre);
         if(!(*majuscule))
         {
            *caractereEntre += 32;
         }
         break;
      }
   }
   for(i = 0; i < 27; i++)
   {
      if(event.key.keysym.sym == SDLK_AMPERSAND + i)
      {
         entrerLettre(lettreEntree,38 + i,caractereEntre);
      }
   }
   for(i = 0; i < 5; i++)
   {
      if(event.key.keysym.sym == SDLK_SPACE + i)
      {
         entrerLettre(lettreEntree,32 + i,caractereEntre);
      }
   }
   switch(event.key.keysym.sym) //Caractères spéciaux
   {
      case SDLK_BACKSLASH:
         entrerLettre(lettreEntree,92,caractereEntre);
         break;
      default:
         break;
   }
   for(i = 0; i < 10; i++)
   {
      if(event.key.keysym.sym == SDLK_KP0 + i) //Nombres du pavé numérique
      {
         entrerLettre(lettreEntree,48 + i,caractereEntre);
      }
   }

}

void entrerLettre(int *lettreEntree, long numeroCaractere, char *caractere)
{
   if(!(*lettreEntree))
   {
      *lettreEntree = 1;
      *caractere = numeroCaractere;
   }
}

void insererCaractereDansChaine(long positionCaractere, char *chaine, char caractereAInserer)
{
   char chaine2[100] = "";
   strcpy(chaine2,&chaine[positionCaractere]);
   chaine[positionCaractere] = caractereAInserer;
   strcpy(&chaine[positionCaractere+1],chaine2);
}



Code:

/*
zonetexte.h
Par Rayman3640
Rôle : définir les fonctions utilisées par le fichier de lecture de chaînes au clavier
*/

#ifndef DEF_ZONETEXTE
   #define DEF_ZONETEXTE
   #include <SDL/SDL.h>
   void lireDonneeZoneTexte(SDL_Surface *surface, TTF_Font *police, char *chaineEntree, char *introductionInitiale, char *texteDePreremplissage, long nombreDeCaracteresMaximal);
   void detecterErreurs(SDL_Surface *surface, SDL_Surface *barre, TTF_Font *police, char *chaineEntree, char *texteDePreremplissage, long nombreDeCaracteresMaximal);
   void lireCaractereZoneTexte(SDL_Event event, int *majuscule, char *chaine, long *positionCaractere, int *continuer, long nombreDeCaracteresMaximal);
   void entrerLettre(int *lettreEntree, long numeroCaractere, char *caractere);
   void insererCaractereDansChaine(long positionCaractere, char *chaine, char caractereAInserer);
   void blitterCurseur(char *chaineFinale, SDL_Rect *positionTexte, TTF_Font *police, char *introduction, char *chaineEntree, SDL_Surface *surface, SDL_Surface *barre, long positionCaractere);
   void detecterLettre(SDL_Event event, int *lettreEntree, char *caractereEntre, int *majuscule);

#endif


Ensuite, dans le même dossier que vos sources, ajoutez cette image, que vous nommerez Curseur.png :

Utilisation
Pour récupérer une chaîne de caractères, utilisez la fonction lireDonneeZoneTexte, qui fonctionne comme ceci :
Code:

void lireDonneeZoneTexte(SDL_Surface *surface, TTF_Font *police, char *chaineEntree, char *introductionInitiale, char *texteDePreremplissage, long nombreDeCaracteresMaximal);


  • SDL_Surface *surface est le pointeur sur la surface où le texte doit être écrit
  • TTF_Font *police est la police à utiliser
  • char *chaineEntree est la chaîne qui contiendra ce qu'à entré l'utilisateur
  • char *introductionInitiale est le texte affiché avant la zone de texte (par exemple "NOM: " ou encore "Adresse: "),
  • char *texteDePreremplissage est le texte mis par défaut dans la zone de texte
  • long nombreDeCaracteresMaximal est le nombre maximal de caractères que l'utilisateur peut taper (attention, le caractère /0 ne doit pas être inclus dans le nombre)


N'oubliez pas d'inclure zonetexte.h !
Code:

#include "zonetexte.h"


Exemple
Code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <SDL/SDL_image.h>
#include "zonetexte.h"

int main(int argc, char *argv[])
{
   SDL_Surface *ecran = NULL;
   int continuer = 1;
   char chaine[100] = "";
   TTF_Font *police = NULL;
   if(SDL_Init(SDL_INIT_VIDEO) == -1)
   {
      fprintf(stderr,"Erreur lors de l'initialisation de la SDL : %s\n",SDL_GetError());      
      exit(EXIT_FAILURE);
   }
   if(TTF_Init() == -1)
   {
      fprintf(stderr,"Erreur lors de l'initialisation de SDL_TTF : %s\n",TTF_GetError());      
      exit(EXIT_FAILURE);
   }
   police = TTF_OpenFont("RostockKaligraph.ttf",40);
   if(police == NULL)
   {
      fprintf(stderr,"Erreur police : %s",TTF_GetError());
      exit(EXIT_FAILURE);
   }
    ecran = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE);
   SDL_WM_SetCaption("Demander une chaîne de caractères à l'utilisateur", NULL);
   SDL_FillRect(ecran,NULL,SDL_MapRGB(ecran->format,255,255,255));
   SDL_Flip(ecran);
   while (continuer)
   {
      lireDonneeZoneTexte(ecran,police,chaine,"Mon site préféré : ","Le Site du Zer0",99);
      continuer = 0;
       }
   TTF_CloseFont(police);
   TTF_Quit();
       SDL_Quit();
       return EXIT_SUCCESS;
}


Remarques

  • J'espère que l'implémentation se fera sans problème, car je n'ai pas essayé mon système séparément de mon projet.
  • Pour faire une lettre majuscule, je n'ai pas réussi à utiliser le KMOD_CAPS, il faut donc faire Shift + Lettre à mettre en majuscule.
  • Je n'ai pas mis une grande variété de caractères (c'est long et chiant à faire ! :p ) : seulement les lettres (sans accents), les chiffres et quelques autres caractères. Mais si vous le désirez, vous pouvez modifier la fonction detecterLettre pour cela. ;)

_________________

Supra-Quest, un jeu vidéo concentrant une aventure épique, un monde presque sans limites à découvrir et un système de combat novateur !
N'oubliez pas de visiter le SQ-Devblog, le blog de développement du jeu !
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nintendo3000.goldzoneweb.info
Xierra54
Admin - .: el traductor :.
Admin - .: el traductor :.


Masculin Nombre de messages: 8504
Age: 50
Programme utilisé (Gm/RmXp/...): GM (6.1 et 7 enregistrées), Purebasic (démo)
Etudes: Supérieures
Loisirs: ordinateur
Date d'inscription: 13/08/2005

MessageSujet: Re: [C][SDL]Demander une chaîne de caractère à l'utilisateur   Dim 31 Mai - 13:10

En tout cas, bravo Rayman3640 pour ta réalisation et tes connaissances en C.

A+

_________________
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://philippe.ragni.free.fr/
Rayman3640
Experimenté
Experimenté


Masculin Nombre de messages: 429
Age: 15
Programme utilisé (Gm/RmXp/...): GM7 Pro/gcc/Vim/RM2003/
Etudes: Collégien
Loisirs: Informatique, tennis, lecture, écriture, jeux vidéo, handball
Date d'inscription: 29/04/2008

MessageSujet: Re: [C][SDL]Demander une chaîne de caractère à l'utilisateur   Dim 31 Mai - 13:25

Merci ! :)
J'ai pris du temps à apprendre ce langage, mais maintenant, je peux faire ce que je veux avec. ;)

_________________

Supra-Quest, un jeu vidéo concentrant une aventure épique, un monde presque sans limites à découvrir et un système de combat novateur !
N'oubliez pas de visiter le SQ-Devblog, le blog de développement du jeu !
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nintendo3000.goldzoneweb.info
Fireranger
Possedé par Mark Overmars
Possedé par Mark Overmars


Masculin Nombre de messages: 1360
Age: 16
Programme utilisé (Gm/RmXp/...): Game Maker 7 PRO, Visual Basic 9.0, Visual C++ et Code::Blocks
Date d'inscription: 22/11/2007

MessageSujet: Re: [C][SDL]Demander une chaîne de caractère à l'utilisateur   Lun 1 Juin - 22:50

C'est très bien. Maintenat, prochaine étape, le faire sans la librairie SDL_TTF :P Tu peux aussi ajouter un paramètre pour la couleur, la taille de la police, etc. à moins que ça ne fasse partie de la police déjà ^^

Bonne continuation !

_________________
Guten Tag von Deutschland ^^


Jeu en cours : Ping Pong C++ en open source
Bibliothèque : SFML
Avancement : |||||||||| 100% !!!
Revenir en haut Aller en bas
Voir le profil de l'utilisateur
kimerafusion
Possedé par Mark Overmars
Possedé par Mark Overmars


Masculin Nombre de messages: 1622
Programme utilisé (Gm/RmXp/...): gamemaker 7.0 pro, code::blocks, adobe dreamweaver, gnu-gcc
Etudes: futur ingénieur logiciel (j'aimerais bien bosser sur de la nanotechnologie, biotechnologie ou autres), seconde GT
Loisirs: jeux-vidéos - programmation (C/C++, Qt, SDL)
Date d'inscription: 14/10/2008

MessageSujet: Re: [C][SDL]Demander une chaîne de caractère à l'utilisateur   Mar 2 Juin - 18:17

La SDL, c'est vraiment bien trop compliqué pour moi... il me faudrait un prof plutôt qu'une page à lire :P
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://kimerafusion.dixkey.com/
Rayman3640
Experimenté
Experimenté


Masculin Nombre de messages: 429
Age: 15
Programme utilisé (Gm/RmXp/...): GM7 Pro/gcc/Vim/RM2003/
Etudes: Collégien
Loisirs: Informatique, tennis, lecture, écriture, jeux vidéo, handball
Date d'inscription: 29/04/2008

MessageSujet: Re: [C][SDL]Demander une chaîne de caractère à l'utilisateur   Mar 2 Juin - 21:17

Fireranger a écrit:
C'est très bien. Maintenat, prochaine étape, le faire sans la librairie SDL_TTF :P Tu peux aussi ajouter un paramètre pour la couleur, la taille de la police, etc. à moins que ça ne fasse partie de la police déjà ^^

Bonne continuation !
Merci ! ^^
Et oui, l'utilisateur (enfin, le programmeur) peut paramétrer la police pour changer la taille et la couleur.

kimerafusion a écrit:
La SDL, c'est vraiment bien trop compliqué pour moi... il me faudrait un prof plutôt qu'une page à lire :P
Moyennant 10€ / minute, je peux t'aider. :D




Je posterai bientôt mon éditeur de niveaux pour RPG fait avec la SDL sur le forum. Peut-être dans une semaine (ou deux)...

_________________

Supra-Quest, un jeu vidéo concentrant une aventure épique, un monde presque sans limites à découvrir et un système de combat novateur !
N'oubliez pas de visiter le SQ-Devblog, le blog de développement du jeu !
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nintendo3000.goldzoneweb.info
kimerafusion
Possedé par Mark Overmars
Possedé par Mark Overmars


Masculin Nombre de messages: 1622
Programme utilisé (Gm/RmXp/...): gamemaker 7.0 pro, code::blocks, adobe dreamweaver, gnu-gcc
Etudes: futur ingénieur logiciel (j'aimerais bien bosser sur de la nanotechnologie, biotechnologie ou autres), seconde GT
Loisirs: jeux-vidéos - programmation (C/C++, Qt, SDL)
Date d'inscription: 14/10/2008

MessageSujet: Re: [C][SDL]Demander une chaîne de caractère à l'utilisateur   Mer 3 Juin - 13:52

waow stylé t'es vraiment trop fort combien d'heures ça t'a prit de faire un éditeur de RPG?
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://kimerafusion.dixkey.com/
Rayman3640
Experimenté
Experimenté


Masculin Nombre de messages: 429
Age: 15
Programme utilisé (Gm/RmXp/...): GM7 Pro/gcc/Vim/RM2003/
Etudes: Collégien
Loisirs: Informatique, tennis, lecture, écriture, jeux vidéo, handball
Date d'inscription: 29/04/2008

MessageSujet: Re: [C][SDL]Demander une chaîne de caractère à l'utilisateur   Mer 3 Juin - 13:57

Pas tant que ça. Enfin ça dépend si tu comptes le temps que j'ai pris pour faire ce système de zone de texte, car la gestion des chaînes de caractères en C est assez corsée... J'ai dû fouiller dans la doc de SDL TTF, faire un système de curseur, etc.

Pour le moment je suis (assez) loin d'avoir fini l'éditeur mais je pense que j'y aurai passé 7-10h (peut-être que je me trompe complètement).

_________________

Supra-Quest, un jeu vidéo concentrant une aventure épique, un monde presque sans limites à découvrir et un système de combat novateur !
N'oubliez pas de visiter le SQ-Devblog, le blog de développement du jeu !
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nintendo3000.goldzoneweb.info
 

[C][SDL]Demander une chaîne de caractère à l'utilisateur

Voir le sujet précédent Voir le sujet suivant Revenir en haut 
Page 1 sur 1

Permission de ce forum:Vous pouvez répondre aux sujets dans ce forum
Game Maker Zone :: Programmation/Graphisme :: Langages de programmation :: C et C++-
Poster un nouveau sujet   Répondre au sujet