Forum tama's team

cp: ne peut évaluer `brain': Aucun fichier ou dossier de ce type
AccueilPortailGalerieCalendrierFAQRechercherS'enregistrerMembresGroupesConnexion
Connexion
Nom d'utilisateur:
Mot de passe:
Connexion automatique: 
:: Récupérer mon mot de passe
Derniers sujets
» Network, essai 1
par godbod Dim 09 Juil 2017, 02:18

» GODBOD
par godbod Sam 08 Juil 2017, 14:05

» Numbers
par godbod Sam 08 Juil 2017, 13:54

» Mort ?
par godbod Sam 08 Juil 2017, 13:47

» mon humeur
par Ver2guerre Sam 30 Juil 2016, 19:44

» [A voir] Programme de traduction original : WikiTranslate
par AdRiWeB Lun 01 Fév 2016, 04:50

» Reprise ?
par Emyl Jeu 14 Juin 2012, 21:17

» Euh, ah ?
par Ver2guerre Dim 27 Mai 2012, 12:11

» Problème TI 89 Titanium non visible après mise à jour
par abdoukid Mer 23 Mai 2012, 13:37

» Y'a quelqu'un ?
par Ver2guerre Sam 21 Avr 2012, 23:10

Quick message
Qui est en ligne ?
Il y a en tout 2 utilisateurs en ligne :: 0 Enregistré, 0 Invisible et 2 Invités

Aucun

Le record du nombre d'utilisateurs en ligne est de 367 le Dim 18 Oct 2009, 00:16

Partagez | 
 

 [C] Police personnalisée

Voir le sujet précédent Voir le sujet suivant Aller en bas 
AuteurMessage
tama
Admin
Admin
avatar

Nombre de messages : 12375
Age : 25
Localisation : DTC ? :triso:
Humeur : =)
items : o
Personalized field : huh ? oO
Réputation : 3
Points : 6963
Date d'inscription : 08/08/2007

Profil
TI: 84+, 89 tita, 89 tita
TO: infini :p
Spécialité: C 68k

MessageSujet: [C] Police personnalisée   Ven 02 Mai 2008, 01:17

Marre des polices standard ? besoin d'utiliser de nouvelles polices pour personnaliser votre programme ? ce tutorial va vous permettre de faire ça. Je présente ici une version assez "basique" qui peut être facilement étendue pour supporter d'autres caractères.



Il est recommandé pour comprendre ce tutorial...


  • d'avoir quelques connaissances basiques en C : comment afficher un sprite, l'allocation de mémoire, quelques connaissances sur les opérations telles que memcpy();
  • Avoir compris comment fonctionne la VAT, et le tuto sur la manipulation de données
Si c'est plus ou moins bon (plus plus que moins de préférence), alors on peut commencer !


Police personnalisée

Bien. Tout d'abord, la traditionnelle phase de réflexion : comment allons-nous réussir à utiliser une police personnalisée ?
...
Une façon d'arriver à cela serait d'utiliser le code suivant :



void draw(int c) //dessine le caractère dont le code est c
{
....switch(c)
.......{
.......case 1:
.......//afficher le sprite 1
.......break;
.......case 2:
.......//afficher le sprite 2
.......break;

.......//etc...
.......}
}

mais ce code présentre plusieurs désavantages :

  1. Il est lourd, par conséquent l'affichage sera plus lent
  2. Où stocker les sprites ? dans un header ? pas terrible... dans la fonction elle-même ? ils ne seront pas réutilisables autre part...

L'autre solution plus propre, et c'est celle que l'on va utiliser, consiste à stocker les données des sprites les unes à la suite des autres dans un fichier externe, puis de lire les données depuis ce fichier lorsqu'on aura besoin d'afficher un sprite à l'aide d'un pointeur qui pointera directement à l'endroit du fichier qu'on doit lire

De ce fait,
les désavantages cités précédemment disparaissent...et plus encore, il sera facile de charger une nouvelle police, il suffira "juste" de charger un autre fichier !

Voici en gros la structure du fichier que j'ai utilisé :


2 octets (obligatoire) : taille du fichier
1 octet : nombre de lignes n à lire pour un sprite
n*s octets : données (s = nombre de sprites), sous la forme d'un tableau d'unsigned char (note : pour des sprites de plus de 8 pixels de largeur, il faudra utiliser des unsigned short (<16) ou des unsigned long (<32))
1 octet (obligatoire) : \\0 marquant la fin des données
3 octets : extension personnelle : FNT
1 octet (obligatoire) : \\0 marquant la fin de l'extension
1 octet (obligatoire) : OTH_TAG, pour montrer qu'il s'agit d'un fichier d'extension personnelle
TOTAL : n*s 9 octets

pas très compliqué, non ?

La taille est également très avantageuse : un fichier contenant 100 sprites d'une hauteur de 8 pixels prendra seulement ... 809 octets !




Bien, maintenant qu'on a la théorie, passons à la pratique. Supposons que j'utilise une police personnalisée, nommée "FONT" (très original, n'est-ce pas ? ^^) pour afficher le score dans un jeu quelconque. Je n'aurais donc besoin que des caractères numériques 0 ~ 9 1 caractère (le 10ème) pour effacer ce qu'il y a à l'ancien emplacement, c'est-à-dire un caractère "tout blanc"

Chaque caractère fera 7 pixels de hauteur, et ma table de caractères sera ainsi :




(pffff, ça m'a mis du temps pour faire ça ^^)


Tout d'abord....on va manipuler la VAT :)
Le but est de créer un nouveau fichier et d'y rentrer les données comme il faut :)
Référez-vous au tutorial III si vous ne savez pas comment faire, sinon vous devez comprendre très facilement ce bout de code :


SYM_ENTRY *sym; //initialisation
HANDLE handle; //va contenir les données
char *ptrFILE; //l'adresse de base des données, on écrira les données par rapport à ça

void create_file() //crée un fichier et y met les bonnes données
{
....static char data[] //ici les données du sprite, fastidieux à copier, mais ça vaut le coup Wink
.......{
.......7, //nombre de lignes par sprite

.......0b01100000, //0
.......0b10010000,
.......0b10010000,
.......0b00000000,
.......0b10010000,
.......0b10010000,
.......0b01100000,

.......//même chose pour tous les autres chiffres

.......0b00000000, //eff
.......0b00000000,
.......0b00000000,
.......0b00000000,
.......0b00000000,
.......0b00000000,
.......0b00000000,
.......}

.......short size = sizeof(data)/sizeof(char); //détermine la taille des données

.......handle = HeapAlloc(size 9); //cf structure

.......if (!handle) //l'allocation a échoué !
..............return -1; //on retourne -1 : il y a eu erreur

.......sym = DerefSym(SymAdd(SYMSTR("font"))); //rien de nouveau normalement ^^

.......if (!sym) //oh non ! ça a échoué ! Wink
.......{
..............HeapFree(handle); //on libère la mémoire allouée précédemment
..............return -1; //erreur !
.......}

.......sym->handle = handle;
.......ptrFILE = HeapDeref(handle); //obtient l'adresse de base
.......*(short *)ptrFILE = size 7; //on met la taille : taille "normale"-2
.......ptrFILE[size 3]=0; //cf structure
.......strcpy(ptrFILE size 4,"FNT"); //cf structure
.......ptrFILE[size 8]=OTH_TAG; //cf...structure ^^

.......memcpy(ptrFILE 2,data,size); //copie des données (data) vers le fichier

//rappel : memcpy(void *dest, void *src, unsigned long len)
//copie len octets depuis src vers dest

.......return ptrFILE[size 2]; //retourne la 1ère donnée, càd le nombre de lignes pour chaque sprite ; utile pour la suite
}
}

normalement, il ne devrait rien y avoir de nouveau ici, il s'agit juste de copier les données dans le fichier, suivant la procédure expliquée dans le tutorial III à propos de la VAT.



_________________


Revenir en haut Aller en bas
Voir le profil de l'utilisateur
tama
Admin
Admin
avatar

Nombre de messages : 12375
Age : 25
Localisation : DTC ? :triso:
Humeur : =)
items : o
Personalized field : huh ? oO
Réputation : 3
Points : 6963
Date d'inscription : 08/08/2007

Profil
TI: 84+, 89 tita, 89 tita
TO: infini :p
Spécialité: C 68k

MessageSujet: Re: [C] Police personnalisée   Ven 02 Mai 2008, 01:18


Bien !
Grâce à ça, on a fait "la plus grosse partie" de ce tutorial. Maintenant une autre "grosse partie" : c'est bien beau tout ça, maintenant il faut l'utiliser !
Nous allons donc voir maintenant comment nous allons pouvoir afficher le score (adaptez-le selon vos besoins, une fois le principe compris, ça va tout seul !)

On va commencer par définir une limite : je suppose par exemple qu'on ne peut afficher qu'un score allant jusqu'à 99,999,999 (largement suffisant pour la plupart des jeux...)

On va donc définir SCORE_MAX :

#define SCORE_MAX 99999999 //score maximum
if (score>SCORE_MAX) return; //on ne continue pas si le score est trop élevé

une fois ce score dépassé, le programme refusera tout simplement d'afficher le score, et restera "bloqué" sur le dernier score affiché.

Le "truc" maintenant est d'extraire chaque chiffre à partir du score qu'on a. Pour cela, on va les extraire de gauche à droite, selon un principe simple :

Soit score notre score, alors
score = a*10000000 b*1000000 c*100000 d*10000 e*1000 f*100 g*10 h
On va de là prendre une variable i qui variera de 7 à 0 (oui, l'ordre est fait exprès) (car 107=10000000)
On va ensuite créer une "copie" de notre nombre score et soustraire 10i jusqu'à ce que 10i soit supérieur à notre copie. Le nombre de soustractions sera égal au chiffre qu'on veut.

Pas très clair ? prenons un exemple : supposons que le score actuel est de 376,664

score = 376664
->création de la "copie" :
score_temp = score = 376664
107>376664, on passe, a=0
106>376664, on passe, b=0
105=100000<376664,on peut soustraire 100000 trois fois, on a donc c=3, il nous reste 76664
104=10000, on peut soustraire 10000 sept fois, d=7
etc...

Plusieurs questions :
1.Pourquoi ne pas avoir utilisé la division entière ? On aurait pu, simplement la soustraction est plus rapide que la division
2.Comment obtenir les puissances de 10 ? En utilisant la définition mathématique : 10a = 10*10*...*10 a fois
En code, cela donne :

long pow10(short n) //retourne 10n
{
.......long result = 1;
.......short i;
.......for(i=1;i<=n;i )
..............result = result * 10;
.......return result;
}

Et v'la l'boulot :)
maintenant la dernière touche : afficher le sprite à l'aide de l'algorithme, le code n'est pas difficile à comprendre :

void aff_score(long score,short xend, short ypos, short xlen) //affiche le score
{
//arguments :
//score = le score, quoi d'autre ? Very Happy
//xend = coordonnée x de fin d'affichage
//ypos = position y d'affichage
//xlen = taille x d'un sprite


.......short i,j;
.......long t, tscore = score;

.......for(j=7;j>=0;j--)
.......{
..............t=pow10(j);
..............i=0; //compteur

..............while(tscore>=t)
..............{
.....................tscore- = t; //on soustrait 10j
.....................i ; //on compte ^^
..............}

.............draw(10,xend-xlen*j,ypos,SPRT_AND);
//rappel :
//a and b = 1 si et seulement si a et b sont égaux à 1
//or le 10ème caractère (eff) est entièrement vide...finalement ça efface ce qu'il y a en-dessous
.............draw(i,xend-xlen*j,ypos,SPRT_OR);
}

draw étant la fonction définie ainsi :

void draw(short n, short x, short y, short attr)
{
//n : numéro du caractère à dessiner
//x : position x
//y : position y
//attr : comment le dessiner ?
.......short s = ptrFILE[2]; //nombre de lignes par sprite
.......char *spr = (char*)malloc(s); //alloue de la mémoire pour y mettre les données du sprite
.......memcpy(spr,ptrFILE s*n 3,s); //copie des données vers le sprite
.......free(spr); //libère la mémoire allouée
}

ce code ne vérifie pas si l'allocation s'est bien effectuée, il peut donc y avoir des crash !

Et voilà, tout est fini, maintenant vous pouvez dessiner n'importe quel caractère de la police personnalisée simplement en appelant la fonction draw()
N'oubliez pas d'"initialiser" avant d'utiliser la police en appelant la fonction create_file()

Toutes les fonctions présentées jusqu'à maintenant peuvent être mises dans un header pour être utilisables par plusieurs programmes :

Résumons donc le code complet :
FONT.h

SYM_ENTRY *sym; //initialisation
HANDLE handle; //va contenir les données
char *ptrFILE; //l'adresse de base des données, on écrira les données par rapport à ça

void create_file() //crée un fichier et y met les bonnes données
{
....static char data[] //ici les données du sprite, fastidieux à copier, mais ça vaut le coup Wink
.......{
.......7, //nombre de lignes par sprite

.......0b01100000, //0
.......0b10010000,
.......0b10010000,
.......0b00000000,
.......0b10010000,
.......0b10010000,
.......0b01100000,

.......//même chose pour tous les autres chiffres

.......0b00000000, //eff
.......0b00000000,
.......0b00000000,
.......0b00000000,
.......0b00000000,
.......0b00000000,
.......0b00000000,
.......}

.......short size = sizeof(data)/sizeof(char); //détermine la taille des données

.......handle = HeapAlloc(size 9); //cf structure

.......if (!handle) //l'allocation a échoué !
..............return -1; //on retourne -1 : il y a eu erreur

.......sym = DerefSym(SymAdd(SYMSTR("font"))); //rien de nouveau normalement ^^

.......if (!sym) //oh non ! ça a échoué ! Wink
.......{
..............HeapFree(handle); //on libère la mémoire allouée précédemment
..............return -1; //erreur !
.......}

.......sym->handle = handle;
.......ptrFILE = HeapDeref(handle); //obtient l'adresse de base
.......*(short *)ptrFILE = size 7; //on met la taille : taille "normale"-2
.......ptrFILE[size 3]=0; //cf structure
.......strcpy(ptrFILE size 4,"FNT"); //cf structure
.......ptrFILE[size 8]=OTH_TAG; //cf...structure ^^

.......memcpy(ptrFILE 2,data,size); //copie des données (data) vers le fichier

//rappel : memcpy(void *dest, void *src, unsigned long len)
//copie len octets depuis src vers dest

.......return ptrFILE[size 2]; //retourne la 1ère donnée, càd le nombre de lignes pour chaque sprite ; utile pour la suite
}

void draw(short n, short x, short y, short attr)
{
//n : numéro du caractère à dessiner
//x : position x
//y : position y
//attr : comment le dessiner ?
.......short s = ptrFILE[2]; //nombre de lignes par sprite
.......char *spr = (char*)malloc(s); //alloue de la mémoire pour y mettre les données du sprite
.......memcpy(spr,ptrFILE s*n 3,s); //copie des données vers le sprite
.......free(spr); //libère la mémoire allouée
}

long pow10(short n) //retourne 10n
{
.......long result = 1;
.......short i;
.......for(i=1;i<=n;i )
..............result = result * 10;
.......return result;
}

#define SCORE_MAX 99999999 //score maximum

void aff_score(long score,short xend, short ypos, short xlen) //affiche le score
{
//arguments :
//score = le score, quoi d'autre ? Very Happy
//xend = coordonnée x de fin d'affichage
//ypos = position y d'affichage
//xlen = taille x d'un sprite


if (score>SCORE_MAX) return; //on ne continue pas si le score est trop élevé


.......short i,j;
.......long t, tscore = score;

.......for(j=7;j>=0;j--)
.......{
..............t=pow10(j);
..............i=0; //compteur

..............while(tscore>=t)
..............{
.....................tscore- = t; //on soustrait 10j
.....................i ; //on compte ^^
..............}

.............draw(10,xend-xlen*j,ypos,SPRT_AND);
//rappel :
//a and b = 1 si et seulement si a et b sont égaux à 1
//or le 10ème caractère (eff) est entièrement vide...finalement ça efface ce qu'il y a en-dessous
.............draw(i,xend-xlen*j,ypos,SPRT_OR);
}

Et voilà, fini !
Voici un exemple d'utilisation de cette police :

MAIN.c
#include < tigcclib.h>
#include "font.h" //ne pas oublier...

void _main(void)
{
.......create_file();
.......randomize(); //pour ne pas sortir les mêmes nombres aléatoires

.......long score = 0; //le score

.......while (!kbhit())
.......{
..............aff_score(score,154,10,5);
..............score = score random(200); //ajoute au score un nombre aléatoire entre 0 et 199
.......}
}

Voyons en images le résultat si tout s'est bien passé (cliquez sur l'image pour télécharger l'exécutable !)



Et voilà, un autre de terminé, il m'a pris beaucoup de temps c'lui là, j'espère que vous l'avez compris au moins ^^

_________________




Dernière édition par tama le Dim 04 Mai 2008, 00:10, édité 3 fois
Revenir en haut Aller en bas
Voir le profil de l'utilisateur
ProgVal
modérateur
modérateur
avatar

Nombre de messages : 4107
Age : 166
Localisation : In da cloud
items : o
Personalized field :
Réputation : -4
Points : 4245
Date d'inscription : 09/08/2007

Profil
TI: V200 - NSpire
TO: 120 [2352 - 2%]
Spécialité: Programmation web

MessageSujet: Re: [C] Police personnalisée   Sam 03 Mai 2008, 15:59

Très jolie police!
Tu peux pas créer un programme que l'on pourrait utiliser depuis le TI-Basic?

_________________
Revenir en haut Aller en bas
Voir le profil de l'utilisateur https://progval.net
tama
Admin
Admin
avatar

Nombre de messages : 12375
Age : 25
Localisation : DTC ? :triso:
Humeur : =)
items : o
Personalized field : huh ? oO
Réputation : 3
Points : 6963
Date d'inscription : 08/08/2007

Profil
TI: 84+, 89 tita, 89 tita
TO: infini :p
Spécialité: C 68k

MessageSujet: Re: [C] Police personnalisée   Sam 03 Mai 2008, 17:18

bah il suffit juste d'adapter le code pour ça pour qu'il prenne des arguments :

MAIN.c
#include < tigcclib.h>
#include "font.h" //ne pas oublier...


void _main(void)
{
.......ESI argptr;//prend les arguments
.......InitArgPtr(argptr);
.......long score = GetIntArg(argptr);
.......short xend = GetIntArg(argptr);
.......short y = GetIntArg(argptr);
.......short len = GetIntArg(argptr);

.......create_file(); //initialisation
.......aff_score(score,xend,y,len); //affiche le score
}

En théorie ça devrait marcher, j'ai pas testé.
appel : outbin(score, xend, y, len)

xend = fin de l'affichage (et pas début !)
len = taille horizontale occupée par 1 caractère (dans cet exemple, 5)

_________________


Revenir en haut Aller en bas
Voir le profil de l'utilisateur
Ver2guerre
chasseur en chef
chasseur en chef
avatar

Nombre de messages : 3139
Age : 106
Localisation : Partout en même temps (V2g quantique)
Loisirs : #pkill boulet
Humeur : Happy :)
items :
Personalized field : 12 jetons
Réputation : 8
Points : 5047
Date d'inscription : 15/09/2007

Profil
TI: (TI-89Tita)^2+TI83Plus
TO: 50 [2380 - 2%] {54}
Spécialité: Autres

MessageSujet: Re: [C] Police personnalisée   Sam 03 Mai 2008, 20:16

Il a l'air pas mal ce truc !!

Je regarderai en entier dès que j'aurais une après-midi complète devant moi.

_________________
Help, j'ai rien compris

C'est moche :
Revenir en haut Aller en bas
Voir le profil de l'utilisateur
tama
Admin
Admin
avatar

Nombre de messages : 12375
Age : 25
Localisation : DTC ? :triso:
Humeur : =)
items : o
Personalized field : huh ? oO
Réputation : 3
Points : 6963
Date d'inscription : 08/08/2007

Profil
TI: 84+, 89 tita, 89 tita
TO: infini :p
Spécialité: C 68k

MessageSujet: Re: [C] Police personnalisée   Sam 03 Mai 2008, 20:26

pas de pb, et tu m'diras si c'est assez clair :)

(c'est marrant ton nouveau pseudo, j'ai toujours l'impression que c'est un nouveau membre -__-')

_________________


Revenir en haut Aller en bas
Voir le profil de l'utilisateur
Contenu sponsorisé




MessageSujet: Re: [C] Police personnalisée   

Revenir en haut Aller en bas
 

[C] Police personnalisée

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

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
Forum tama's team :: TI :: TI 68k :: Tutoriels-
Créer un forum | © phpBB | Forum gratuit d'entraide | Contact | Signaler un abus | Forum gratuit