SDL: Faire apparaître plusieurs voiture à la suite

Résolu/Fermé
kosuke.K Messages postés 489 Date d'inscription dimanche 13 mars 2011 Statut Membre Dernière intervention 29 octobre 2017 - Modifié par baladur13 le 26/11/2016 à 22:09
kosuke.K Messages postés 489 Date d'inscription dimanche 13 mars 2011 Statut Membre Dernière intervention 29 octobre 2017 - 18 déc. 2016 à 13:09
Bonjour à tous !

[U]Jeu[/U]: Tous les voitures (Car + Taxi) vont dans le même sens, mais si on accélère il faut donc éviter les taxis qui foncent vers nous, plus on tient dans le temps et plus on esquive de taxi, plus on aura de point.

J'essaye dont depuis un long moment de faire apparaître des taxis à la suite. J'y arrive pas ...
J'ai aussi d'autres problème :
- J'ai un problème au niveau des directions quand j'appuie par exemple sur gauche, normalement quand je relâche la touche la voiture est sensé s'arrêter or ici la voiture continue sa trajectoire.
- La souris fait aussi bouger ma voiture.

#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <time.h>
//constantes
#define LARGEUR_FENETRE 640
#define HAUTEUR_FENETRE 480
#define VITESSE 5


//alias
typedef struct objet objet;
typedef enum direction direction;
 
//structures et énumérations
enum direction
{
    DROITE,GAUCHE,BAS,HAUT
};
 
struct objet
{
    long positionx_Car;
    long positiony_Car;
    long taillex_Car;
    long tailley_Car;
 
    long positionx_Taxi;
    long positiony_Taxi;
    long taillex_Taxi;
    long tailley_Taxi;
 
    direction sens;
};

//Prototypage 
void deplacement(objet *source);
objet initobjet(objet retour1, SDL_Surface *image2, SDL_Surface *ecran);


