begin process at 2010 02 10 10:27:56
  Trouver un code source :
 
dans
 
Accueil > Forum > 

C#

 > 

Multimédia

 > 

Image et Vidéo

 > 

Programme 2D très lent (gros débutant)


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

Programme 2D très lent (gros débutant)

samedi 7 juillet 2007 à 08:36:56 | Programme 2D très lent (gros débutant)

meuh_ou_jeje

Bonjour,

Tout d'abord, je tiens à dire que je suis très fortement débutant en programmation, surtout en c#.
Ayant depuis peu plusieurs heures à perdre, j'ai voulu faire un petit jeu en 2D (du style rpg).
Je n'utilise ni directx ni quoi que ce soit d'autre (je n'y connais absolument rien) et je me suis donc lancé en touriste avec pour seuls outils ceux de l'API de Visual Studio.

Mon problème se situe dans la redéfinition de la méthode onPaint du formulaire affichant le jeu.

protected override void OnPaint(PaintEventArgs e)
{
    carte.dessiner(e);
}


Allons voir la méthode dessiner :

public void dessiner(PaintEventArgs e)
{
    dessinerDecor(e);     // On dessine le décor
    dessinerUnités(e);    // puis les unités
}


Rien de bien palpitant, mais le problème est que à chaque déplacement d'une unité sur la carte, la méthode onPaint est appelée via la fonction invalidate(). Donc ça redessine tout à chaque fois que mon unité bouge, décor y compris (de plus, je redessine toutes les 100ms).
Le problème vient du décor qui prend un temps fou à se redessiner (1 seconde !!), car si je désactive le décor, tout se fait très fluidement.

C'est franchement pas génial de redessiner tout à chaque mouvement d'unité, mais je n'arrive pas à trouver une autre solution... J'ai essayé de faire des invalidate avec un rectangle comme argument pour ne redessiner que la zone où mon unité est en train de bouger, mais celà ne marche pas, ou du moins, je n'y arrive pas. :-(

Que faire? Je bloque sur ce point depuis des heures, et ce n'est franchement pas celui qui m'intéresse le plus. Le problème est que je ne peux pas avancer plus loin dans la programmation car la lenteur du programme empêche tout autre test.

PS: je stocke le décor dans une grilleDécor qui contient des objets Décor. Lors du dessin du décor, pour chaque élément Décor de grilleDécor, je dessine une image correspondant au type de décor (herbe, eau...). Ces images élémentaires sont en .gif de dimension 20x20 et pèsent moins de 100 octets.

Merci d'avance pour d'éventuelles réponses.
samedi 7 juillet 2007 à 09:54:53 | Re : Programme 2D très lent (gros débutant)

Julien237

Réponse acceptée !
Salut,
Il y a plusieurs précautions à prendre, d'abord ne dessine pas ta map directement sur le graphics donné par PaintEventArgs. Au chargement de ton jeu dessine la map statique sur un bitmap, puis utilise graphics.DrawImageUnscaledClipped lors du dessin en clippant le bon morceau. Tu devras utiliser graphics.TranslateTransform pour la placer au bon endroit. Rien qu'en faisant ça tu y gagneras déjà beaucoup.

Ensuite pour les autres éléments du décors, qui pourraient ne pas être statiques, appliquent la même technique à une différence près. Tu ajoute un flag booléen disant si le bitmap a besoin d'être redessiné ou pas. Lorsqu'une propriété affectant l'apparence de ton élément de décors change, tu lève le flag. Lors du dessin, si le flag est levé, tu l'abaisse et tu redessine ton bitmap, puis tu fais le rendu de la même manière qu'au point précédant.

Tu gagneras beaucoup à utiliser DrawImageUnscaled plutot que DrawImage. A toi de leur donner directment la bonne taille.

Essaye de voir ce qui prend vraiment du temps dans ton dessin, c'est pas toujours évident, utilise System.Diagnostic.Stopwatch pour mesurer les temps dans ton code.

Sinon la vraie solution ce serait quand même du directx, mais je pense que y'a quand même moyen de faire de chouettes choses avec GDI+...


Julien.
samedi 7 juillet 2007 à 10:10:24 | Re : Programme 2D très lent (gros débutant)

Bidou

Administrateur CodeS-SourceS
Moi je connais un gros wrapper directX qui s'appelle WPF






-Blog-
samedi 7 juillet 2007 à 10:36:43 | Re : Programme 2D très lent (gros débutant)

MorpionMx

Membre Club Administrateur CodeS-SourceS
Et XNA alors ?

Mx
MVP C#
 

samedi 7 juillet 2007 à 12:54:31 | Re : Programme 2D très lent (gros débutant)

Lutinore

Administrateur CodeS-SourceS

Salut, 1 seconde pour dessiner le background, c'est pas normal.. GDI+ n'est pas super performant mais avec un double buffer et en limitant les zones à dessiner on peut faire des choses sympas. 




public partial class Form1 : Form
{
    private const int WIDTH = 800; // client size width.
    private const int HEIGHT = 600; // client size height.
    private const int W = 20; // tile width.
    private const int H = 20; // tile height;
    private const int X = WIDTH / W; // tile x count.
    private const int Y = HEIGHT / H; // tile y count;

    private Bitmap[ ] tiles = null;
    private byte[ , ] map = null;

    public Form1( )
    {
        InitializeComponent( );

        this.ClientSize = new Size( WIDTH, HEIGHT );
        this.BackColor = Color.Black;
        this.FormBorderStyle = FormBorderStyle.FixedSingle;
        this.StartPosition = FormStartPosition.CenterScreen;
        this.SetStyle // Double buffer.
        (
            ControlStyles.AllPaintingInWmPaint |
            ControlStyles.OptimizedDoubleBuffer,
            true
        );

        // Les tiles font 20x20 pour eviter d'être redimensionnés.
        tiles = new Bitmap[ 4 ]
        {
            new Bitmap( "tile1.bmp" ),
            new Bitmap( "tile2.bmp" ),
            new Bitmap( "tile3.bmp" ),
            new Bitmap( "tile4.bmp" )
        };

        map = new byte[ X, Y ];

        Random r = new Random( ( int )DateTime.Now.Ticks );

        for( int x = 0; x < X; x++ )
        {
            for ( int y = 0; y < Y; y++ )
            {
                map[ x, y ] = ( byte )r.Next( 0, 4 ); // Aléatoire pour l'exemple.
            }
        }

        // Une boucle avec DoEvent peut être mieux qu'un timer,
        // ou invalider seulement dans un OnMouseDown ou KeyDown ..
        Timer t = new Timer( );
        t.Interval = 100;
        t.Tick += delegate
        {
            Invalidate( this.ClientRectangle );
        };
        t.Start( );
    }

    protected override void OnPaint( PaintEventArgs args )
    {
        //base.OnPaint( args );

        Graphics g = args.Graphics;

        for( int x = 0; x < X; x++ )
        {
            for ( int y = 0; y < Y; y++ )
            {
                g.DrawImage( tiles[ map[ x, y ] ], x * W, y * H );
            }
        }
    }
}

samedi 7 juillet 2007 à 21:09:49 | Re : Programme 2D très lent (gros débutant)

yann_lo_san

Il y a un moyen simple de ne redessiner que la partie qui est derriere le sprite qui vient de bouger :

1 - on dessine le fond (qui est presque toujours statique)
Image imgFond = new Bitmap("leFond.bmp");
g.Draw ect...

2 - dans la méthode qui deplace les sprites on récupère les coordonnées des sprites avant qu'ils ne bougent
int xOld = X_EN_COURS;
int yOld = Y_EN_COURS;
int w = sprite.Width;
int h = sprite.Height;

3 - On bouge le sprite

4 - On ne redessine du fond, que l'ancienne position du sprite de dimention de celui-ci

BitmapData bmpData = 
         imgFond.LockBits(new Rectangle(xOld, yOld, w, h), 
         ImageLockMode.ReadWrite,
         imgFond.PixelFormat);
  
int stride = bmpData.Stride;
System.IntPtr scan0 = bmpData.Scan0;

// morceau de l'image de fond a dessiner

Bitmap morceauBmp = new Bitmap(
   w,
   h,
   stride,
   imgFond.PixelFormat,
   scan0)

//
dessine le morceau
g.Draw ect...


//
on peut travailler au niveau pixel directement avec les pointeurs C#
// pour faire des effet de couleurs

unsafe
{
    byte* p = (byte*)(void*)scan0;
    int offset = stride - w * 3;
    p[offset] = 0x00ffff;
}

// UnlockBits(...)


Mais le mieux n'étant pas toujours l'ennemis du bien, DIRECTX en dotnet est très agréable à utiliser....

samedi 7 juillet 2007 à 21:41:02 | Re : Programme 2D très lent (gros débutant)

Julien237

Bon je recommence avec firefox vu qu'apparemment IE est allergique à ce forum (ou le contraire ?)

Je disais,
Si tu clippe la partie où ça a bougé, puis que tu demande de redessiner tout, normalement GDI ne redessine que la partie clippée non ?
Ce serait quelque peu plus simple non ?


Julien.
dimanche 8 juillet 2007 à 02:42:56 | Re : Programme 2D très lent (gros débutant)

meuh_ou_jeje

Problème résolu facilement !
Merci beaucoup pour toutes vos réponses, c'est très sympa.

J'ai suivi vos conseils et crée un bitmap qui sert pour le décor statique, et j'ai mis des flags pour redessiner éventuellement le décor modifiable. À vrai dire cette idée me trottait en tête avant de vous poser ma question mais je ne savais pas à l'époque comment déclarer une image.

class Carte
{
/* Attributs */
private static const int LARGEUR_CARTE = 460, LONGUEUR_CARTE=300;
private Bitmap decor = new Bitmap(LARGEUR_CARTE, LONGUEUR_CARTE);

...
/* Fonction permettant de dessiner tous les décors de la grille */
 private void dessinerDecor(PaintEventArgs e)
{
    Graphics g = Graphics.FromImage(decor);
    Pour chaque élément de la grille de décor, si son flag est à true
        {       
                elem.dessiner(g);
                mettre le flag à faux;
          }
                e.Graphics.DrawImageUnscaled(decor, 0, 0, LARGEUR_CARTE, LONGUEUR_CARTE);   // Puis finalement on dessine le décor
}

Voilà, c'est tout bête, tout simple et ça marche, il fallait donc créer une image fixe ! A chaque fois que le formulaire se rafraîchit, aucun problème, ça s'affiche direct.
Je m'occuperai du clipping plus tard, quand j'aurai des maps plus grandes :-)

Merci à vous tous et bonne journée.


Cette discussion est classée dans : problème, programme, unité, 2d, décor


Répondre à ce message

Sujets en rapport avec ce message

Limiter les ressources utilisé par un programme [ par kezyr ] BonjourVoila, j'expose mon problème : j'ai un programme avec une fonction qui comporte 14 boucle for imbriqué (oui je sais, c'est beaucoup, mais oblig Problème avec Windows Installer [ par DevilYann ] Salut G un petit problème urgent à résoudre car je bosse en informatique et je dois corriger ce bug le plus rapidement possible pour envoyer le corre TextBox + Problème [ par emmanuel9 ] Bonjour à tous, J'ai un textbox que j'ai dérivé et je l'ais appliqué à tout les textbox de mon programme, le problème est que mon textbox n'est pas Problème de sécurité.net [ par avildark ] Bonjour,actuellement je modifie un programme en c# que je n'ai pas concu, qui passea la compilation , a l'éxecution, mais des que je le met sur un lec Problème de mémoire [ par chandler8692 ] Salut, après 2 semaines acharnées, j'ai enfin fini le programme que j'avais entrepri defaire dans le cadre de mes TIPE. Je l'ai fini aujourd'hui mais problème avec une erreur [ par choukri175 ] Bonjour à tous et à toutes,J'ai un petit programme qui a bien marché dans une forme, alors je l'ai copié dans une autre form.lorsque j'exécute mon pro Form affiché l'écran [ par taoetc ] Bonjour,je vous explique mon problème :j'ai une form principale qui appelle une autre form ( mais pas en MDI). Je lance la seconde form en pricisant q Problème de compilation d'une Application C# sur SmartPhone [ par Mohammad000 ] SalamJ'ai un problème lors de la compilation d'un programme écris en Visual Studio 2008 (C#), Mon programme doit tourner dans un SmartPhone, il doit p Openfiledialog, problème bouton annuler [ par yabiyou ] Bonjour,J'ai dans mon programme une openfiledialog qui me perrmet de selectionner des fichiers pour la suite du code. Tout se passe bien lorsque je sé problème avec un fichier XML [ par suethi75 ] BonsoirJe développe un petite application en C# orienté Objet. Cependant, j'ai un soucis. private void button1_Click(object sender, EventArgs e)      


Nos sponsors


Sondage...

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,842 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales