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

Framework .NET Discussion :

[dotnet] gdi+ rafraichissement


Sujet :

Framework .NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Inscrit en
    Novembre 2002
    Messages
    291
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 291
    Points : 81
    Points
    81
    Par défaut [dotnet] gdi+ rafraichissement
    Bonjour,

    Comment faire pour raffraichir seulement une partie d'une image avec gdi+ ?

    J'ai une Bitmap que j'affiche masi pas forcement avec ses dimensions d'origine :
    par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Bitmap^ texture = gcnew Bitmap("test.png");
     
    /* ... */
    Rectangle tailleEcran = Rectangle(0, 0, 50, 100);
     
    if (tailleEcran.IntersectWith(e->ClipRectangle)
        g->DrawImage(texture, tailleEcran, 0, 0, texture->Width, texture->Height, GraphicsUnit::Pixel, mImageAttr)
    j'affiche donc toute mon image. Seulement je ne l'affiche pas avec ses dimensions d'origine (donc l'image est deformée)

    Donc maintenant, mon prob :
    J'ai une boule qui se deplace, et quand elle se deplace sur l'image, je redessine cette image en entier (dans OnPaint)... et ca ne me plait pas, je voudrais juste raffraichir la zone de l'image où la balle passe.. (et je m'embrouille avec les 30 declarations différentes de drawimage )

    voilà j'espere que c'est compréhensible ?
    merci de votre aide

    P.S. si qqun connait des liens vers l'optimisation de l'affichage avec gdi+, je suis preneur...merci

  2. #2
    Membre expérimenté Avatar de Mose
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 143
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 143
    Points : 1 379
    Points
    1 379
    Par défaut
    1 - C'est bien DrawImage qu'il faut utiliser.
    Je te suggère l'overload avec x, y et un rectangle source :

    * x et y sont les coordonnées, dans ton Graphics, où tu veux dessiner ton image.
    * le rectangle source est la portion de l'image à coller dans le Graphics.

    2 - Pour animer un sprite, sans tout redessiner, il n'y a qu'un méthode : en rajoutant un buffer.
    * Tu as un premier buffer ("back") qui représente le fond de ton image
    * Tu en as un second buffer ("frame") qui contient la frame : l'image à un instant t

    2.1 - le dessin de la frame se fait en deux étapes :
    * Tu copies "back" dans "frame"
    * Tu dessines ton sprite par dessus

    2.2 - Sinon, méthode plus évoluée (plus lourde à gérer) :
    * Au départ tu initializes "frame" en copiant "back" dedans"
    * Au moment T
    * * Si tu as dessiné un sprite en T-1, tu copies dans "frame" uniquement la portion de "back" nécessaire à recouvrir ton sprite
    * * Tu dessines ensuite ton nouveau sprite là où tu veux
    (Note : ça t'oblige à savoir où était le sprite en T-1)

    2.3 - Sinon, encore plus evolué :
    * Tu fais un buffer "back" qui fait la taille maximale de ton sprite
    * Au départ tu dessines directement dans "frame"
    * Au moment T :
    * * tu sauvegarde dans "back" la portion de "frame" qui va se faire recouvrir par le sprite
    * * tu dessines ton sprite
    * Au moment T+1
    * * tu restaures dans "frame" le contenu de "back" là où tu l'as pris, pour effacer ton sprite
    * * etc.

    Note : je ne suis pas sûr de savoir laquelle de ces méthodes est la plus rapide.
    2.1 : la plus rapide à coder
    2.2 : évite une copie par frame (probablement la plus rapide IMHO)
    2.3 : la moins lourde en mémoire

    3 - GDI accéléré : voir dans la FAQ du forum.

  3. #3
    Membre régulier
    Inscrit en
    Novembre 2002
    Messages
    291
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 291
    Points : 81
    Points
    81
    Par défaut
    merci de ta reponse :
    Pour le drawimage aurais tu un exemple car je dois aussi mettre mon ImgAttr dans drawImage... donc je dois utiliser une des surchages avec ImageAttributes..

    Ensuite pour l'animation : dessiner une autre image pour la balle : ca ok mais dessiner que la partie caché du fond.. voilà ce que j'aimerai !!!

    Et enfin pour l'acceleration de GDI+ je n'ai pas trouvé la FAQ du forum, ou un post parlant de l'acceleration de GDI...
    Est ce une bonne methode de tout mettre dans OnPaint ? ou existe t'il une autre methode ?

    merci

  4. #4
    Membre régulier
    Inscrit en
    Novembre 2002
    Messages
    291
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 291
    Points : 81
    Points
    81
    Par défaut
    voilà en fait j'ai un souci et je ne sais pas si c'est moi qui fait mal qqchose ou si c'est GDI+ qui rame !!!

    Donc j'ai plusieurs balles qui se deplacent entre 4 murs.

    Le prob dès qu'il y a plus de 3 balles, elles ralentissent et j'ai l'impression que ca rame !!! :00000010:

    Voici un extrait de mon code :

    Code de mis à jour des balles :
    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
     
     
    	ControleurObjets^ cObjets = ControleurObjets::GetInstance();
     
    	Rectangle rectPos, rectPosPrec, rectEnglob;
    	// Rafraichissement des objets mobiles
    	for each(Balle^ b in cObjets->GetListeBalles())
    	{
    		Point pos		= b->GetPosition();
    		Point posPrec	= b->GetPositionPrec();
     
    		// calcule du rectangle englobant ancienne+nouvelle position
    		rectPos	    = Rectangle(b->GetPosition(), b->GetDimensions());
    		rectPosPrec = Rectangle(b->GetPositionPrec(), b->GetDimensions());
    		rectEnglob  = rectPos.Union(rectPos, rectPosPrec);
     
    		// on ne met à jour que la zone qui en a besoin
    		mFenetre->Invalidate(rectEnglob);
     
    	}
    Code d'affichage des balles :

    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
     
    	ControleurObjets^ cObjets = ControleurObjets::GetInstance();
     
    	for each(Balle^ b in cObjets->GetListeBalles())
    	{
    		// si l'objet se trouve dans le rectangle de raffraichissement : on le reaffiche
    		Rectangle tailleImg = Rectangle(b->GetPosition(), b->GetDimensions());
    		if (tailleImg.IntersectsWith(rectAff))
    		{
    	Bitmap^ texture     = mListeTextures[b->GetTexture()];
    	Rectangle tailleImg = Rectangle(b->GetPosition(), b->GetDimensions());
     
     
    	// on definit la transparence (1 = opaque, 0 = tranparent)
    	mColorMatrix->Matrix33 = 1.f - b->GetTransparence();
    	mImageAttr->SetColorMatrix(mColorMatrix, ColorMatrixFlag::Default,ColorAdjustType::Bitmap);
     
    	g->DrawImage(texture, tailleImg, 0, 0, texture->Width, texture->Height, GraphicsUnit::Pixel, mImageAttr);
     
    		}		
    	}
    y a t'il qqchose qui ne va pas ?

    pour info : pour faire avancer la balle c'est position = position+vitesse et j'appelle la fonction deplacement toutes les 15ms...

    mercide votre aide

    P.S : pas de reponse du type : utilise DirectX ou OpenGl, merci

  5. #5
    Membre expérimenté Avatar de Mose
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 143
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 143
    Points : 1 379
    Points
    1 379
    Par défaut
    J'ai pas d'exemples pour DrawImage, mais je crois avoir donné assez d'explication pour ne pas avoir à faire cette recherche à ta place. Allez courage, y'a que 9 surcharges.

    Pour l'accélération de GDI+, recherche les forums/tuto qui parlent de code unsafe avec GDI+, j'ai pas de tuto sous la main, mais voici un exemple complet sur code project

    Pour le dessin : attention... ne pas confondre dessiner et copier.
    Relis les algos que je que j'ai donné dans mon post précédent. J'ai pas passé 20mn à écrire tout ça pour que tu me dise le contraire de ce que j'ai expliqué.
    Je t'ai donné les techniques utilisé dans les jeux en 2D depuis des années, ce sont des techniques sûres et efficaces. Je veux bien détailler ce que tu ne comprend pas, mais fait l'effort d'essayer de comprendre.

    Pour ton problème de ralentissements, c'est parce que tu ne dois pas utiliser pas le double buffering. Il y a des tas de tuto sur la question un peu partout.

  6. #6
    Membre régulier
    Inscrit en
    Novembre 2002
    Messages
    291
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 291
    Points : 81
    Points
    81
    Par défaut
    merci de tes reponses,

    Excuse moi, j'ai du mal expliqué qqchose, en effet, je suis en c++.net, donc pas de code unsafe ...
    Ensuite il y a bcp plus que 9 surcharges :
    http://msdn2.microsoft.com/fr-fr/lib...ge(VS.80).aspx


    Sinon le double buffering est normelement géré par .NET 2 (avec setStyles avec optimzeddoublebuffered...) je ne revalide donc que les zones necessaires (qui correspond à ta solution 2.2 si j'ai bien compris ?) : je n'invalide que les zones necessaires t je reaffiche que si besoin..
    Il y a donc quelque chose que j'ai soit mal comprise, soit pas compris du tout ?

    Ensuite en effet je dois confondre copier et afficher. Car je ne vois pas ce que je copie ? je ne fais que afficher non ? la copie se fait automatiquement avec le double buffer géré par le framework, non ?

    Cependant ce qui m'inquiete le plus : certe gdi+ est peut etre lent, cependant je n'affiche que 3images de 2ko et ca commence deja à ramer....je pense que ca vient plus de moi je pense...


    Merci de ton aide, j'ai relus au moins 10 fois ce que tu as ecrit et je ne vois pas si j'ai mal fait qqchose !

Discussions similaires

  1. rafraichissement avec GDI+
    Par sdecorme dans le forum C#
    Réponses: 4
    Dernier message: 11/07/2012, 11h09
  2. [gdi] problème de zone de rafraichissement
    Par NiamorH dans le forum Windows
    Réponses: 2
    Dernier message: 06/08/2007, 11h45
  3. [C# + GDI]Panel transparent:Pb de rafraichissement
    Par Wolverin dans le forum Windows Forms
    Réponses: 9
    Dernier message: 26/06/2007, 10h57
  4. Probleme de rafraichissement d'un BDGrid
    Par marmotte dans le forum Bases de données
    Réponses: 10
    Dernier message: 28/05/2004, 18h07

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