//Main fonction
int main(int argc, char *argv[])
{
    //initialisation des variables
    SDL_Surface *ecran = NULL, *car = NULL, *taxi = NULL, *map=NULL;
    SDL_Rect positionCar, positionTaxi, positionMap;
    objet CarTaxi;
    SDL_Event event;
    int continuer = 1, tempsPrecedent = 0, tempsActuel = 0;
    SDL_TimerID timer;
 
    // Initialisation du générateur de nombre aléatoires
    srand(time(NULL));
 
    // Initialisation de SDL avec Gestion d'erreurs
    if (SDL_Init(SDL_INIT_VIDEO) == -1)
    {
        fprintf(stderr, "Erreur d'initialisation de la SDL");
        exit(EXIT_FAILURE);
    }
 
    // Chargement de l'icône de la barre de fenêtre AVANT SDL_SetVideoMode
    SDL_WM_SetIcon(IMG_Load("route.png"), NULL);
 
    // initialisation de la fenêtre avec les constante défini dans le préprocesseur
    ecran = SDL_SetVideoMode(LARGEUR_FENETRE, HAUTEUR_FENETRE, 32, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_INIT_TIMER);
 
    //petite vérification de la fenêtre
    if ( ecran == NULL )
    {
        fprintf(stderr, "Impossible de charger le mode vidéo : %s\n", SDL_GetError());
        exit(EXIT_FAILURE);
    }
 
    // On ajoute un titre
    SDL_WM_SetCaption("Gestion du temps en SDL", NULL);

        // on charge la route
    map = IMG_Load("route.png");

    // on fixe la position
    positionMap.x = 0;
    positionMap.y = 0;

    // on charge car
    car =  IMG_Load("car.png");

    // position par défaut de car
    CarTaxi.positionx_Car = 183;
    CarTaxi.positiony_Car = 330;

    //taille car
    CarTaxi.taillex_Car = car->w;
    CarTaxi.tailley_Car = car->h;

    // on configure l'affichage de car
    SDL_SetColorKey(car, SDL_SRCCOLORKEY, SDL_MapRGB(car->format, 0, 0, 255));
 
    // on charge le taxi
    taxi = IMG_Load("taxi.png");
 
    //initialisation
    CarTaxi = initobjet(CarTaxi, taxi, ecran);
 
    // On autorise la répétition de touches
    SDL_EnableKeyRepeat(10, 10);
 

    //Boucle infini (enfin presque...)
    while(continuer)
    {
        // On regarde si il y'a un événement, mais on ne bloque pas le programme
   while (SDL_PollEvent(&event)) // correct
        {  
        // Si il y'a un évènement SDL, on le traite
        switch(event.type)
        {
            case SDL_QUIT:
                continuer = 0;
                break;
            case SDL_KEYDOWN :
                switch(event.key.keysym.sym)
                {
                    case SDLK_ESCAPE: // Appui sur la touche Echap, on arrête le programme
                        continuer = 0;
                        break;
                    case SDLK_UP : // Flèche haut
                        CarTaxi.sens = HAUT;
                        break;
                    case SDLK_DOWN : // Flèche bas
                        CarTaxi.sens = BAS;
                        break;
                    case SDLK_RIGHT : // Flèche droite
                        CarTaxi.sens = DROITE;
                        break;
                    case SDLK_LEFT : // Flèche gauche
                        CarTaxi.sens = GAUCHE;
                        break;
                    default :
                        break;
                }
            default :
                break;
        }
} 
        // On initialise temps actuel pour savoir depuis quand le programme tourne
        tempsActuel = SDL_GetTicks();
 
        if (tempsActuel - tempsPrecedent > VITESSE) // Si 30 ms se sont écoulées depuis le dernier test
        {
            //déplacement
            deplacement(&CarTaxi);
 
            tempsPrecedent = tempsActuel; // Le temps "actuel" devient le temps "precedent" pour nos futurs calculs
        }
        else // Si ça fait moins de 30ms depuis le dernier tour de boucle, on endort le programme le temps qu'il faut
        {
            SDL_Delay(VITESSE - (tempsActuel - tempsPrecedent));
        }
 
        //gestion de colision
 
 
        //report des coordonées
        positionCar.x = CarTaxi.positionx_Car;
        positionCar.y = CarTaxi.positiony_Car;
        positionTaxi.x = CarTaxi.positionx_Taxi;
        positionTaxi.y = CarTaxi.positiony_Taxi;
 
        // on refait l'affichage avec les nouveau paramêtres
        SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
        SDL_BlitSurface(map, NULL, ecran, &positionMap);
        SDL_BlitSurface(car, NULL, ecran, &positionCar);
        SDL_BlitSurface(taxi, NULL, ecran, &positionTaxi);
        // on affiche le tout en premier plan
        SDL_Flip(ecran);
    }
 
    // libération de la mémoire
    SDL_FreeSurface(car);
    SDL_FreeSurface(taxi);
 
    // Libération du timer
    SDL_RemoveTimer(timer);
 
    // Fermeture de sdl et fin
    SDL_Quit();
 
    return EXIT_SUCCESS;
}



 
// Gestion du déplacement et de la colision avec les bords de la fenêtre
void deplacement(objet *source)
{
    //Déclaration des variables
    objet *position = source;
 
    switch(position->sens)
    {
        case DROITE :
            position->positionx_Car+=1; // On bouge car vers la droite
            // Si position car.x + largeur car dépasse la fenêtre
            if ((position->positionx_Car) > 315)
            {
                // on change de sens et on bouge car vers la gauche
                position->positionx_Car=315; 

            }
            break;
        case GAUCHE :
            position->positionx_Car-=1; // On bouge car vers la droite
            // Si position car.x + largeur car dépasse la fenêtre
            if ((position->positionx_Car) < 55)
            {
                // on change de sens et on bouge car vers la gauche
                position->positionx_Car=55; 

            }

            break;
        case BAS :
            position->positiony_Car+=1; // On bouge car vers la droite
            // Si position car.x + largeur car dépasse la fenêtre
            if ((position->positiony_Car) > 330)
            {
                // on change de sens et on bouge car vers la gauche
                position->positiony_Car=330; 

            }
            break;
        case HAUT :
            position->positiony_Car-=1; // On bouge car vers la droite
            // Si position car.x + largeur car dépasse la fenêtre
            if ((position->positiony_Car) < 280)
            {
                // on change de sens et on bouge car vers la gauche
                position->positiony_Car=280; 

            }
            break;
        default :
            break;
    }
 
}
 
 


objet initobjet(objet retour1, SDL_Surface *image2, SDL_Surface *ecran)
{
    int nombre_aleatoire = rand()%9;

    //taille taxi
    retour1.taillex_Taxi = image2->w;
    retour1.tailley_Taxi = image2->h;
 
    // position par défaut de taxi, endehors de l'écran
    retour1.positiony_Taxi= 0;
 
    switch(nombre_aleatoire){
        case 0:
            retour1.positionx_Taxi=60;

            break;
        case 1:
            retour1.positionx_Taxi=90;

            break;
        case 2:
            retour1.positionx_Taxi=110;

            break;
        case 3:
            retour1.positionx_Taxi=150;

            break;
        case 4:
            retour1.positionx_Taxi=210;

            break;
        case 5:
            retour1.positionx_Taxi=250;

            break;
        case 6:
            retour1.positionx_Taxi=290;

            break;
        case 7:
            retour1.positionx_Taxi=300;

            break;
        case 8:
            retour1.positionx_Taxi=310;

            break;
    }

    // on renvoie le tout
    return retour1;
 
}



