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

SDL Discussion :

2 problèmes avec la SDL(évement et déplacement d'un sprite)


Sujet :

SDL

  1. #1
    Membre du Club Avatar de Jordinateur
    Profil pro
    Inscrit en
    Février 2007
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 119
    Points : 51
    Points
    51
    Par défaut 2 problèmes avec la SDL(évement et déplacement d'un sprite)
    Bien bonjour à tous et à toutes tout d'abord
    Je suis sous windows, j'ai CodeBlocks comme IDE et je code en C uniquement.
    Je suis actuellement en train d'apprendre la SDL depuis disons 3 semaines ou un peu plus...(je ne me souviens plus très bien)
    J'ai donc 2 petits problèmes avec la SDL dont je n'arrive pas à trouver les solutions tout seul...

    Le premier problème est le suivant :
    Lorsque j'appuis sur la touche ECHAP (que j'ai configurer comme étant une touche servant à fermer la fenêtre) ou que je clique sur la croix en haut à droite, il me faut le faire plusieurs fois avant que la fenêtre ne se ferme...
    Au début, croyant que c'était un lag, j'ai laissé passé, mais en fait sa n'en ai pas un




    Le deuxième problème est celui-ci :
    Mon programme sert à déplacer un personnage. L'affichage du sprite se fait dans la fonction principale et le déplacement du personnage (avec la mise à jour de l'écran, etc...) se fait dans la fonction que j'ai appellée "mouvemen.c"
    Je met les prototypes des fonctions dans un fichier header à part que j'ajoute à un fichier header pour la fonction "main".
    Mais lorsque j'appuis sur la touche qui sert à déplacer mon personnage, cela affiche comme prévue une image 32 pixel plus bas (puisque la touche est la flèche bas du clavier et que le quadrillage a des carreaux de 32X32 px), mais l'image n'est pas effacée alors que j'ai remplacée l'image précédente par un carreau noir(la couleur de fond est le noir);
    puis ensuite lorsque je réappuis sur la touche bas, il ne se passe plus rien

    En résumé, j'appuis une fois sur la touche bas, le sprite est réaffiché 32 pixel plus bas, mais l'image précédente du sprite ne s'affiche pas, et lorsque j'appuis une deuxième fois sur la touche bas, il ne se passe rien !



    Voici donc mes fichiers (je met uniquement les fichiers sources, sachant que les headers ne servent pas vraiment à quelque chose dans ce cas précis) :

    main.c :
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    //==============================================================================
    //{Directives de préprocesseur :
    //{Include :
    #include <stdlib.h>//Chargement de la bibliothèque standard stdlib.h
    #include <stdio.h>//Chargement de la bibliothèque standard stdio.h
    #include <SDL/SDL.h>//Chargement de la bibliothèque de la SDL
    #include <SDL/SDL_image.h>//Chargement de la bibliothèques pour gérer plusieurs types d'images en SDL
    # include "sdl_main.h"//Chargement des protoypes des fonctions du jeu
    //}
    //------------------------------------------------------------------------------------------------------------------------------------------
     
    //------------------------------------------------------------------------------------------------------------------------------------------
    //{Defines :
    #define LONGUEUR_FENETRE 640 //On définit la largeur de la fenêtre
    #define HAUTEUR_FENETRE 480 //On définit la longueur de la fenêtre
    #define RESOLUTION 32//Ici, le type de résolution (couleurs par pixels)
    #define TITRE_DE_LA_FENETRE "Yggdrasil"//Titre de la fenêtre
    //}
    //}
    //==============================================================================
     
    //==============================================================================
    int main(int argc, char *argv[])
    {//Début de la fonction principale
     
    	//Déclaration des variables et pointeurs et assignement de valeurs
    	SDL_Surface *ecran = NULL;
     
    	//Initialisation de la SDL
    	SDL_Init(SDL_INIT_VIDEO);
     
    	//Création d'une fenêtre sur la variable ecran
    	ecran = SDL_SetVideoMode(LONGUEUR_FENETRE, HAUTEUR_FENETRE, RESOLUTION, SDL_HWSURFACE | SDL_DOUBLEBUF);
     
    	//Titre (il faut le mettre juste après la création de la fenêtre)
    	SDL_WM_SetCaption(TITRE_DE_LA_FENETRE, NULL);
     
    	//Création des surfaces
    	SDL_Surface *personnage_principal = NULL;
    	personnage_principal = IMG_Load("images/personnages/héros/hero1_bas1.png");
     
    	//Mise à jour de l'écran
    	SDL_Flip(ecran);
     
    	//Mise en pause en attendant les événements
    	//{------------------------------------------------------------------------------------
    	//Déclaration des variables
        int continuer = 1;
        SDL_Event event;
     
    	//Boucle pour la pause
        while (continuer)
        {
        	//---------------------------------------------------------
    		//Gestion de la fermeture de la fenêtre
            SDL_WaitEvent(&event);
            switch(event.type)
            {//début du switch
                case SDL_QUIT:
                    continuer = 0;
    				break;
     
    			case SDL_KEYDOWN:
    					switch (event.key.keysym.sym)
    					{//début du switch
    						case SDLK_ESCAPE:
    							continuer = 0;
    							break;
    					}//Fin du switch
    					break;
            }//Fin du switch
    		//---------------------------------------------------------
     
     
    		//---------------------------------------------------------
    		//Gestion des mouvements du personnage et affichage de son sprite
    		mouvement(ecran, personnage_principal);
    		//---------------------------------------------------------
        }
    	//}------------------------------------------------------------------------------------
     
    	//Libération de la mémoire des surfaces
    	SDL_FreeSurface(ecran);
     
    	//Libération de la mémoire des systèmes de la SDL
    	SDL_Quit();
     
    	//Renvois de la valeur 0
    	return EXIT_SUCCESS;
    }//Fin de la fonction principale
    //==============================================================================

    mouvement.c :
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
    //{====================================================================
    //Includes et defines
    #include <stdlib.h>
    #include <stdio.h>
    #include <SDL/SDL.h>
    #include <SDL/SDL_image.h>
    #include <SDL/SDL_timer.h>
    //}====================================================================
     
     
    //====================================================================
    void mouvement(SDL_Surface *ecran, SDL_Surface *personnage)
    {//Début de la fonction
     
    	//Déclaration des variables et pointeurs et assignement des valeurs
    	SDL_Event event;
    	SDL_Rect coordonnees_personnage_principal;
     
    	//Enumérations
    	typedef enum direction direction;
    	enum direction
    	{//Début de l'énumération direction
    	HAUT = 1, BAS = 2, GAUCHE = 3, DROITE = 4
    	};  //Fin de l'énumération direction
     
    	//SDL_EnableKeyRepeat(10, 10);//répétition de la touche enfoncée
    	SDL_WaitEvent(&event);
    	switch(event.type)
    	{//début du switch
    			case SDL_KEYDOWN:
    				switch (event.key.keysym.sym)
    				{//Début du switch
    					case SDLK_UP:
    						break;
     
    					case SDLK_DOWN:
    						coordonnees_personnage_principal.y =coordonnees_personnage_principal.y + 32;
    						break;
     
    					case SDLK_RIGHT:
    						break;
     
    					case SDLK_LEFT:
    						break;
     
    				}//Fin du switch
    				break;
    	}//Fin du switch
     
    	//Bliltage des surfaces
    	SDL_BlitSurface(personnage, NULL, ecran, &coordonnees_personnage_principal);
     
    	//On efface la surface que l'on veut bouger
    	SDL_FillRect(personnage, NULL, SDL_MapRGB(ecran->format, 0, 0, 0));
     
    	//Mise à jour de l'écran
    	SDL_Flip(ecran);
     
    }//Fin de la fonction
    //====================================================================
    Je remercie d'avance tout ceux qui prêteront attention à ce sujet

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //Mise à jour de l'écran
    SDL_Flip(ecran);
    Pourquoi en mettre un avant la boucle ?

    Ton code va rester bloqué jusqu'à ce qu'un évènement se produise. Si tu appuies sur echap alors que tu te trouves dans la fonction mouvement, il ne se passera rien. De la même manière, si tu appuies sur une flèche alors que tu te trouves dans la boucle principale, rien ne se passera.

    Tu devrais d'une part utiliser SDL_PollEvent pour que l'appel ne bloque pas l'exécution de ton programme, d'autre part concentrer la gestion de tes évènements à un seul endroit.

    Ensuite, plutôt que d'effacer des portions de l'écran à chaque tour de boucle, habituellement on réaffiche tout complétement (ici donc tu aurais un fond noir pour tout effacer).

    D'un point de vue conceptuel, tu devrais également séparer la mise à jour de ton personnage de son affichage. C'est plus propre, ça évite de toute mélanger.

  3. #3
    Membre du Club Avatar de Jordinateur
    Profil pro
    Inscrit en
    Février 2007
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 119
    Points : 51
    Points
    51
    Par défaut
    La mise à jour sert à quoi fondamentallement ?

    Donc en fait je devrais plutot faire une fonction mouvements qui gère le mouvement du personnage en fonction des événements géré par la fonction main ?
    Comme sa sa devrait marcher ?

    D'autres part je ne saisi pas vraiment la différence entre SDL_WaitEvent et PollEvent...

    Et enfin comment je fais pour tout réafficher ?
    Je dois réafficher l'écran noir par dessus le sprite et réafficher le sprite par la suite, c'est sa ?

    Désolé pour ces questions, je débute !

  4. #4
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    La mise à jour sert à quoi fondamentallement ?
    Ce qu'on appelle mise à jour c'est globalement tout ce qui ne concerne pas l'affichage. Mouvement de ton personnage, collisions, etc.

    Donc en fait je devrais plutot faire une fonction mouvements qui gère le mouvement du personnage en fonction des événements géré par la fonction main ?
    Comme sa sa devrait marcher ?
    Ou plutôt, tu ne devrais appeler ta fonction mouvement que lorsque l'évènement approprié a été intercepté.

    D'autres part je ne saisi pas vraiment la différence entre SDL_WaitEvent et PollEvent...
    Le premier va attendre qu'il y ait un évènement à traiter, le second va retourner immédiatement même s'il n'y a pas d'évènement en attente. On utilise généralement le second, car on fait principalement des applications temps réel et on en veut pas que l'affichage se bloque lorsqu'il n'y a pas d'évènement à traiter.

    Et enfin comment je fais pour tout réafficher ?
    Je dois réafficher l'écran noir par dessus le sprite et réafficher le sprite par la suite, c'est sa ?
    Considère juste qu'à chaque nouveau tour de boucle tu repars avec un écran vide.
    Ensuite c'est juste une question d'afficher les choses dans l'ordre :
    - Ton fond
    - Ton personnage
    - ...
    Pour le fond utilise juste SDL_FillRect.

    Pour résumer, ta boucle devrait ressembler à ça :
    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
    while (continuer)
    {
        SDL_Event Event;
        while (SDL_PollEvent(&Event))
        {
            if (Event.type == SDL_QUIT)
                continuer = false;
     
            if (Event.type == SDL_KEYDOWN)
            {
                 switch (event.key.keysym.sym)
                {
                    case SDLK_ESCAPE : continuer = false; break;
                    case SDLK_LEFT :   position.x -= 32; break;
                    case SDLK_RIGHT :  position.x += 32; break;
                    case SDLK_UP :     position.y -= 32; break;
                    case SDLK_DOWN :   position.y += 32; break;
                }
            }
        }
     
        SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0));
     
        SDL_BlitSurface(personnage, NULL, ecran, &position);
     
        SDL_Flip(ecran);
    }

  5. #5
    Membre du Club Avatar de Jordinateur
    Profil pro
    Inscrit en
    Février 2007
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 119
    Points : 51
    Points
    51
    Par défaut
    sa sa serait donc la boucle de la fonction mouvement ?

    EDIT : En fait tu me conseil de mettre PollEvent dans les deux fonctions ?

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Non. C'est ta boucle principale, et il n'y a plus de fonction mouvement.

  7. #7
    Membre du Club Avatar de Jordinateur
    Profil pro
    Inscrit en
    Février 2007
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 119
    Points : 51
    Points
    51
    Par défaut
    Oui ba justement, en fait j'arrive a gérer tout sa dans la fonction principale, mais je crois que j'ai oublié de dire que je veux partitionner tout sa en plusieurs fichiers !

  8. #8
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Dans ce cas tu peux séparer toutes les fonctions ayant un rapport avec ton personnage, par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void mouvement_personnage(personnage* pers, int x, int y);
    void afficher_personnage(personnage* pers, SDL_surface* ecran);

  9. #9
    Membre du Club Avatar de Jordinateur
    Profil pro
    Inscrit en
    Février 2007
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 119
    Points : 51
    Points
    51
    Par défaut
    D'accord...
    Par contre qu'est ce que sa veut dire "personnage&pers" ?...

    Je vais essayer de faire ceci comme cela !
    Je posterais mes erreurs la prochaine fois !

  10. #10
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Citation Envoyé par Jordinateur
    Par contre qu'est ce que sa veut dire "personnage&pers" ?...
    Une erreur de ma part : je voulais en fait écrire "personnage*" (en gros, un pointeur sur une structure qui contient les infos de ton personnage). J'ai corrigé dans mon message précédent.

  11. #11
    Membre du Club Avatar de Jordinateur
    Profil pro
    Inscrit en
    Février 2007
    Messages
    119
    Détails du profil
    Informations personnelles :
    Âge : 32
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 119
    Points : 51
    Points
    51
    Par défaut
    D'accord ! Merci

    EDIT :
    Donc voilà ! J'ai essayé et il y a deux choses :
    Bon quand j'utilise SDL_PollEvent dans main (et en même temps PollEvent dans mouvements), l'image ne s'affiche pas, mais le fait d'utiliser PollEvent ne bloque pas le programme donc le problème pour fermer la fenêtre s'est résolu "tout seul" si je puis dire.
    Mais j'aimerais tout de même savoir pouquoi avec PollEvent dans main, l'image du perso ne s'affiche...

    Ensuite, j'aimerais savoir si la mémoire des variable est effacée lorsque la fonction mouvement est terminée et que l'on revient a main pendant un instant.
    J'en doutes, mais cela expliquerais le fait que lorsque j'appuis sur la touche bas, rien ne se passe(je veux dire par la que mon personnage ne bouge pas)

Discussions similaires

  1. Problème avec la SDL
    Par l'hachemi dans le forum SDL
    Réponses: 2
    Dernier message: 24/09/2007, 09h57
  2. Problème avec la SDL
    Par kaled1209 dans le forum SDL
    Réponses: 4
    Dernier message: 11/08/2007, 15h00
  3. Problème avec la SDL
    Par mjfcolas dans le forum SDL
    Réponses: 10
    Dernier message: 24/06/2007, 19h17
  4. Problème avec la sdl sur devc++
    Par cuicuicui dans le forum SDL
    Réponses: 3
    Dernier message: 07/08/2006, 13h04
  5. probléme avec la sdl et c++
    Par wikers dans le forum OpenGL
    Réponses: 1
    Dernier message: 10/11/2004, 19h02

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