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 :

Lancer d'une boule de billard


Sujet :

SDL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 15
    Par défaut Lancer d'une boule de billard
    Bonsoir, je réalise un jeu de billard en SDL.

    J'éprouve quelques difficultés pour faire en sorte que lors d'un lancer de boule blanche, celle ci suive la même trajectoire que la queue de billard (celle ci est modélisée par une surface, et est modifiée par rotations effectuée par l'utilisateur grâce à SDL_gfx.)

    J'ai donc décidé de me servir d'un moyen simple en utilisant la hauteur/largeur de la surface queue de billard pour que la boule suive la bonne trajectoire.

    Voici mon actuelle fonction de déplacement de la boule blanche :

    avec positionQb la position de la queue de billard, P ma variable de type Position (cf code plus bas), positionBb la position de la boule blanche (susceptible de changer), qBillard la surface modelisant la queue de billard, posBbInit la position initiale avant lancer de la boule blanche et cptdeplace un compteur permettant de détecter si le lancer a deja eu lieu :

    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
    void deplacerBoule(Position *P, SDL_Rect *positionQb, SDL_Rect *positionBb, SDL_Surface* qBillard, SDL_Rect *posBbInit, int cptdeplace)
    {
        if(cptdeplace == 0)
        {
            P->posX = positionBb->x;
            P->posY = positionBb->y;
        }
        cptdeplace = 1;
     
        if((positionQb->x + qBillard->w) < posBbInit->x)
            P->posX += (((positionQb->x + qBillard->w) - positionQb->x) / 10);
        else if(positionQb->x > (posBbInit->x + 20))
            P->posX -= (((positionQb->x + qBillard->w) - positionQb->x) / 10);
     
        if(positionQb->y < posBbInit->y)
            P->posY += (((positionQb->y + qBillard->h) - positionQb->y) / 10);
        if(positionQb->y >= posBbInit->y)
            P->posY -= ((positionQb->y - (positionQb->y + qBillard->h)) / 10);
    avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct
    {
       double posX,
              posY;
     
    } Position;
    , ceci devant me permettre de blitter la boule en fonction d'une position spécifique si P est défini :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (P == NULL)
                SDL_BlitSurface(Bb, NULL, ecran, &positionBb);
            else
                Blit(ecran, Bb, &P);
    , et ma fonction devant permettre de blitter la boule (je cast la position) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void Blit(SDL_Surface *ecran, SDL_Surface *Bb, Position *P)
    {
        SDL_Rect pos;
     
        pos.x = (int)P->posX;
        pos.y = (int)P->posY;
        SDL_BlitSurface(Bb, NULL, ecran, &pos);
    }
    Toutefois, cela ne fonctionne pas, et je ne vois pas pourquoi d'ailleurs.
    Erreur de types ? Avez vous une idée ?

    Merci.

  2. #2
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 084
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 084
    Par défaut
    Salut,

    Je comprend rien a tes fonctions et rien a ton probleme.

    Commente tes fonctions, fais des printf pour voir qu'est ce qui ne vas pas, et detaille nous ton probleme et ta demarche.

    C'est ton code, pas le notre et ya 10 000 facon de faire un billard.

    Deja, developpe tu en C ou en C++ ? ( je pense que c'est en C, mais je veux etre sur)
    Ensuite, tu dis que "ca ne marche pas". Qu'est ce qui ne marche pas ???
    La balle ne part pas quant tu tire ? La Balle suit une mauvaise trajectoire ?
    Comment la balle sait qu'elle va partir ?

    Si je me souviens bien, seul la balle blanche doit etre frapper.

    Voila comment je procèderai pour le tir.

    Lorsque l'utilisateur click du gauche, je retiens en memoire la position du click.
    Tant qu'il n'a pas relacher le bouton, il n'a pas encore tirer.
    Lorsqu'il le relache, je retiens en memoire cette deuxieme position.
    Je regarde la largeur/hauteur des deux position et je l'applique a la balle blanche.

    c'est sans doute ce que tu fais, mais je n'arrive pas a le voir.

    Bref, explique mieux tes morceaux de code et ton probleme.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 15
    Par défaut
    Bonjour SofEvans,

    déjà, mon programme est développé en C.

    Ensuite, quand je dis que mon programme ne fonctionne pas, c'est qu'en fait la boule blanche ne bouge pas de son point initial après un lancer. La boule blanche est donc blittée en permanence à la même position.

    La fonction SDL_PollEvent(); est appelée plus tôt dans le programme et donc en fonction des evenements la boule blanche devrait se déplacer périodiquement selon un laps de temps en utilisant SDL_GetTicks();

    Mon problème est un très probablement un problème de types :

    1. Je récupère la position de la boule blanche au premier appel de ma fonction deplacerBouler, en affectant un type SDL_Rect* (positionBb) à un float (posX et posY).
      P est de type Position, structure que j'ai défini, avec les champs posX variable de position en abscisse "x", et posY variable de position en ordonnée "y", tous deux étant des float.
      Déja, je me demande comment je devrais gérer ça pour que l'affectation se fasse correctement.
    2. Ensuite, je modifie la position de la boule blanche (P toujours) en l'incrémentant ou inversement de la manière suivante :
      Je calcule le nombre de pixels entre le début et la fin de la queue de billard (aussi bien en largeur qu'en hauteur) que je divise ensuite par une valeur arbitraire pour faire avancer la boule périodiquement.
      Là encore, j'effectue des opération sur des types SDL_Rect*, je divise ensuite par 10, et j'affecte le résultat à un float.
    3. Enfin, je blitte la boule après chaque micro-déplacement à cette position là de P en l'affectant à une variable de type SDL_Rect car la fonction SDL_BlitSurface(); doit recevoir ce type là.


    Après toute cette démarche, la boule blanche n'est pas blittée comme voulue, elle ne bouge pas au lancer comme dit plus haut.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (P == NULL)
                SDL_BlitSurface(Bb, NULL, ecran, &positionBb);
            else
                Blit(ecran, Bb, &P);
    A la condition if (P == NULL) elle renvoit probablement vrai étant donné que le programme blitte purement et simplement à la position initiale de la boule blanche.

  4. #4
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 540
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 540
    Par défaut
    Citation Envoyé par Ident01 Voir le message
    , et ma fonction devant permettre de blitter la boule (je cast la position) :

    Merci.
    je ne vois pas du tout l'intérêt de faire spécialement une fonction blit ...si tu regardes les codes sources de jeux vidéos tu as la plupart du temps une fonction de rendu ou tu appelles toutes les SDL_Surfaces que tu copies sur la surface d'écran primaire et puis tu appelles SDL_Blit dans cette fonction de rendu.

    Sinon le code est un peu incomplet.
    Quel algorithme utilises-tu pour faire bouger la boule ?
    En principe il faut prendre Bresenham
    Ensuite, je modifie la position de la boule blanche (P toujours) en l'incrémentant ou inversement de la manière suivante :
    Je calcule le nombre de pixels entre le début et la fin de la queue de billard (aussi bien en largeur qu'en hauteur) que je divise ensuite par une valeur arbitraire pour faire avancer la boule périodiquement.
    Est-ce qu'il y a dans ton code une fonction de mise-à-jour appelée à intervalles réguliers ?
    Il faut faire comme un timer qui appelle une fonction MAJ et dans cette fonction tu modifies les coordonnées de la boule..
    soit les coordonnées sont précalculées et tu les mets dans une liste chainée ( ou dans un std::list ce serait plus souple ) soit tu les recalcules à chaque MAJ.
    Mais sans le code complet c'est difficile..

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 15
    Par défaut
    Je ne connais pas d'algorithme autre que le petit calcul que j'ai fait pour bouger la boule.

    Il faut préciser que les mouvements que j'effectue pour le moment avec la queue de billard se font uniquement à gauche de la table, c'est à dire que ma queue de billard est uniquement capable de faire un premier lancer mais j'ai pas placé celle-ci ailleurs.

    J'ai bien une fonction appelée à intervalles réguliers, voici mon programme complet, ce devrait être plus clair je l'espère :

    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
    #include <stdlib.h>
    #include <stdio.h>
    #include <SDL/SDL.h>
    #include <SDL_image.h>
    #include <SDL_rotozoom.h>
     
    #include "constantes.h"
     
    int main(int argc, char *argv[])
    {
        SDL_Surface *ecran = NULL;
     
        SDL_Init(SDL_INIT_VIDEO); // Initialisation de la SDL
        // SDL_WM_SetIcon(IMG_Load("billard.jpg"), NULL); // Chargement de l'icone (inutile pour le moment)
        ecran = SDL_SetVideoMode(LARGEUR_FENETRE, HAUTEUR_FENETRE, 32, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_FULLSCREEN);
        SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 255));
        SDL_WM_SetCaption("Billard 2D", NULL); // Nouveau nom de fenêtre
     
        jeu(ecran);
     
        SDL_Quit();
        return EXIT_SUCCESS;
    }
    functions.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
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    #include <stdlib.h>
    #include <stdio.h>
    #include <SDL/SDL.h>
    #include <SDL_image.h>
    #include <SDL_rotozoom.h>
     
    #include "constantes.h"
    #include "functions.h"
     
    void jeu(SDL_Surface* ecran)
    {
        SDL_Surface *table = NULL, *Bb = NULL, *Qb = NULL, *rotation;
        SDL_Rect positionTable, positionBb, positionQb, posBbInit;
        SDL_Event event;
        Position *P;
        int continuer = 1, tempsPrecedent = 0, tempsActuel = 0, cptlancer = 0, cptdeplace = 0, *rebond;
        double angle = 0;
        double zoom = 1.0;
     
        table = IMG_Load("table.jpg");
        positionTable.x = ecran->w / 2 - table->w / 2;
        positionTable.y = ecran->h / 2 - table->h / 2;
     
        Bb = IMG_Load("Bb.bmp");
        SDL_SetColorKey(Bb, SDL_SRCCOLORKEY, SDL_MapRGB(Bb->format, 0, 0, 0)); // Le noir derrière la boule blanche devient transparent
        positionBb.x = LARGEUR_FENETRE / 3 + 25;
        positionBb.y = HAUTEUR_FENETRE / 2 - (Bb->h) / 2;
     
        Qb = IMG_Load("QB.bmp");
        SDL_SetColorKey(Qb, SDL_SRCCOLORKEY, SDL_MapRGB(Qb->format, 0, 0, 0)); // Le noir derrière la queue de billard devient transparent
        positionQb.x = LARGEUR_FENETRE / 3 - (Qb->w);
        positionQb.y = HAUTEUR_FENETRE / 2 - (Qb->h) / 2;
     
        rotation = Qb; // rotation prend l'image de la queue de billard (pour blitter rotation meme si il n'y a pas de rotation de l'image de Qb)
     
        posBbInit = positionBb; // posBbInit prend la position initiale de la boule blanche
     
        while(continuer)
        {
            SDL_PollEvent(&event); // Utilisation de PollEvent et non WaitEvent pour ne pas bloquer le programme
            switch(event.type)
            {
                case SDL_QUIT:
                    continuer = 0;
                    break;
                case SDL_KEYDOWN:
                    switch(event.key.keysym.sym)
                    {
                        case SDLK_a:
                            continuer = 0;
                            break;
                        case SDLK_ESCAPE:
                            continuer = 0;
                            break;
                        case SDLK_UP:
                            angle -= 1;
                            rotation = rotozoomSurface(Qb, angle, zoom, 0); // Transformation de la surface
                            positionQb.x = LARGEUR_FENETRE / 3 - (Qb->w);
                            positionQb.y -= (rotation->h / 10);
                            break;
                        case SDLK_DOWN:
                            angle += 1;
                            rotation = rotozoomSurface(Qb, angle, zoom, 0); // Transformation de la surface
                            positionQb.x = LARGEUR_FENETRE / 3 - (Qb->w);
                            positionQb.y += (rotation->h / 10);
                            break;
                        case SDLK_SPACE: // Recul de la queue de billard avant lancer
                            if (positionQb.x > LARGEUR_FENETRE / 3 - (Qb->w) - 25) // Si la queue de billard est placée correctement en abscisse avant la distance maximale
                            {
                                positionQb.x -= 1;
                                if (positionQb.y > HAUTEUR_FENETRE / 2 - (Qb->h) / 2)
                                    { positionQb.y += 1; }
                                else if (positionQb.y < HAUTEUR_FENETRE / 2 - (Qb->h) / 2)
                                    { positionQb.y -= 1; }
                            }
                            break;
                    }
                    break;
                case SDL_KEYUP:
                    switch (event.key.keysym.sym)
                    {
                        case SDLK_SPACE:
                            cptlancer = 1;
                            break;
                    }
            }
     
            // Avancement de la queue de billard lors du lancer
            if(cptlancer == 1 && (positionQb.x + rotation->w < posBbInit.x)) // Si le lancer a eu lieu et que la queue de billard est située avant la boule blanche au départ
            {
                positionQb.x += 1;
                if (positionQb.y > HAUTEUR_FENETRE / 2 - (Qb->h) / 2)
                    positionQb.y -= 1;
                else if (positionQb.y < HAUTEUR_FENETRE / 2 - (Qb->h) / 2)
                    positionQb.y += 1;
            }
     
     
            if(positionQb.x + rotation->w == posBbInit.x) // Si l'extremite de la queue de billard se trouve collé au côté droit de la boule
            {
                tempsActuel = SDL_GetTicks();
                if (tempsActuel - tempsPrecedent > 30) // Si 30 ms se sont écoulées
                {
                    if(!collisionTable(&positionTable, &positionBb, &rebond))
                    {
                        deplacerBoule(&P, &positionQb, &positionBb, &rotation, &posBbInit, cptdeplace);
                    }
     
                    if(collisionTable(&positionTable, &positionBb, &rebond))
                    {
                        //Partie a developper
                        ;
                    }
     
                    tempsPrecedent = tempsActuel; // Le temps "actuel" devient le temps "precedent" pour les futurs calculs
                }
                else // Si ça fait moins de 30ms depuis le dernier tour de boucle, on endort le programme un certain temps
                {
                    SDL_Delay(30 - (tempsActuel - tempsPrecedent));
                }
            }
     
            SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0));
     
            SDL_BlitSurface(table, NULL, ecran, &positionTable);
            if (P == NULL)
                SDL_BlitSurface(Bb, NULL, ecran, &positionBb);
            else
                Blit(ecran, Bb, &P);
     
            SDL_BlitSurface(rotation, NULL, ecran, &positionQb);
     
            SDL_Flip(ecran);
        }
        SDL_FreeSurface(table);
        SDL_FreeSurface(Bb);
        SDL_FreeSurface(rotation);
    }
     
    void deplacerBoule(Position *P, SDL_Rect *positionQb, SDL_Rect *positionBb, SDL_Surface* qBillard, SDL_Rect *posBbInit, int cptdeplace)
    {
        if(cptdeplace == 0)
        {
            P->posX = (double)positionBb->x;
            P->posY = (double)positionBb->y;
        }
        cptdeplace = 1;
     
        if((positionQb->x + qBillard->w) < posBbInit->x)
            P->posX += (double)(((positionQb->x + qBillard->w) - positionQb->x) / 10);
        else if(positionQb->x > (posBbInit->x + 20))
            P->posX -= (double)(((positionQb->x + qBillard->w) - positionQb->x) / 10);
     
        if(positionQb->y < posBbInit->y)
            P->posY += (double)(((positionQb->y + qBillard->h) - positionQb->y) / 10);
        if(positionQb->y >= posBbInit->y)
            P->posY -= (double)((positionQb->y - (positionQb->y + qBillard->h)) / 10);
    }
     
    int collisionTable(SDL_Rect* positionTable,SDL_Rect* positionBb, int *rebond)
    {
        if(!(positionTable->x + positionTable->w - 25 > positionBb->x + positionBb->w))
            *rebond = DROITE;
        if(!(positionTable->y + positionTable->h - 25 > positionBb->y + positionBb->h))
            *rebond = BAS;
        if(!(positionTable->x + 25 < positionBb->x))
            *rebond = GAUCHE;
        if(!(positionTable->y + 25 < positionBb->y))
            *rebond = HAUT;
     
    	if((positionTable->x + positionTable->w - 25 > positionBb->x + positionBb->w)
    	&& (positionTable->y + positionTable->h - 25 > positionBb->y + positionBb->h)
    	&& (positionTable->x + 25 < positionBb->x)
    	&& (positionTable->y + 25 < positionBb->y)
    	)
            return 0; // Si la balle ne touche aucun des 4 rebords
        return 1; // Si la balle touche un des rebords
    }
     
    void Blit(SDL_Surface *ecran, SDL_Surface *Bb, Position *P)
    {
        SDL_Rect pos;
     
        pos.x = (int)P->posX;
        pos.y = (int)P->posY;
        SDL_BlitSurface(Bb, NULL, ecran, &pos);
    }
    functions.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef struct
    {
       double posX,
              posY;
     
    } Position;
     
    void jeu(SDL_Surface* ecran);
    void deplacerBoule(Position *P, SDL_Rect *positionQb, SDL_Rect *positionBb, SDL_Surface* qBillard, SDL_Rect *posBbInit, int cptdeplace);
    int collisionTable(SDL_Rect* positionTable, SDL_Rect* positionBb, int *rebond);
    void Blit(SDL_Surface *ecran, SDL_Surface *Bb, Position *P);
    constantes.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #ifndef DEF_CONSTANTES
        #define DEF_CONSTANTES
     
        #define LARGEUR_FENETRE     1200
        #define HAUTEUR_FENETRE     800
     
     
        enum {HAUT, BAS, GAUCHE, DROITE};
     
    #endif

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 15
    Par défaut
    J'ai réussi à comprendre le problème, il s'agissait en fait des opérations sur les SDL_Rect* et SDL_Surface* qui posaient problème.

    J'ai rectifié en faisait des opérations uniquement sur des SDL_Rect*.

Discussions similaires

  1. lancer automatiquement une base 4D
    Par arwen dans le forum 4D
    Réponses: 17
    Dernier message: 13/09/2006, 06h30
  2. Boutons pour lancer/arrêter une animation Flash ?
    Par -=ET=- dans le forum ActionScript 1 & ActionScript 2
    Réponses: 3
    Dernier message: 01/05/2006, 02h54
  3. [Système] lancer / kill une application sous linux
    Par Antoine NSG dans le forum Langage
    Réponses: 1
    Dernier message: 31/10/2005, 16h06
  4. Algo de positionnement de aprticule pour une boule de feu .
    Par Clad3 dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 02/09/2005, 15h26

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