Merci d'avance !

4 réponses

[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 29/11/2016 à 14:47
Salut kosuke.K,

Voilà ce que j'ai pu pondre sans y passer trop de temps.

C'est un code fonctionnel en SDL 1.2 (que tu sembles utiliser, plutôt que SDL2), et qui montre comment gérer les taxis prévus sur le jeu (30 taxis sur cette démo), leur vitesse relative par rapport à la voiture, qui a la possibilité d'accélérer ou de ralentir avec les touches haut ou bas, c'est à dire la conception décrite dans mon post initial.

Contrairement à la tienne, qui improvise l'apparition ou la disparition des taxis en ne gérant que ce qui s'affiche (avec tes 3 taxis maximum), cette conception gère tous les taxis que l'on rencontrera, et permet, en ralentissant, de faire revenir les taxis dépassés, et en accélérant de les dépasser sans les perdre si on doit ralentir, etc.

Les taxis et la voiture ont des vitesses différentes, et leurs déplacements sont gérés par le programme, qui ne calcule les coordonnées d'affichage que si on est dans la capacité d'affichage de la fenêtre de l'écran.

Pour faire quelque chose de rapide, je n'ai rien intégré d'autre (l'affichage de la voiture et son changement de file, la gestion des collisions, le score, l'affichage et défilement d'un décor pour donner l'illusion du déplacement même si les taxis et voitures roulent à la même vitesse, etc.), mais tu dois aussi travailler un peu... n'est-ce pas ? Et ce code n'a pour vocation que de te montrer comment fonctionne mon idée.

Dans cet exemple, tous les taxis roulent à la même vitesse, mais avec quelques modifications, cela permettrait aux taxis d'avoir des vitesses différentes entre eux (mais alors, tu dois gérer une "intelligence" des taxis, qui ralentissent et/ou changent éventuellement de file pour éviter de percuter d'autres taxis... mais rien d'insurmontable).

La boucle est courte, et distingue les fonctions de gestion des inputs, de déplacement des objets et d'animation. De même, les données sont séparées du code, gérées dans des struct et passées par pointeurs aux fonctions.

J'ai conservé la même gestion du temps que tu faisais, mais le SDL_Delay n'est, en fait, pas nécessaire dans cette gestion simplifiée.

/*
 * TAXIS    Une démo d'implémentation d'un système de gestion 
 *          d'objets animés en SDL, ayant des vitesses relatives 
 *          différentes et gestion de la visibilité sur la 
 *          fenêtre d'affichage        
 *
 * Version: @(#)taxis.c 1.0     29/11/2016
 *
 * Auteur:  [Dal] sur le forum de Commentcamarche.net
 *          http://www.commentcamarche.net/forum/affich-34091100#14
 *
 *      Licence Creative Commons by-nc-sa 3.0
 *      https://creativecommons.org/licenses/by-nc-sa/3.0/fr/
 *      Attribution avec le lien précité sur le forum
 */
#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <time.h>

/* constantes */
#define LARGEUR_FENETRE 640
#define HAUTEUR_FENETRE 480
#define VITESSE_INIT_VOIT 5
#define VITESSE_MAX_VOIT 10
#define VITESSE_MIN_VOIT 2
#define VITESSE_TAXI 4
#define VITESSE_JEU 10
#define NB_VOIES 3
#define LARG_TAXI 71
#define LONG_TAXI 78
#define ESPACE_TAXI (LONG_TAXI + (LONG_TAXI / 2))
#define MI_HAUTEUR_FENETRE (HAUTEUR_FENETRE / 2)

#define MAX_TAXIS   30  /* max taxis */

enum action {
    DROITE, /* pour changer de file */
    GAUCHE, /* pour changer de file */
    BAS,    /* pour ralentir */
    HAUT,   /* pour accélérer */
    RIEN    /* aucune touche pressée */
};

struct car {
    int vitesse;
    unsigned int y;     /* position y dans le monde, au départ
                           on place la voiture à l'origine 0 */
    enum action act;
};

struct taxi {
    int voie;
    unsigned int y;     /* position y dans le monde, 0 est le début de
                           la route */
    SDL_Rect coord;     /* coordonnées calculées à l'écran, si le taxi
                           est visible */
    int vitesse;
    int visible;
};

struct game {
    int loop;   /* continue loop or not */
    int score;
    int cur_time;
    int prev_time;
    int xvoies[NB_VOIES];   /* x coord pour chaque voie */
};

void init_objects(struct game * game, struct car * car, struct taxi taxis[]);
void move_objects(struct game * game, struct car * car, struct taxi taxis[]);
void get_input(struct car * car, int * continue_game);
void render(SDL_Surface *ecran, SDL_Surface *taxi, struct taxi taxis[]);

int main(int argc, char* args[]) {
    SDL_Surface *ecran = NULL;
    SDL_Surface *taxi = NULL;

    if (SDL_Init(SDL_INIT_VIDEO) == -1) {
        fprintf(stderr, "Erreur d'initialisation de la SDL");
        exit(EXIT_FAILURE);
    }
    ecran = SDL_SetVideoMode(LARGEUR_FENETRE, HAUTEUR_FENETRE, 32, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_INIT_TIMER);
    if (ecran == NULL ) {
        fprintf(stderr, "Impossible de charger le mode vidéo : %s\n", SDL_GetError());
        exit(EXIT_FAILURE);
    }
    taxi = IMG_Load("taxi.png");

    struct car car;
    struct taxi taxis[MAX_TAXIS];
    struct game game;

    init_objects(&game, &car, taxis);

    while (game.loop) {
        game.cur_time = SDL_GetTicks();
        get_input(&car, &game.loop);
        if (game.cur_time - game.prev_time > VITESSE_JEU) {
            game.prev_time = game.cur_time;
            move_objects(&game, &car, taxis);
            render(ecran, taxi, taxis);
        } else {
            SDL_Delay(VITESSE_JEU - (game.cur_time - game.prev_time));
        }
    }
    
    /* libérer tout et fermer */
    SDL_FreeSurface(taxi);
    SDL_Quit();

    return 0;
}

void init_objects(struct game * game, struct car * car, struct taxi taxis[]) {
    int n;
    /* rand */
    srand(time(NULL));
    /* game data */
    game->loop = 1;
    game->score = 0;
    game->cur_time = 0;
    game->prev_time = 0;
    /* positions horizontales par voies */
    for (n=0; n<NB_VOIES; n++)
        game->xvoies[n] = (LARGEUR_FENETRE / NB_VOIES / 2) 
            + ((LARGEUR_FENETRE / NB_VOIES) * n)
            - (LARG_TAXI / 2);
    /* init car */
    car->vitesse = VITESSE_INIT_VOIT;
    car->y = 0;
    car->act = RIEN;    
    /* init taxis */
    for (n=0; n<MAX_TAXIS; n++) {
        taxis[n].voie = rand() % NB_VOIES;
        taxis[n].y = ESPACE_TAXI * (n + 1);
        taxis[n].vitesse = VITESSE_TAXI;
        taxis[n].visible = 0;
        taxis[n].coord.w = LARG_TAXI;
        taxis[n].coord.h = LONG_TAXI;
    }
}

void move_objects(struct game * game, struct car * car, struct taxi taxis[]) {
    int n;
    int finished = 1;

    /* car */
    if (car->act == HAUT && car->vitesse < VITESSE_MAX_VOIT) {
        car->vitesse++;
    }
    if (car->act == BAS && car->vitesse > VITESSE_MIN_VOIT) {
        car->vitesse--;
    }
    car->y += car->vitesse;
    car->act = RIEN;
    /* taxis */
    for (n=0; n<MAX_TAXIS; n++) {
        /* décider, en fonction de la distance parcourue par la voiture
         * les coordonnées du taxi, et la dimension de l'écran graphique
         * si ce taxi est visible ou pas, et précalculer sa position
         * à l'écran s'il doit l'être */
        taxis[n].y += taxis[n].vitesse;
        if (abs(taxis[n].y - car->y) < MI_HAUTEUR_FENETRE) {
            taxis[n].visible = 1;
            taxis[n].coord.x = game->xvoies[taxis[n].voie];
            taxis[n].coord.y = MI_HAUTEUR_FENETRE - (taxis[n].y - car->y);
            finished = 0;
        } else
            taxis[n].visible = 0;
    }
    if (finished)
        game->loop = 0;
}

void get_input(struct car * car, int * continue_game){
    SDL_Event event;

    while (SDL_PollEvent(&event)) {  
        // Si il y'a un évènement SDL, on le traite
        switch(event.type) {
            case SDL_QUIT:
                *continue_game = 0;
                break;
            case SDL_KEYDOWN :
                switch(event.key.keysym.sym) {
                    case SDLK_ESCAPE: // Appui sur la touche Echap, on arrête le programme
                        *continue_game = 0;
                        break;
                    case SDLK_UP : // Flèche haut
                        car->act = HAUT;
                        break;
                    case SDLK_DOWN : // Flèche bas
                        car->act = BAS;
                        break;
                    case SDLK_RIGHT : // Flèche droite
                        car->act = DROITE;
                        break;
                    case SDLK_LEFT : // Flèche gauche
                        car->act = GAUCHE;
                        break;
                    default :
                        car->act = RIEN;
                        break;
                }
            default :
                break;
        }
    }
}

void render(SDL_Surface *ecran, SDL_Surface *taxi, struct taxi taxis[]){
    int n;

    /* clear everything */
    SDL_FillRect(ecran, 0, 0);
    /* draw taxis */
    for (n=0; n<MAX_TAXIS; n++) {
        if (taxis[n].visible)
            SDL_BlitSurface(taxi, NULL, ecran, &taxis[n].coord);
    }
    /* draw car, etc. */
    // TODO
    SDL_Flip(ecran);
}

Si tu utilises mon code, n'oublie pas de me citer :-)

Enjoy !


Dal
1
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 18/11/2016 à 15:03
Salut,

Je n'ai pas regardé dans le détail ton code, car je ne peux pas le tester.

Cependant, je comprends que, dans ton jeu, tu veux une voiture et plusieurs taxis, et que tu n'as qu'une seule voiture et un seul taxi.

Or, je vois que tu crées une struct avec un typedef "objet" dans la quelle tu mets les informations concernant une voiture et un seul taxi en créant une seule variable "objet".

Si tu veux gérer un nombre donné de taxis, tu devrais :

- créer une struct pour ta voiture
- créer une struct pour un taxi
- créer un tableau de struct pour stocker tes différents taxis et pouvoir itérer dans la liste des taxis, ou une liste chaînée, ou une autre structure de données.

Dans la conception de ton programme, tu devras décider si tu crées tous les taxis d'un coup, ou si tu ne stockes que les taxis qui sont visibles, sachant que tu pourrais les créer et les faire disparaître que lorsqu'ils ont besoin d'être affichés ou lorsqu'ils sortent de l'écran respectivement.

Une liste chaînée est intéressante dans ce 2ème cas, car tu n'as qu'à supprimer la tête ou ajouter un élément à la chaîne pour gérer ta liste de taxis... avec l'inconvénient qu'une fois ton taxi détruit parce qu'il sort de l'écran, tu ne gérera pas sa réapparition si ta voiture ralentit.

Eventuellement, pour éviter cet inconvénient, tu peux ajouter un champ dans la struct des taxis indiquant s'ils sont dans la zone d'affichage ou pas, et ne pas détruire ceux qui en sortent tout de suite, ce qui leur permettrait de "revenir".

C'est, d'ailleurs, un champ que tu devras inclure aussi si tu décides de créer tous les taxis d'un coup.


Dal
0
kosuke.K Messages postés 489 Date d'inscription dimanche 13 mars 2011 Statut Membre Dernière intervention 29 octobre 2017 37
Modifié par kosuke.K le 22/11/2016 à 05:58
Merci de votre commentaire, sachant que je suis un débutant en programmation et que je n'ai pas beaucoup de temps (projet à rendre dans les jours à venir c'est assez urgent), pouvez-vous me montrer un exemple et j'essayerais de le compléter.
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 22/11/2016 à 11:20
Pour un débutant, tu t'attaques à quelque chose de pas simple.

