IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Problème d'arrondi (?)


Sujet :

C

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 50
    Points : 34
    Points
    34
    Par défaut Problème d'arrondi (?)
    Bonjour.

    Il semblerait que j'ai un problème d'arrondi dans l'un de mes codes.

    Voici les lignes en cause (toutes les variables sont de type long) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    long tileX = spriteTile % (sprite->info.Width / sprite->tile.x);
    long tileY = spriteTile / (sprite->info.Width / sprite->tile.y);
    Ce code sert à calculer à partir d'un numéro d'index des coordonnées dans un sprite. L'image est découpée en plusieurs cases en hauteur et largeur.

    A priori, il me semble que tileX et tileY contiennent strictement une valeur entière.

    spriteTile = numéro d'index.
    sprite->info.Width = largeur du sprite en pixel, dans le cas présenté plus bas, 216 pixels.
    sprite->tile.x = largeur d'une case.
    sprite->tile.y = hauteur d'une case.

    L'indexation est de ce type (exemple) :

    00 - 01 - 02 - 03
    04 - 05 - 06 - 07
    08 - 09 - 10 - 11
    12 - 13 - 14 - 15

    Le 00 renvoie les coordonnées (0,0), le 09 (1,2), le 15 (3,3), etc...

    Ces coordonnées sont ensuite traitées pour un affichage de sprite qui ne pose pas de problème.

    Lorsque je laisse les calculs de tileX et tileY tels que présentés plus haut, ça bugue :/ .Visuellement, ce problème cause ceci :

    Voici le sprite original, de taille 216x48 :




    Voici les images affichées pour sprite->tile.x = 24 et sprite->tile.y = 48, et spriteTile de 0 à 8 (le noir n'est pas le fond d'écran, mais ce qui m'est affiché par le sprite) :




    Image affichée pour sprite->tile.x = 24 et sprite->tile.y = 30 et spriteTile de 0 à 8




    Lorsque je remplace ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    long tileX = spriteTile % (sprite->info.Width / sprite->tile.x);
    long tileY = spriteTile / (sprite->info.Width / sprite->tile.y);
    par cela, ou autres valeurs, tout fonctionne correctement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    long tileX = 5;
    long tileY = 0;
    Et avec tileX de 0 à 8, j'obtiens :



    Soit le sprite correctement affiché. D'où vient le problème ?

    La fonction complète :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    // On affiche une tile du sprite.
    // sprite = Pointeur vers les données du sprite.
    // spriteTile = Numéro de la tile à afficher.
    // positionX = Abscisse pour l'affichage de la tile.
    // positionY = Ordonnée pour l'affichage de la tile.
     
    	void DXS_DrawSpriteTile(M2ESPRITE* sprite, long spriteTile, float positionX, float positionY)
    	{
     
    		RECT tile = {0};
     
    		spriteTile -= 1;
     
    		long tileX = spriteTile % (sprite->info.Width / sprite->tile.x);
    		long tileY = spriteTile / (sprite->info.Width / sprite->tile.y);
     
    		tile.left = tileX * sprite->tile.x;
    		tile.top = tileY * sprite->tile.y;
    		tile.right = (tileX + 1) * sprite->tile.x;
    		tile.bottom = (tileY + 1) * sprite->tile.y;
     
    		// Mise à jour de la position du sprite pour l'affichage.
    			sprite->position.x = positionX / sprite->scale.x;
    			sprite->position.y = positionY / sprite->scale.y;
     
    		// Affichage du sprite.
    			sprite->sprite->Draw(	sprite->texture,								// Données sur la texture du sprite.
    									&tile,							// Rectangle source sur la texture.
    									&sprite->center,						// Position du centre du sprite, par rapport à 
    																	// son bord haut gauche.
    									&sprite->position,					// Position du sprite.
    									D3DCOLOR_ARGB(	sprite->alpha,			// Génère la couleur de diffusion et d'alpha.
    													sprite->rouge,
    													sprite->vert,
    													sprite->bleu));	
    	}

  2. #2
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    salut

    Primo le type flottant par défaut en C est double, donc ce serait mieux de passer des doubles que des floats.

    Secondo, est-ce que sprite->scale.x ou .y est flottant ? sinon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	sprite->position.x = (int)(positionX / (double)sprite->scale.x);
    	sprite->position.y = (int)(positionY / (double)sprite->scale.y);

    Tertio, tu peux simplifier du code et accélerer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    		tile.right = tile.left + sprite->tile.x;
    		tile.bottom = tile.top + sprite->tile.y;
    Enfin :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    long tileX = spriteTile % (long)((double)sprite->info.Width / (double)sprite->tile.x));
    long tileY = (long)((double)spriteTile / ((double)sprite->info.Width / (double)sprite->tile.y));
    Car en C par défaut la division est entière..
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  3. #3
    Membre éclairé Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Points : 844
    Points
    844
    Par défaut
    En C, grâce à la promotion numérique, il suffit que seulement l'une des opérande soit flottante pour que la division se fasse en flottant.

    Donc ce qui suit :

    Citation Envoyé par souviron34
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	sprite->position.x = (int)(positionX / (double)sprite->scale.x);
    	sprite->position.y = (int)(positionY / (double)sprite->scale.y);
    Peut être simplifié en :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	sprite->position.x = (int)(positionX / sprite->scale.x);
    	sprite->position.y = (int)(positionY / sprite->scale.y);
    Même chose pour :

    Citation Envoyé par souviron34
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    long tileX = spriteTile % (long)((double)sprite->info.Width / (double)sprite->tile.x));
    long tileY = (long)((double)spriteTile / ((double)sprite->info.Width / (double)sprite->tile.y));
    A remplaçer par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    long tileX = spriteTile % (long)((double)sprite->info.Width / sprite->tile.x));
    long tileY = (long)(spriteTile / ((double)sprite->info.Width / sprite->tile.y));
    Avant de poster un message .
    Quand vous avez la réponse à votre question, n'oubliez pas de cliquer sur .

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 50
    Points : 34
    Points
    34
    Par défaut
    Merci pour ces précisions, ça me sera sans doute utile pour la suite

    En fait je n'avais qu'une lettre à changer à cette ligne pour tout corriger :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    long tileY = spriteTile / (sprite->info.Width / sprite->tile.y);
    Qui devient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    long tileY = spriteTile / (sprite->info.Width / sprite->tile.x);
    Une conne erreur ^^"

  5. #5
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par mchk0123
    En C, grâce à la promotion numérique, il suffit que seulement l'une des opérande soit flottante pour que la division se fasse en flottant.

    Donc ce qui suit :

    ...

    Peut être simplifié en :

    ....
    Bien sûr que tu as raison, mais je préfère la première écriture pour raison d'homogénéité...

    Au moins, si tu veux comprendre, ou modifier, ou passer dans un autre langage, tu sais que là pour les 2 il te faut des flottantS.

    Mais bon, chacun fait ce qu'il veut, pusique c'est autorisé
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  6. #6
    Membre éclairé Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Points : 844
    Points
    844
    Par défaut
    Bah ! Je dois être trop feinéant !
    Avant de poster un message .
    Quand vous avez la réponse à votre question, n'oubliez pas de cliquer sur .

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème d'arrondi
    Par rigobert dans le forum C
    Réponses: 28
    Dernier message: 05/04/2006, 12h56
  2. problème d'arrondi à 2 chiffres après virgule
    Par nerick dans le forum Langage
    Réponses: 1
    Dernier message: 05/01/2006, 17h26
  3. Problème d'arrondis
    Par steps5ive dans le forum Access
    Réponses: 5
    Dernier message: 09/12/2005, 17h35
  4. [DECIMAL] problème d'arrondi
    Par Boosters dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 28/11/2005, 15h30
  5. Problème d'arrondi
    Par ptitsoleil87 dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 07/01/2005, 09h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo