J'avoue, moi aussi j'ai triché pour voir où était la clé. C'est juste impossible de la trouver sans, à mon avis...
Par contre j'ai trouvé un petit bug: si on s'enferme dans la salle du couteau, ça débloque une issue sud et le programme plante quand on y va ou qu'on la fouille.
Je vais présenter pendant quelques temps des fonctions permettant d'imiter avec SDL_TTF, les entrées/sorties qu'on peut réaliser en console.
Je considère que tout le monde sait comment:
-initaliser SDL_TTF
-charger une fonte.
Si ce n'est pas le cas, c'est expliqué dans le tuto C partie SDL du SDZ.
SDL_TTF permet de manière portable, d'afficher des caractères accentués.
je ne vais pas me priver d'utiliser cette possibilité.
Par contre, les codes proposés seront en C99, pour pouvoir profiter des wchar_t.
void Font_puts(TTF_Font *font, SDL_Surface *dst, int x, int y, SDL_Color fg, wchar_t const *buf)
{
SDL_Rect pos;
pos.x = x;
pos.y = y;
/* Tant que le caractère courant n'est pas '\0' */
while(*buf != '\0')
{
wchar_t crtChar[2] = {L'0'};
/* On crée un chaine composée uniquement du caractère courant, */
crtChar[0] = *buf;
if(pos.x >= dst->w || crtChar[0] == L'\n')
{
/* On se place au début de la ligne suivante */
pos.x = 0;
pos.y += TTF_FontLineSkip(font);
}
if(crtChar[0] != L'\n')
{
SDL_Surface *tmp = TTF_RenderUNICODE_Solid(font,
(Uint16 *)crtChar,
fg);
SDL_BlitSurface(tmp, NULL, dst, &pos);
SDL_FreeSurface(tmp);
pos.x += tmp->w;
}
/* On passe au caractère suivant */
buf++;
}
}
On lit simplement les caractères de la chaîne buf 1 à 1, et tant que ce n'est pas le '\0' final:
-Si on dépasse de l'écran en x, ou que le caractère lu est '\n', on passe a la ligne suivante, et on se replace à 0 en x.
-Si le caractère lu n'est pas '\n', on l'affiche et on avance en x de la valeur de ce caractère.
La fonction TTF_FontLineSkip retourne la hauteur recommandée d'une ligne de texte rendu avec la fonte passée en argument.
Maintenant qu'on a notre puts, il est facile de faire
void Font_printf(TTF_Font *f, SDL_Surface *dst, int x, int y, SDL_Color fg, wchar_t const *format, ...)
{
wchar_t buf[512];
va_list ap;
va_start(ap, format);
vswprintf(buf, sizeof(buf), format, ap);
va_end(ap);
Font_puts(f, dst, x, y, fg, buf);
}
Pour comprendre cette fonction il faut savoir utiliser les fonctions à paramètres optionnels.
Je ne vais pas me lancer dans une explication sur le sujet, car
- Ma fonction fait le minimum
- encore une fois c'est expliqué dans les tuto du SDZ.
edit:
La fonction vswprintf est inconnue sous Windows, il faut utiliser la fonction _vsnwprintf à la place.
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <wchar.h>
#define CHECK(cond) \
do \
{ \
if(!(cond)) \
{ \
fprintf(stderr, "%s %s %u", \
SDL_GetError(), \
__FILE__, \
__LINE__); \
exit(EXIT_FAILURE); \
} \
}while(0)
#ifdef __WIN32__
#define vswprintf _vsnwprintf
#endif
#define W 800
#define H 600
#define BPP 32
void Font_puts(TTF_Font *font, SDL_Surface *dst, int x, int y, SDL_Color fg, wchar_t const *buf)
{
SDL_Rect pos;
pos.x = x;
pos.y = y;
/* Tant que le caractère courant n'est pas '\0' */
while(*buf != '\0')
{
wchar_t crtChar[2] = {L'0'};
/* On crée un chaine composée uniquement du caractère courant, */
crtChar[0] = *buf;
if(pos.x >= dst->w || crtChar[0] == L'\n')
{
/* On se place au début de la ligne suivante */
pos.x = 0;
pos.y += TTF_FontLineSkip(font);
}
if(crtChar[0] != L'\n')
{
SDL_Surface *tmp = TTF_RenderUNICODE_Solid(font,
(Uint16 *)crtChar,
fg);
SDL_BlitSurface(tmp, NULL, dst, &pos);
SDL_FreeSurface(tmp);
pos.x += tmp->w;
}
/* On passe au caractère suivant */
buf++;
}
}
void Font_printf(TTF_Font *f, SDL_Surface *dst, int x, int y, SDL_Color fg, wchar_t const *format, ...)
{
wchar_t buf[512];
va_list ap;
va_start(ap, format);
vswprintf(buf, sizeof(buf), format, ap);
va_end(ap);
Font_puts(f, dst, x, y, fg, buf);
}
void pause(void)
{
SDL_Event ev;
while(SDL_WaitEvent(&ev) && ev.type != SDL_KEYDOWN)
;
}
int main(int argc, char *argv[])
{
SDL_Surface *screen;
const SDL_Color white = {255, 255, 255, 0};
TTF_Font *font;
CHECK(SDL_Init(SDL_INIT_VIDEO) == 0);
CHECK(screen = SDL_SetVideoMode(W, H, BPP, SDL_SWSURFACE));
CHECK(TTF_Init() == 0);
CHECK(font = TTF_OpenFont("FreeMono.ttf", 12));
Font_puts(font, screen, 0, 0, white,
L"L'implémentation de la quasi totalité des processeurs qui "
"équipent les ordinateurs est de nature impérative : ils sont "
"faits pour exécuter du code écrit sous forme d'opcodes "
"(pour operation codes), qui sont des instructions élémentaires "
"exécutables par le processeur. L'ensemble des opcodes forme le "
"langage machine spécifique au processeur et à son architecture. "
"L'état du programme à un instant donné est défini par le contenu "
"de la mémoire centrale à cet instant, et le programme lui-même "
"est écrit en style impératif en langage machine, ou le plus "
"souvent dans une traduction lisible par les humains du langage "
"machine, dénommée assembleur. \n\n"
"Les langages de plus haut niveau utilisent des variables et des "
"opérations plus complexes, mais suivent le même paradigme. Les "
"recettes de cuisine et les vérifications de processus industriel "
"sont deux exemples de concepts familiers qui s'apparentent à de "
"la programmation impérative ; de ce point de vue, chaque étape "
"est une instruction, et le monde physique constitue l'état "
"modifiable. Puisque les idées basiques de la programmation "
"impérative sont à la fois conceptuellement familières et "
"directement intégrées dans l'architecture des microprocesseurs, "
"la grande majorité des langages de programmation sont impératifs."
);
Font_printf(font, screen, 0, 40 * TTF_FontLineSkip(font), white,
L"Un test avec un printf accentué\n : %d %d\n", 3, 4);
SDL_Flip(screen);
pause();
TTF_CloseFont(font);
TTF_Quit();
SDL_Quit();
return 0;
}
Ces fonctions ont un nombre de paramètres probablement trop important.
On peut imaginer diverses améliorations, par exemple, attacher les fontes à une fenêtre et avoir un curseur par fenêtre.
Partant de là on pourrait avoir l'interface:
Win_setFont(Win *win, TTF_Font *font);
Win_locate(Win *win, int x, int y);
Win_setFontColor(Win *win, SDL_Color color);
La prochaine fois ce sera getchar() et ungetc() version SDL_TTF.
edit:
Correction du code d'exemple, il manquait le TTF_CloseFont.
Bien joué !
J'avais déjà fais une fonction du style de Font_puts() avec TTF_FontLineSkip() mais en moins bien (cela va de soit, surtout que c'était il y a plus de 5-6 mois).
Au fait, dans les explication, tu as mis "TTF_LineSkip".
Je vais mettre ce code là avec quelques petites modifications et des explications un peu différentes dans ma bio en te citant, si ça ne te dérange pas bien sûr.
Très bel exemple mise à part que la police est moche
Je ne connaissais pas la fonction TTF_FontLineSkip, elle est franchement pratique.
Sinon, je me trompe peut-être mais ce code fonctionne sous Windows? Parce qu'en encodant le fichier source en utf-8, les chaîne de multicaractères sont encodées en utf-8 (cela évite déjà quelques ennuis), cependant le type wchar_t aura une taille de 1 octets (encodage Windows-1252), ce qui risque de poser problème...
Aussi, par curiosité, lorsque tu programme sans SDL_ttf, tu gères également les accents?
Pour les accents, je t'avoue que je ne me suis jamais penché sur le problème avec une fonte bitmap.
Je teste mon exemple sous Windows, et j'édite(et si je pouvais éviter l'UTF8, ce serait pas mal ).
edit:
Alors!
Avec mingw32, la fonction vswprintf est inconnue au bataillon.
J'ai un soucis, pas d'internet sous Windows.
Donc, je cherche une solution pour Windows(sous Ubuntu), et j'édite.
Avec mingw32, la fonction vswprintf est inconnue au bataillon.
Ah bon ?!
Si je ne me trompe pas, une solution simple serait de stocker le texte sous forme de chaîne de caractères simple, mais d'encoder le fichier en utf-8 (sans BOM). Ainsi, il suffit d'utiliser la fonction TTF_RenderUTF8_Solid.
Du côté de la fonction Font_printf, il suffit de modifier cette dernière pour qu'elle manipule des chaîne des caractères simples. En effet, du moment que le format ne contient pas des caractères non ASCII cela ne pose pas de problème étant donné la correspondance avec l'uft-8
EDIT: je reprends ma deuxième phrase parce qu'elle n'est pas clair
Ce que je veux dire, c'est qu'utiliser cette fonction pour ajouter un nombre sous forme de chaîne à une chaîne déjà encodée en utf-8 ne pose pas de problème puisque toutes les lettres de la table ASCII conserve leur valeur en utf-8.
Avec mingw32, la fonction vswprintf est inconnue au bataillon.
J'ai un soucis, pas d'internet sous Windows.
Donc, je cherche une solution pour Windows(sous Ubuntu), et j'édite.
Essaye avec vsnwprintf(wchar_t*,size_t,constwchar_t*,__VALIST).
EDIT : Ah et aussi j'ai essayé de modifier la fonction Font_puts pour qu'elle évite de couper les mots en plein milieu. C'est du C++ mais ca devrait pas être trop dur à adapter en C. L'idée consiste à anticiper sur la longeur du mot :
void Font_puts(TTF_Font *font, SDL_Surface *dst, int x, int y, SDL_Color color, string buf)
{
SDL_Rect pos;
pos.x = x;
pos.y = y;
for (unsigned i = 0; i < buf.length(); ++i)
{
if(pos.x >= dst->w && buf[i] == '\n')
{
pos.x = x;
pos.y += TTF_FontLineSkip(font);
}
if(buf[i] != '\n')
{
unsigned int j = i;
int curpos = pos.x;
string av = "";
char c = buf[j];
while (c != ' ' && j < buf.length())
{
av = "";
av.push_back(c);
SDL_Surface *tmp = TTF_RenderText_Solid(font,av.c_str(),color);
curpos += tmp->w;
j++;
c = buf[j];
}
if (curpos >= dst->w)
{
pos.x = x;
pos.y += TTF_FontLineSkip(font);
}
string cur = "";
cur.push_back(buf[i]);
SDL_Surface *tmp = TTF_RenderText_Blended(font,cur.c_str(),color);
SDL_BlitSurface(tmp, NULL, dst, &pos);
SDL_FreeSurface(tmp);
pos.x += tmp->w;
}
}
}
In function 'Font_printf':|
main.c|65|warning: passing argument 2 of 'vswprintf' makes pointer from integer without a cast|
include\stdio.h|578|note: expected 'const wchar_t *' but argument is of type 'unsigned int'|
main.c|65|warning: passing argument 3 of 'vswprintf' from incompatible pointer type|
include\stdio.h|578|note: expected '__gnuc_va_list' but argument is of type 'const wchar_t *'|
main.c|65|error: too many arguments to function 'vswprintf'|
main.c||In function 'SDL_main':|
main.c|119|warning: passing argument 6 of 'Font_printf' from incompatible pointer type|
main.c|59|note: expected 'const wchar_t *' but argument is of type 'char *'|
||=== Build finished: 1 errors, 5 warnings ===|
Alors que sous ubuntu, j'ai 2 warnings(argc, et argv pas utilisés.)
Je suis dessus, pour essayer de résoudre le problème.
@_Fender_:
Sauf que sous Ubuntu ça fonctionne pas.
Après, à coup de prépro, on doit pouvoir s'en sortir!
Merci pour le test.
edit2: j'avais pas vu, désolé
@_Fender:
Citation : _Fender_
Ah et aussi j'ai essayé de modifier la fonction Font_puts pour qu'elle évite de couper les mots en plein milieu. C'est du C++ mais ca devrait pas être trop dur à adapter en C. L'idée consiste à anticiper sur la longeur du mot :
La fonction puts, ne coupe pas les mots?
Sinon, bien vu.
C'était un exercice proposé par candide qui se nommait zJustificator(tu vas voir que c'est pas simple. :))
Pour ce que je propose:
lorsque ça fonctionne , je propose une base, mais vraiment une base.
Libre à vous d'améliorer le truc, et effectivement l'amélioration que tu propose peut être une priorité.
A l'occasion, je met un lien vers ton code.
J'ai enfin essayé ce petit jeu (mais pas encore regardé le code). Ce serait sympa d'avoir des images comme dans "The Pawn", "The Guild of Thieves", "Jinxter" et autres jeux FireBird de l'époque (du ST). Vivement la version SDL !
(Bon, pas exactement comme le ST vu qu'il n'y avait que 16 couleurs ! )
Le coup de la clef est quand même bien vicieux, je n'ai pas trouvé sans regarder dans le code de la salle...
Par contre, j'ai trouvé le petit souci suivant avec le couteau, qu'on trouve sans arrêt mais qu'on ne peut ramasser qu'une fois (à moins que je n'ai pas pris la bonne version ?) :
Direction possibles : Sud Est Ouest
>examiner
Il y a une porte derriere vous.
Direction possibles : Sud Est Ouest
>sud
Direction possibles : Nord
>examiner
En fouillant partout, vous trouvez un couteau.
Direction possibles : Nord
>prendre couteau
Vous vous enrichissez!
Direction possibles : Nord
>examiner
En fouillant partout, vous trouvez un couteau.
Direction possibles : Nord
>prendre couteau
Pas touche l'ami!
Direction possibles : Nord
>nord
Direction possibles : Sud Est Ouest
>poser couteau
Vous voila plus leger!
Direction possibles : Sud Est Ouest
>sud
Direction possibles : Nord
>examiner
En fouillant partout, vous trouvez un couteau.
Direction possibles : Nord
>prendre couteau
Pas touche l'ami!
Direction possibles : Nord
>
Mais sinon, c'est sympa ! Et la fin est très drôle !
Clément.
Edit :
Petit bug, j'ai le même souci que le couteau avec la clef :
Direction possibles : Ouest
>examiner mur
Une cle est accrochee au mur
Direction possibles : Ouest
>prendre clef
Vous vous enrichissez!
Direction possibles : Ouest
>ouest
Direction possibles : Est Ouest
>poser clef
Vous voila plus leger!
Direction possibles : Est Ouest
>est
Direction possibles : Ouest
>examiner mur
Une cle est accrochee au mur
Direction possibles : Ouest
>prendre clef
Pas touche l'ami!
Direction possibles : Ouest
>
Edit 2 :
Pour la clef, je crois qu'on peut rajouter 'estPresent' dans le premier 'if' de la salle5 :
/* L'entrée */
static int salle5(int idAct, int idObj)
{
if(idAct == ACT_EXAMINER && idObj == OBJ_MUR && !estPossede(OBJ_CLE) && estPresent(5, OBJ_CLE))
{
puts("Une cle est accrochee au mur");
rendreAccessible(OBJ_CLE);
}
else if(idAct == ACT_AIDE)
{
puts("Les murs, les murs...");
}
else
erreur(idAct);
return 0;
}
Edit 3 :
Pour le couteau, on doit pouvoir changer le dernier 'if' de la salle7 comme suit :
Merci pour le test!
Du coup même avec un jeu de 5 salles et 2 objets, j'ai réussi à me planter.
Pour la version SDL, je vais juste continuer à présenter la gestion du texte.
Je pense qu'ensuite, ce n'est pas le chargement d'image qui bloquera quelqu'un.
Il y a tellement peu de centre d'intérêts actuellement que quand il y en a un .......
J essayes de l'encourager en le suivant voire même essayer de comprendre le maximum de ce qui se raconte
Très bon sujet qui me passionne
Oui, et ça permet de voir comment font les autres (et de leur piquer des bout de codes )
Et je comprends pas forcément tout, mais bon, c'est bien quand même
Vous pouvez préciser les points que vous ne comprenez pas, pour que je revienne dessus?
Pour ma part j'ai buté au départ sur les operations logiques "et" "ou" "ou exclusif", j'ai mis un mois a comprendre...non sans mal....mais finalement avec ton tuto nous avons un bon exemple d'utilisation (au passage j'ai vu sur le forum python un autre exemple d'utilisation de ces operations logiques....). Après le reste de ton tuto n'est que la suite logique.Merci de nous faire progresser
× 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.