cela serait quelque chose comme :

struct car {
    int xecran;
    int y;
    int largeur;
    int longueur;
    enum direction sens;    /* la voiture peut changer de sens */
    int dist_parcourue;     /* distance parcourue par la voiture */
};

struct taxi {
    int xposition;      /* position x dans le monde, l'écran est 
                           une fenêtre sur ce monde */
    int xecran;
    int y;
    int largeur;
    int longueur;
    int visible;        /* les taxis ne changent pas de sens, mais 
                           ils peuvent être, ou non, visibles selon
                           la distance parcourue par la voiture */
};

(...)

void move_objects(struct car * car, struct taxi taxis[]) {
    int n;
    /* faire faire à car ce qu'il doit faire */
    // TODO
    for (n=0; n<MAX_TAXIS; n++) {
        /* décider, en fonction de la distance parcourue par la voiture,
         * la position du taxi dans le monde, et la dimension de 
         * l'écran graphique, si ce taxi est visible ou pas, et 
         * précalculer ses coordonnées à l'écran */
        // TODO
    }
}


avec taxis déclaré, par exemple, comme
struct taxi taxis[MAX_TAXIS];
... et un define définissant le maximum.

c'est juste pour te donner une idée de comment gérer plusieurs taxis :-)


Dal
0
kosuke.K Messages postés 489 Date d'inscription dimanche 13 mars 2011 Statut Membre Dernière intervention 29 octobre 2017 37
22 nov. 2016 à 20:20
Bonsoir,

