:: PlayerAdvance.org ::  

Précédent   :: PlayerAdvance.org :: > :: Développement Amateur :: > Autres > Tutoriels

Tutoriels Tutoriels dédiés au développement sur d'autres supports

Publicité

Réponse
 
Outils de la discussion Modes d'affichage
Vieux 19/04/2006, 22h07   #1
Brunni
Super Modérateur
 
Date d'inscription: 10/11/2005
Localisation: Un pays avec beaucoup de banques
Messages: 3 226
Par défaut Virgule fixe: revisited

Hello tout le monde
Voici un tuto qui vous permettra de créer et manipuler des nombres à virgule fixe très simplement en C++, comme si c'étaient des float, mais avec une énorme amélioration de vitesse:
Code PHP:
void main()        {
    
fixed i 0.5;
    
+= 0.75;
    
printf("%i, %f", (int)i, (float)i);            // => 1, 1.25

Dans ce tuto, j'explique comment arriver à ce résultat, mais vous pouvez très bien télécharger le fichier .h tout prêt à la fin du post, il suffit de l'inclure et à vous les fixed!

Tout d'abord, on va devoir travailler en C++, car le C ne permet pas de faire ça (si vous voulez faire du C, regardez un autre tuto sur les fixed point ).
Bien heureusement, le C est compatible C++ (mais pas l'inverse) et en général un programme C compilera en C++ sans souci. Il suffit de renommer les fichiers .c en .cpp pour spécifier que c'est du C++.
Note: Les performances d'un même programme peuvent varier suivant qu'il est compilé en C ou en C++.

Pour créer ce nouveau type de données, nous allons profiter des fonctionnalités propres au C++ que sont les classes et la surcharge d'opérateurs. Tout d'abord, une classe, c'est simplement une évolution des structures en C: elle est designée pour contenir plusieurs paramètres, tel qu'un objet dans un jeu:
Code PHP:
class OBJET        {
    
int xy;            //Positions
    
IMAGE *img;        //Sprite de l'objet
}; 
En plus de ça, les classes sont chargées d'effectuer des tâches, contrairement aux structures en C. On peut par exemple définir une fonction (qu'on appelle méthode lorsqu'elle est contenue dans une classe) dans la classe OBJET qui serait chargée de dessiner l'objet:
Code PHP:
class OBJET        {
    
int xy;            //Positions
    
IMAGE *img;        //Sprite de l'objet
    
void affiche()
    {
        
printf("je suis un objet aux positions %i, %i"xy);
    }
}; 
Vous pouvez ensuite l'utiliser simplement, comme une structure en C:
Code PHP:
void main()
{
    
OBJET piece;
    
piece.4;
    
piece.10;
    
piece.affiche();

Une classe peut également être considérée comme un type de données: on peut définir ce qui se passe lorsqu'on accède à sa valeur (ici 'piece'), mais également définir ce qui se passe si on l'additionne avec quelque chose par exemple (piece = piece + 1). C'est de là que naît notre classe 'fixed', qui représente un nombre à virgule fixe. Cette classe contient simplement une valeur, notre nombre en virgule fixe, c'est-à-dire multiplié par 256 (j'ai choisi 256 comme ça, ça aurait pu être n'importe quoi d'autre. Ici: 256 = 1, 512 = 2, 128 = 0.5, ...):
Code PHP:
class fixed        {
    
int value;
}; 
On pourrait dores et déjà l'utiliser comme ceci (oubliez ça si vous n'y connaissez rien en fixed point):
Code PHP:
void main()        {
    
fixed i;
    
i.value 256;
    
i.value *= 0.5 256;
    
printf("%f", (float)i.value 256);            // => 1.5

Mais ça n'est pas très beau. On remarque toutefois que systématiquement, on doit remplacer un "i = 3" naturel par un 'i.value = 3 * 256', beaucoup moins pratique. Et si on pouvait le faire directement? Grâce à la surcharge d'opérateurs du C++, c'est possible. On peut définir plus généralement que 'fixed = x' devient 'fixed.value = x * 256'.
C'est également possible pour toutes les autres opérations, comme l'addition, où on peut dire que 'fixed + x' est équivalent à 'fixed.value + x * 256'. Sans oublier les autres types, par exemple la valeur entière: '(int)fixed = fixed.value / 256'.
Pour le code:
Code PHP:
fixedoperator = (fixedfint n)        {
    
f.value 256;
    return 
f;

C'est déjà moins joyeux tout ça, ci-dessus on définit ce que l'assignement (opérateur '=') d'une valeur entière (int) à un type fixed va réaliser. N'oubliez pas que 'value' représente le membre correspondant dans la classe, c'est à dire le nombre en fixed point lui même.
Finalement, suite à un assignement, on doit toujours retourner la valeur de l'assignement lui même, c'est une spécificité du C/C++: (i = 2) * 3 => 6. En l'occurence, la valeur de retour c'est notre classe 'fixed' passée en paramètre, nommée 'f'.
Le '&' pour les paramètres est une spécificité du C++, il définit les paramètres passés en référence, comme par exemple:
Code PHP:
int add2(intx)        {
    
2;
}
void main()            {
    
int x 1;
    
add2(x);
    
printf("%i"x);            // => 3

Sans le &, la valeur de 'x' n'aurait pas été conservée en dehors de la fonction 'add2', et le résultat aurait été 1.
Finalement, il va falloir écrire du code pour tous les opérateurs vers tous les types supportés (en l'occurence, ma classe gère les int, float et double, et tout ce qui peut être converti vers l'un de ces types, tel que 'short'). Si jamais vous avez besoin de plus d'informations, regardez mon code, car le bout que j'ai présenté ici n'est pas optimisé du tout, c'est juste pour expliquer

Ensuite, si vous incluez mon fichier .h, vous pouvez modifier le #define VIRGULE au début pour y mettre le nombre de bits que vous voulez après la virgule. En général, 12 est une bonne valeur pour les positions de vos personnages, car elle offre une précision à 0.00024 près, tout en laissant 20 bits pour la partie entière (valeurs entre +/- 500'000), donc aucun problème pour les grandes maps
Et l'utilisation se fait comme montré en haut de ce post, exactement comme des floats quoi
Question performances, c'est quand même légèrement plus lent que des fixed faits à la main (enfin ça dépend du compilo, parce que théoriquement ça devrait être pareil s'il fait bien son boulot), et j'ai pas de DS donc je peux pas tester.
Ce tuto s'applique également à la GBA et à la PSP
Dernière précision: ce n'est pas un tuto sur le C++, j'ai juste expliqué pour qu'on comprenne le principe, en plus c'est un très mauvais exemple. Si vous voulez vous mettre au C++, regardez les tutos correspondants

Téléchargement: http://oslib.palib.info/oth/fixed_tuto.zip
Benchmarks (temps écoulé, plus bas = mieux):
Code:
Int (C): 807
Int (C++): 809
Fixed: 933
Float: 1174
Double: 22000 (et augmente selon la taille du nombre)
On a donc un bon compromis entre la simplicité et la vitesse Notez que ces tests ont été effectués sur une PSP, qui a une FPU, c'est donc normal que les float soient si rapides. Sur GBA/DS, les float devraient avoir la même vitesse que les double (c'est-à-dire vraiment, mais alors vraiment lent).

Voilà, si vous avez des questions, n'hésitez pas

Dernière modification par Brunni ; 19/04/2006 à 22h12.
Brunni est déconnecté   Réponse avec citation

Publicité

Vieux 19/04/2006, 22h52   #2
mastertop101
Membre confirmé
 
Date d'inscription: 14/11/2005
Messages: 346
Par défaut

J'ai fait un petit test pour voir si la ds est si lente que ca avec les floats...:
Code:
while(var<1000000)
		var=var*1.0001;
		PA_OutputText(1,0,4,"var: %f4 ", var);
et la valeur s'est affichée quand même très rapidement (moins d'une seconde..)
A-t-on vraiment besoin de multiplier plus de 100 000 fois par seconde un float ?
Je ne dis pas que ton tutoriel est inutile, je veux seulement comprendre .
mastertop101 est déconnecté   Réponse avec citation
Vieux 19/04/2006, 23h07   #3
DJP
Bitchy Little Girl...
 
Date d'inscription: 29/10/2005
Messages: 3 200
Par défaut

Citation:
Envoyé par mastertop101
J'ai fait un petit test pour voir si la ds est si lente que ca avec les floats...:
Code:
while(var<1000000)
        var=var*1.0001;
        PA_OutputText(1,0,4,"var: %f4 ", var);
et la valeur s'est affichée quand même très rapidement (moins d'une seconde..)
A-t-on vraiment besoin de multiplier plus de 100 000 fois par seconde un float ?
Je ne dis pas que ton tutoriel est inutile, je veux seulement comprendre .
Fait la même chose avec plusieurs float et/ou sur GBA ...
__________________

>> On garde :: On améliore :: On kill <<
DJP est déconnecté   Réponse avec citation
Vieux 20/04/2006, 08h28   #4
Brunni
Super Modérateur
 
Date d'inscription: 10/11/2005
Localisation: Un pays avec beaucoup de banques
Messages: 3 226
Par défaut

Dans ton cas, le compilo optimise de lui-même parce qu'il peut déjà calculer le résultat final à la compilation, c'est pour ça que c'est si rapide
Rêve pas, déjà sur PSP sans le support des float en hardware t'en fais pas 1 million par seconde, donc sur DS y'a aucune chance
Et déjà rien que dans un moteur de collisions si tes positions (et uniquement elles) sont en float tu auras déjà plusieurs dizaines de milliers d'accès par seconde (additions, tests, indices de la map, divisions obligatoires, *60 fps), après si tu les utilises ailleurs (affichage du perso, moteur physique, etc.) ben tu arrives vite à ton million, et à ce moment là tu seras déjà à moins de 0.2 image/seconde, et ça c'est sans parler de tout le reste du code que tu as à faire en dehors de ça
De toute façon on voit bien la différence sur mes benchs, entre 20'000 et 40'000 unités de temps pour un float/double contre moins de 1'000 pour les fixed (sans oublier les conversions à faire entre float/int, le fait qu'on ne peut pas optimiser avec des décalages, ...) donc le choix est vite fait si tu as un minimum besoin de vitesse
Brunni est déconnecté   Réponse avec citation
Vieux 20/04/2006, 19h55   #5
Yodajr
Administrateur
 
Date d'inscription: 09/11/2005
Messages: 3 750
Par défaut

Merci Brunni, si seulement il y avait + de tutos dans le genre
Yodajr est déconnecté   Réponse avec citation
Vieux 20/04/2006, 20h59   #6
Nesgba
Membre confirmé
 
Date d'inscription: 10/11/2005
Messages: 830
Par défaut

traitre tu est passé au c++

ca me servira pas, mais je te dit quand meme merci pour les autres

Dernière modification par Nesgba ; 20/04/2006 à 21h05.
Nesgba est déconnecté   Réponse avec citation
Vieux 20/04/2006, 23h43   #7
Dr.Vince
Administrateur
 
Date d'inscription: 10/11/2005
Messages: 4 963
Voir les codes amis Nintendo DS Voir les codes amis Wii
Par défaut

merci pour le tuto Brunni !!

c'est vrai que ça manque de tutos depuis le nouveau PA, mais heureusement que tu es là !!! (mais oui toi aussi yodajr )
__________________
Projets Abandonnés: [Arcomage Advance] [Puzznic] [PA Card Games] [Blob Runner]
Projet en cours: [Ne plus abandonner de projet...]
Dr.Vince est déconnecté   Réponse avec citation
Réponse

Liens sociaux

Publicité



Utilisateurs regardant la discussion actuelle : 1 (0 membre(s) et 1 invité(s))
 
Outils de la discussion
Modes d'affichage

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 04h21.


Édité par : vBulletin® version 3.7.2
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Tous droits réservés.
Version française #16 par l'association vBulletin francophone
Design par Ass-Itch, DJP et Dr.Vince