Compte à rebours en c++ et +

cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018 - 26 déc. 2010 à 18:32
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018 - 30 déc. 2010 à 20:02
Bonjour, je programme en c++ sur linux (debian / ubuntu) et je creer le jeu diamant, (il faut aligner trois formes). Je souhaite ajouter un "bonus" comme le temps, donc avec un compte à rebours que j'ai deja codé (tres simple) mais il me manque la fonction qui fait patientez juste le temps mais pas le jeu :
Je m'explique je souhaite enlever une seconde toutes les 1000 ms (car c'est souvent en ms) mais je souhaite pouvoir jouer en attendant vous voyez ?

Merci a tous de m'expliquez un peu le "fonctionnement de la fonction" avec le lib a inclure et tout et tout.

CLDT

9 réponses

pop70 Messages postés 181 Date d'inscription mardi 6 avril 2010 Statut Membre Dernière intervention 7 janvier 2012 10
29 déc. 2010 à 19:14
Petite rectification :

if (event.type SDL_KEYDOWN && event.key.keysym.sym SDLK_SPACE)
{
(pause % 2) ? pause false : pause true; // J'avais mis == à la place de =
} 




Pop70
1
pop70 Messages postés 181 Date d'inscription mardi 6 avril 2010 Statut Membre Dernière intervention 7 janvier 2012 10
28 déc. 2010 à 20:27
Si j'ai bien compris, le problème est de ne pas bloquer le jeu pendant le délai.

Pour ça si le jeu contient une boucle principale, ce qui est souvent le cas, il faut juste un compteur dans la boucle :

genre :

#include 
#include <time.h>

int main()
{
    clock_t chrono;
    double temps = 0;
    int secondes_restantes;
    int TEMPS_BONUS = 10;

    while (secondes_restantes > 0)
    {

        secondes_restantes = TEMPS_BONUS - temps;

        //...Jeu
        temps = (int(clock() - temps) / 1000);

        system("cls");
        std::cout << "Temps restant : " << secondes_restantes << "\n";

    }

}

Pop70
0
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018
28 déc. 2010 à 20:47
Bonjour,
Je vous remercie pour votre grande aide,
Par contre je suis en train de chercher pour faire une pause (pipi par exemple ^^) pendant le jeu en appuyant sur la barre espace.
j'ai fait cela :

void pause(SDL_Surface* &menuFond, SDL_Event &event)
{
SDL_PollEvent(&event);
if (event.type==SDL_KEYDOWN)
{
if (envent.key==SDLK_SPACE)
{
if (deja_pause==faux)
{
apply_surface( NULL, NULL, menuFond, SCREEN, NULL); // menufond (image de fond)
"timer_STOP";
"sauvegarde matrice des diamants"
"sauvegarde des points"
}

else
{
"timer_start";
"genere_grille = matrice sauvegardée"
"points= points sauvegardés"
}
}
}
}


donc comme vous pouvez le voir j'ai fait une detection SDLK_SPACE, mais le probleme se trouve a la sortie de la pause car il va me regenerer une nouvelle grille et remettre le compte à rebours au debut (disons 100 secondes), comment concerver ma matrice de diamants (creer une nouvelle matrice temporelle ?), et comment faire repartir le temps avec le temps sauvegardé (temps=temps_sauvegarde ? dans le else ?).

merci de me confirmer (ou m'infirmer) mes pistes et de me debloquer au niveau de la matrice.

Cordialement.
Je vous souhaite d'excellentes fêtes.
Cyril Z.
0
pop70 Messages postés 181 Date d'inscription mardi 6 avril 2010 Statut Membre Dernière intervention 7 janvier 2012 10
29 déc. 2010 à 19:12
Voila un petit code que j'ai testé et qui fonctionne :



#include 
#include <time.h>

bool Pause (int);

int main (int argc, char **argv)
{

    bool continuer = true;
    bool pause = false;

    int temps_bonus = 15;
    int temps_restant = temps_bonus;

    int temps_compte = 0;
    double temps_ecoule = 0;
    int temps_total = 0;
    double t1 = 0;
    double t2 = 0;


    while (continuer)
    {


        t1 = t2;
        t2 = clock();
        temps_ecoule += t2 - t1;

        if (temps_ecoule >= 1000)
        {
            temps_ecoule = 0;
            temps_total ++;

            if (!pause)
            {

                temps_compte ++;

                temps_restant = temps_bonus - temps_compte;

                if (temps_restant <= 0)
                {
                    continuer = false;
                }
            }

        }


        pause = Pause (temps_total);

        system ("cls");
        std::cout << "temps total : " << temps_total
        << "\n temps compte : " << temps_compte
        << "\n temps restant : " << temps_restant;


    }

    system ("cls");
    std::cout << "temps total : " << temps_total
    << "\n temps compte : " << temps_compte
    << "\n temps restant : " << temps_restant;
    std::cout << "\n\n";

    system ("PAUSE");
    return 0;
}

bool Pause (int t)
{
    bool retour = false;
    // simule une	Pause de 3 secondes: t 5, t  6 , t =  7
    if (t > 4 && t < 8)
    {
        retour = true;
    }
    return retour;
}




temps_ecoule compte les millisecondes et revient en zéro dès qu'il passe la secondes. A ce moment il incrément temps_total, qui est le temps global que dure la boucle. S'il n'y a pas de pause, le temps_compte s'incrémente aussi, mais si la pause est activé, alors il ne change pas.

temps_restant est le temps qu'il reste au joueur, c'est le temps_bonus - le temps passé sans la pause (donc temps_compte).
Si le temps_restant est inférieur ou égal à 0, le jeu s'arrête.

Pour simuler la pause, je passe temps_total en argument d'une fonction "Pause", celle-là renvoie vrai si le temps_total est entre 4 et 8 secondes exclus, et faux dans le cas contraire. ça a pour conséquence de 3 secondes.

A la place de cette fonction "Pause", en SDL tu active le booléen "pause" si le nombre de fois de la touche du clavier modulo 2 = 1 et le désactive si ça vaut 0.

exemple en gros (donc pas testé) :

if (event.type SDL_KEYDOWN && event.key.keysym.sym SDLK_SPACE)
{
(pause % 2) ? pause false : pause true;
} 


Mais je pense qu'il faudrait 2 touches et pas une :
une pour activer la pause, l'autre pour la désactiver.
Car si dans le code il y a le SDL_EnableKeyRepeat() activé, on ne peut plus compter le nombre de fois que le joueur à appuyé sur la touche Espace.

En tout cas, de cette manière, il n'y a plus besoin de réinitialiser les autres variables, car elle ne disparaissent pas.


Voilà, Bon courage :)