ça y est j'ai refait mon programme avec 2 struct comme vous m'avez indiquer.
Par contre je n'ai pas compris la fonction void move_objects

Moi je suis partie sur l'idée de :


- Créer un tableau unidimensionnelle (chaque case correspond à la une route d’apparition du taxi)
Exemple 3 voies: positionx_taxi=0, positionx_taxi=100, positionx_taxi=150
- Lorsqu'un taxi apparaît, cette case est occupé mais les deux autres sont libre.
- Si la distance entre la première apparition est supérieure à 200 (positiony_taxi>200) alors sur une des deux cases apparaît un taxi.
- Une variable va à chaque fin de boucle vérifier si sur une voie est prise ou pas.
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
23 nov. 2016 à 09:32
la fonction
move_objects()
s'occupe de déplacer les objets de ton animation. Elle montre comment tu peux passer un tableau de struct à une fonction, et comment itérer sur ce tableau.
0
kosuke.K Messages postés 489 Date d'inscription dimanche 13 mars 2011 Statut Membre Dernière intervention 29 octobre 2017 37
26 nov. 2016 à 14:32
J'ai tout essayé j'y arrive pas...
0
kosuke.K Messages postés 489 Date d'inscription dimanche 13 mars 2011 Statut Membre Dernière intervention 29 octobre 2017 37
Modifié par kosuke.K le 29/11/2016 à 21:02
Bonsoir Monsieur Dal,

Déjà un très grand bravo ! Vous êtes une personne vraiment sympa de vouloir carrément faire la majeur partie de mon projet ! En plus, il fait exactement ce que je voulais. (accélération et décélération). Un très grand merci !

De mon coté j'ai réussi à faire défiler les taxis par contre il y a des bugs et un core dumped que je n'arrive pas à résoudre

Par ailleurs, même si je me suis lancé sur le C que depuis quelques semaines, il y a énormément de chose que je dois apprendre ou revoir dont notamment les bases du C avec les struct, tableaux, fonction ou pointeurs etc ...

Votre mini-programme est vraiment extraordinaire, mais je pense que je vais conserver le mien qui représente plus mon niveau actuelle. Je vais plutôt essayé de m'inspirer de ce que vous avez fait pour améliorer mon programme, parce que la gestion des apparitions ce n'est pas trop ça:

#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <time.h>
#include <SDL/SDL_ttf.h>
#include <string.h>
//header perso
#include "constantes.h"
#include "affichage_taxi.h"
#include "traitement.h"

void automatique(SDL_Surface *ecran, int continue1);
int valeur_random(int valeur);


//Main fonction
int main(int argc, char *argv[])
{
 SDL_Surface *ecran = NULL, *ecran1 = NULL;
 //int continue1 = 1;
 int continue2 = 1;

 automatique(ecran, continue2);
 SDL_Quit();

 return EXIT_SUCCESS;
}