Pop70
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018
29 déc. 2010 à 21:42
Bonjour, je vous remercie encore énormément.
Par contre je ne voit pas comment on peut être sûr que 1000 tour dans la boucle while correspond a une seconde réellement (et non par rapport a temps_ecoule).

Sinon ne pensant pas a faire une pause controlée par le systeme (3sec) je pensais refaire une detection mais de la meme touche (espace) car je ne souhaitais pas mettre de SDL_EnableKeyRepeat() mais bien mon if (event.key==SDLK_SPACE). Esc-ce bien ?

De plus, pourquoi envoyer temps_total a Pause car t ne sera presque jamais (voir nullement) compris entre 4 et 8. Et
0
pop70 Messages postés 181 Date d'inscription mardi 6 avril 2010 Statut Membre Dernière intervention 7 janvier 2012 10
29 déc. 2010 à 22:51
t1, t2 et temps_ecoule sont en millisecondes, dans

if (temps_ecoule >= 1000), temps_ecoule est la sommes des millisecondes comprisent entre t1 et t2 :

      (T2 = clock())
T1 .......T2  
      (T2 devient T1)       (T2 = clock())
           ....................T2
                         (T2 devient T1)             (T2 = clock())
                                 .......................T2 
                                                      (T2 devient T1)


et ainsi de suite.
Chaque ligne de points est une durée en millisecondes qu'on ajoute à temps_ecoule (temps_ecoule += t2 - t1).
Si il y a 1000 points (donc 1000 millisecondes = 1s), on remet temps_ecoule a 0, on ajoute 1 au temps_total et on recommence jusqu'a avoir une seconde supplémentaire, et encore, et encore...

Je met temps_total à Pause, car temps_ecoule se réinitialise tout le temps, il ne dépasse pas 1, et si temps_compte était passé à pause, la boucle ne s'arrêterait jamais, car temps_compte ne s'incrémente plus justement quand il y a la Pause.

temps_total est le temps qui permet de faire une mesure sans interruption du programme.
               (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)(11)(12)(13)(14)
___________________________|  PAUSE    |_______________________________|FIN
temps_total :  +++.+++.+++.|+++.+++.+++|.+++.+++.+++.+++.+++.+++.+++.+++.
temps_compte : +++.+++.+++.|           |.+++.+++.+++.+++.+++.+++.+++.+++.