void automatique(SDL_Surface *ecran, int continue1){
 //initialisation des variables
 SDL_Surface *car = NULL, *taxi = NULL, *map=NULL, *taxi2 = NULL, *taxi3 = NULL, *map2=NULL, *texte1=NULL;
 SDL_Rect positionCar, positionTaxi, positionTaxi2, positionTaxi3, positionMap, positionMap2, positiontxt1;

 Car Car;
 Taxi Taxi;
 Taxi2 Taxi2;
 Taxi3 Taxi3;
 SDL_Event event;
 SDL_Rect position;
 SDL_Color couleurNoire = {0,0,0};

 TTF_Font *police = NULL;
 int a = 0;
 int X=-533;
 char temps2[20] = "";
 int compteur = 0;
 int tempsPrecedent = 0, tempsActuel;
 int choix_alea;
 int A, B, C, k;
 int Y=0;
 int continuer = 1;

 TTF_Init();

 // Initialisation du générateur de nombre aléatoires
 srand(time(NULL)); 

 // Initialisation de SDL avec Gestion d'erreurs
 if (SDL_Init(SDL_INIT_VIDEO) == -1)
 {
  fprintf(stderr, "Erreur d'initialisation de la SDL");
  exit(EXIT_FAILURE);
 }


 // Chargement de l'icône de la barre de fenêtre AVANT SDL_SetVideoMode
 SDL_WM_SetIcon(IMG_Load("images/route_finale2.png"), NULL);

 // initialisation de la fenêtre avec les constante défini dans le préprocesseur
 ecran = SDL_SetVideoMode(LARGEUR_FENETRE, HAUTEUR_FENETRE, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);

 //petite vérification de la fenêtre
 if ( ecran == NULL )
 {
  fprintf(stderr, "Impossible de charger le mode vidéo : %s\n", SDL_GetError());
  exit(EXIT_FAILURE);
 }

 // On ajoute un titre
 SDL_WM_SetCaption("Gestion du temps en SDL", NULL);

 // on charge la route_finale2
 map = IMG_Load("images/route_finale1.png");
 map2 = IMG_Load("images/route_finale2.png");

 // on fixe la position
 positionMap2.x = 0;
 positionMap2.y = X;
 // on fixe la position
 positionMap.x = 0;
 positionMap.y = Y;

 // on charge car
 car =  IMG_Load("images/car.png");

 // position par défaut de car
 Car.positionx_Car = 190;
 Car.positiony_Car = 400;

 // taille car
 Car.taillex_Car = car->w;
 Car.tailley_Car = car->h;

 // on configure l'affichage de car
 SDL_SetColorKey(car, SDL_SRCCOLORKEY, SDL_MapRGB(car->format, 0, 0, 255));

 // on charge le taxi
 taxi = IMG_Load("images/taxi.png");
 taxi2 = IMG_Load("images/taxi.png");
 taxi3 = IMG_Load("images/taxi.png");

 /* Chargement de la police */
 police = TTF_OpenFont("fonts/OptimusPrincepsSemiBold.ttf", 30);

 //Position texte1
 positiontxt1.x=2;
 positiontxt1.y=10;

 // Déclaration de la variable temps_sec_ecoule
 int temps_sec_ecoule;
 temps_sec_ecoule=SDL_GetTicks()/1000; // Conversion du temps en seconde
 compteur=temps_sec_ecoule;


 while(continue1)

 {

  while (SDL_PollEvent(&event)) // correct
  {  
   // Si il y'a un évènement SDL, on le traite
   switch(event.type)
   {
    case SDL_QUIT:
     continue1 = 0;
     break;
    case SDL_KEYDOWN :
     switch(event.key.keysym.sym)
     {
      case SDLK_ESCAPE: // Appui sur la touche Echap, on arrête le programme
       continue1 = 0;
       // menu(ecran3,  continue3);
       break;
     }
     break;
   }

  }

  sprintf(temps2, "Appuyez sur ECHAP pour quitter");
  texte1 = TTF_RenderText_Blended(police, temps2, couleurNoire);



  choix_alea = valeur_random(k);
  switch(choix_alea)
  {
   case 85:
    A=-170;
    Taxi.positionx_Taxi = 85;
    if (Taxi.positiony_Taxi>533)
    {
     Taxi.positiony_Taxi=A;
    }
    else
    {
     Taxi.positiony_Taxi=Taxi.positiony_Taxi+1;
    }
    break;
   case 190:

    if (choix_alea == 190)
    {
     Taxi2.positionx_Taxi2 = 190;
     B=-170;
     if (Taxi2.positiony_Taxi2>533)
     {
      Taxi2.positiony_Taxi2=B;
     }
     else
     {
      Taxi2.positiony_Taxi2=Taxi2.positiony_Taxi2+1;
     }
    }

    break;
   case 295:

    if (choix_alea == 295)
    {
     Taxi3.positionx_Taxi3 = 295;
     C=-170;
     if (Taxi3.positiony_Taxi3>533)
     {
      Taxi3.positiony_Taxi3=C;
     }
     else
     {
      Taxi3.positiony_Taxi3=Taxi3.positiony_Taxi3+1;
     }
    }

    break;
  }

  Y = Y+2;
  positionMap.y = Y;
  positionMap2.y = X;
  if (positionMap.y = Y)
  {
   X=X+2;
  }
  if (positionMap.y > 533)
  { 
   X=-533;
   positionMap.y=X;
   Y=0;
   positionMap2.y=Y;
  }

  tempsActuel = SDL_GetTicks();
  if (tempsActuel - tempsPrecedent > VITESSE) // Si 30 ms se sont écoulées depuis le dernier test
  {
   tempsPrecedent=tempsActuel;
  }

  else // Si ça fait moins de 30ms depuis le dernier tour de boucle, on endort le programme le temps qu'il faut
  {
   SDL_Delay(VITESSE - (tempsActuel - tempsPrecedent));
  }



  //report des coordonées
  positionCar.x = Car.positionx_Car;
  positionCar.y = Car.positiony_Car;

  positionTaxi.x = Taxi.positionx_Taxi;
  positionTaxi.y = Taxi.positiony_Taxi;

  positionTaxi2.x = Taxi2.positionx_Taxi2;
  positionTaxi2.y = Taxi2.positiony_Taxi2;

  positionTaxi3.x = Taxi3.positionx_Taxi3;
  positionTaxi3.y = Taxi3.positiony_Taxi3;

  // on refait l'affichage avec les nouveau paramêtres
  SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
  SDL_BlitSurface(map2, NULL, ecran, &positionMap2);
  SDL_BlitSurface(map, NULL, ecran, &positionMap);
  //SDL_BlitSurface(taxi, NULL, ecran, &positionTaxi);
  SDL_BlitSurface(taxi2, NULL, ecran, &positionTaxi2);
  SDL_BlitSurface(taxi3, NULL, ecran, &positionTaxi3);
  SDL_BlitSurface(car, NULL, ecran, &positionCar);
  SDL_BlitSurface(texte1, NULL, ecran, &positiontxt1); 
  SDL_Flip(ecran);
 }

 SDL_FreeSurface(texte1);
 SDL_FreeSurface(map);
 SDL_FreeSurface(map2);
 SDL_FreeSurface(car);
 SDL_FreeSurface(taxi);
 SDL_FreeSurface(taxi2);
 SDL_FreeSurface(taxi3);
 SDL_FreeSurface(ecran);
 TTF_CloseFont(police);
 TTF_Quit();
 // Fermeture de sdl et fin
}

int valeur_random(int valeur){

 srand(time(NULL));
 const int MIN = 0, MAX = 2;
 int nombre_aleatoire = 0;

 // Nombre compris entre 0 à 3
 nombre_aleatoire = (rand() % (MAX + 1 - MIN)) + MIN;
 valeur = nombre_aleatoire*105 + 85;
 // Position d'apparition du Taxi
 return valeur;
}


Je ne sais pas si je vous demande trop mais si vous pouviez corriger ce problème ou me donner des indications sa serait génial.


PS: Je trouve que votre programme est assez complexe, mais si je devais prendre une partie de votre code c'est avec plaisir que je mettrais votre nom ;)
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
30 nov. 2016 à 01:23
Déboguer fait partie de la programmation... quand le programme n'est plus sous contrôle.

Compile ton programme avec l'option -g de gcc, et utilise un débogueur pour exécuter ton programme pas à pas, inspecter les variables et comprendre ce qui se passe.

Pour les core dump, il est probable que tu aies un problème de mémoire. Si tu es sous Linux, utilise valgrind pour exécuter ton programme, son rapport te signalera certainement des choses utiles.


Dal
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 30/11/2016 à 09:39
Une autre indication...

Pour l'affichage à l'écran, j'avais aussi constaté en rédigeant mon code et en regardant le tiens, que tu n'effaçais pas l'écran, avant de réécrire les objets, puis de les afficher avec le page flip (ou alors, je n'ai pas vu où tu le fais).

Si l'écran n'est pas effacé, ou que la réécriture n'efface pas d'une façon ou d'une autre ce qui a été écrit dans le buffer avant et qui n'est plus sensé y être, le
SDL_Flip(ecran);
ne va pas le faire à ta place, et tu peux avoir des "fantômes" qui restent à l'écran.

Vois ma fonction
render()
et l'usage de
SDL_FillRect()
avant d'écrire les objets.

void render(SDL_Surface *ecran, SDL_Surface *taxi, struct taxi taxis[]){
    int n;

    /* clear everything */
    SDL_FillRect(ecran, 0, 0);
    /* draw taxis */
    for (n=0; n<MAX_TAXIS; n++) {
        if (taxis[n].visible)
            SDL_BlitSurface(taxi, NULL, ecran, &taxis[n].coord);
    }
    /* draw car, etc. */
    // TODO
    SDL_Flip(ecran);
}

Dal
0
kosuke.K Messages postés 489 Date d'inscription dimanche 13 mars 2011 Statut Membre Dernière intervention 29 octobre 2017 37
18 déc. 2016 à 13:09
Bonjour Monsieur Dal,

Je vous remercie infiniment de votre aide mais si j'ai malgré tout fait à ma manière.

J'ai finalement décroché une note correct de 14,5, et je trouve que c'est pas mal pour un début en C.

Merci encore, et je vous souhaite par la même occasion de bonne fête et une très bonne année !

A bientôt.

Kosuke.K
0