(pour l'exemple : 3+ représentent 1 s.)

Ici on dit que la pause est définie dès que temps_total > 3 et s'arrête quand elle est temps_total > 6. Durant ce temps, on cesse d'augmenter temps_compte.
Du coup on peut obtenir un temps de jeu = à temps compté de 11s alors que temps_total de l'exécution est de 14s.


si on dit que 3+ = 1s, dans le premier tour de boucle il ne peut très bien se passer que 1/3s et dans le deuxième 2/3s, temps écoulé sert à les additionner et à compter les secondes :

Tours:   Temps:
1         0.33s (temps_ecoule = 0 + 0.33)
2         0.77s (temps_ecoule 0.33 + 0.77 1s, donc temps_total++,
                 et temps_ecoule remis à 0)
3         0.25s (temps_ecoule = 0 + 0.25)
4         0.60s (temps_ecoule 0.25 + 0.60 0.85)
5         0.15s (temps_ecoule 0.85 + 0.15 1s, donc temps_total++,
                et temps_ecoule remis à 0)
...
et ainsi de suite



Pour la SDL, si SDL_EnableKeyRepeat()n'est pas mis, il n'y a pas de problème :
if (event.key==SDLK_SPACE)
{
(pause % 2) ? pause false : pause true;
/* pause % 2 = 1 donc vrai si l'utilisateur appui pour pause
 pause % 2 = 0 donc faux si il appui un nombre pair de fois,
donc pour enlever la pause, en fonction du résultat,
on enlève ou met la pause avec pause false ou pause true */
}


Voila, voila...

Pop70
0
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018
29 déc. 2010 à 23:56
Magnifique, avec vos superbes explications j'ai tout compris. Vu l'heure tardive je me pencherai plus en détails demain sur ce sujet.
Si je ne laisse plus de messages, c'est que tout s'est bien passé (et je l'espère !!!.
Je vous remercie infiniement pour votre aide.
cldt
0
pop70 Messages postés 181 Date d'inscription mardi 6 avril 2010 Statut Membre Dernière intervention 7 janvier 2012 10
30 déc. 2010 à 19:09
Tant mieux, mais au cas où il y a encore un problème , j'ai retrouvé un projet SDL que j'avais fait, j'ai remis un code presque similaire, la fenêtre affiche le compte à rebours. Par contre une seul touche ne marche pas bien (même sans SDL_EnableKeyRepeat()), ça viens peut-être de mon ordi, mais en tout cas pour l'exemple il y a 2 touches.
(Pour compiler le code, il faut arial.ttf dans le même dossier que l'exécutable (on peut la trouver dans ("C:\Windows\Fonts") et la dll SDL_ttf.dll.
Aussi, vu que c'est des touches qui vont gérer la pause, temps_total et Pause() peuvent partir :



#include <SDL.h>
#include <time.h>
#include 
#include <SDL_ttf.h>

int main(int argc, char *argv[])
{
    //***********SDL**************//
    SDL_Surface *ecran NULL, *texte NULL;
    SDL_Init(SDL_INIT_VIDEO);
    ecran = SDL_SetVideoMode(1024, 768, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
    SDL_Flip(ecran);
    SDL_Event event;
    SDL_Rect posText;
    char ch_compt[20] = "";
    bool continuer = true;

    //***********Variable pour pause *************//
    bool pause = false;

    int temps_bonus = 15;
    int temps_restant = temps_bonus;

    int temps_compte = 0;
    double temps_ecoule = 0;
    double t1 = 0;
    double t2 = 0;

    //*************Variable Texte ********//
    if (TTF_Init() == -1)
    {
        fprintf(stderr, "Erreur d'initialisation de Arial.ttf : %s\n", TTF_GetError());
        exit(EXIT_FAILURE);
    }
    TTF_Font *police = NULL;
    police = TTF_OpenFont("arial.ttf", 25);
    SDL_Color couleurRouge = {255, 0, 0};
    posText.x = 150;
    posText.y = 150;

    SDL_BlitSurface(texte, NULL, ecran, &posText);



    //************Boucle******************//

    while (continuer)
    {

        SDL_PollEvent(&event);

        t1 = t2;
        t2 = clock();
        temps_ecoule += t2 - t1;

        if (temps_ecoule >= 1000) // Si on passe une seconde,
        {
            temps_ecoule = 0;      // On remet temps_ecoule a 0.

            if (!pause)                  // Et si on n'est pas sur pause :
            {

                temps_compte ++;
                temps_restant = temps_bonus - temps_compte; // On descend le temps restant.


                sprintf(ch_compt, "Temps restant : %d", temps_restant);
                texte = TTF_RenderText_Blended(police, ch_compt, couleurRouge);

                if (temps_restant <= 0)
                {
                    continuer = false;     // Si le temps restant est inferieur à 0, on stoppe le jeu
                }
            }


        }



        if (event.type == SDL_KEYDOWN)
        {
            if (event.key.keysym.sym == SDLK_UP)  // Flèche du haut pour stopper la pause
            {
                pause = false;
            }
            if (event.key.keysym.sym == SDLK_DOWN)  // Flèche du bas pour l'activer
            {
                pause = true;
            }
            if (event.key.keysym.sym == SDLK_ESCAPE)  // Echap pour fermer la fenetre
            {
                continuer = false;
            }
        }

        if (!pause)     // Si il n'y a pas la pause :
        {

                    // Les variables de la matrice peuvent-être modifiées ici

        }




        SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
        SDL_BlitSurface(texte, NULL, ecran, &posText);
        SDL_Flip(ecran);
    }


    SDL_FreeSurface(ecran);

    SDL_Quit();
    return EXIT_SUCCESS;

}


Bon, avec ça devrait aller avec ça

Bon code !
Pop70
0
cs_tiouil Messages postés 51 Date d'inscription dimanche 8 août 2010 Statut Membre Dernière intervention 2 mars 2018
30 déc. 2010 à 20:02
Merci
0
Rejoignez-nous