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

JavaScript Discussion :

Baisse croissante de fps inexpliqué


Sujet :

JavaScript

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Décembre 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Décembre 2019
    Messages : 3
    Par défaut Baisse croissante de fps inexpliqué
    Salut !

    Je débute en javascript, j'ai voulu me lancer dans la programmation d'un jeu Pacman. Jusque maintenant, son développement se passait bien, sans problème majeur.

    Puis j'ai ajouté les déplacements du personnage, et je me suis rendu compte que sa vitesse de déplacement se ralentissait au fur et à mesure. J’ai passé beaucoup de temps à essayer de comprendre pourquoi sans jamais réussir.

    J’ai finalement rajouté un compteur de fps (prit sur internet), et j’ai découvert que les fps de mon programme était décroissant. C’est-à-dire que lorsque je lançe le jeu, les fps passe de 60 à 50 en quelque secondes, puis à 40 et ainsi de suite jusqu’à être en dessous de 10 (et ce quelques soit le navigateur/ordinateur sur lequel le jeu est lancé)

    Cela fait un moment que je suis bloqué sans aucune solution. Je sollicite donc votre aide. Je précise que le jeu n’est qu’au début de son développement et qu’il ne faut pas me tenir rigueur pour une utilisation maladroite de la POO, je suis débutant.

    Le code faisant 700 lignes, ici le lien du dossier du jeu (avec le code un minimum commenté) : https://www.mediafire.com/file/6k0j5...acman.rar/file

    Voici quand même la partie principale du code :
    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
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    //canvas
    let canvas = document.getElementById('c1');
    let ctx = canvas.getContext('2d');
    window.onload = create;
     
    // images
    var img0 = new Image();
    img0.isLoad = false;
    img0.onload = function () {
        this.isLoad = true;
    }
    img0.src = 'sprite.png';
     
    // objet case
    var Case = [];
    function CaseCreation(a, b, c){
      this.posX = a;
      this.posY = b;
        this.id = c; // 0 = vide | 1 = point
     
        Case.push(this);
    };
     
    allCreation();
     
    // variables
    var x = (window.innerWidth/2)-223;
        y = (window.innerHeight/2)-247;
        score = 0;
     
    // -----------------------------------------------------------------------------
     
    var pacman = {
        posX : 10,
        posY : 10,
     
        posXmax : 10,
        posYmax : 10,
     
        ori : 'gauche',
     
        px : 0,
        py : 0,
        lx : 0,
        ly : 0,
     
        time : Date.now() - 15,
        tick : 15,
     
        deplacement : function() {
     
          if (pacman.ori == 'gauche') {
              pacman.posX -= 16;
              if (testPos() == 0) { pacman.posX += 16; } else {
                  pacman.posX += 16;
                  pacman.posXmax -= 16;
              }
     
          }
     
          if (pacman.ori == 'droite') {
              pacman.posX += 16;
     
              if (testPos() == 0) { pacman.posX -= 16; } else {
                  pacman.posX -= 16;
                  pacman.posXmax += 16;
              }
          }
     
          if (pacman.ori == 'bas') {
            pacman.posY += 16;
            if (testPos() == 0) { pacman.posY -= 16; } else {
                pacman.posY -= 16;
                pacman.posYmax += 16;
            }
          }
     
          if (pacman.ori == 'haut') {
            pacman.posY -= 16;
     
            if (testPos() == 0) { pacman.posY += 16; } else {
                pacman.posY += 16;
                pacman.posYmax -= 16;
            }
          }
     
          if (pacman.posXmax > pacman.posX) { pacman.posX += 8 }
          if (pacman.posXmax < pacman.posX) { pacman.posX -= 8 }
          if (pacman.posYmax > pacman.posY) { pacman.posY += 8 }
          if (pacman.posYmax < pacman.posY) { pacman.posY -= 8 }
     
        }
    }
     
    function updatePacman() {
     
      if (pacman.ori == 'gauche') {
          pacman.px = 15;
          pacman.py = 13;
          pacman.lx = 25;
          pacman.ly = 27;
      }
     
      if (pacman.ori == 'droite') {
          pacman.px = 13;
          pacman.py = 53;
          pacman.lx = 25;
          pacman.ly = 27;
      }
     
      if (pacman.ori == 'haut') {
          pacman.px = 13;
          pacman.py = 95;
          pacman.lx = 27;
          pacman.ly = 25;
      }
     
      if (pacman.ori == 'bas') {
          pacman.px = 13;
          pacman.py = 133;
          pacman.lx = 27;
          pacman.ly = 25;
      }
     
      if (Date.now() - pacman.time > pacman.tick) {
          pacman.time = Date.now();
          pacman.deplacement();
      }
     
    }
     
    // -- clavier --
    document.onkeydown = function(event) {
      // gauche
      if (event.keyCode == 37) {
          pacman.ori = 'gauche';
     
      }
     
      // droite
      if (event.keyCode == 39) {
          pacman.ori = 'droite';
      }
     
      // haut
      if (event.keyCode == 38) {
          pacman.ori = 'haut';
     
      }
     
      // bas
      if (event.keyCode == 40){
          pacman.ori = 'bas';
      }
     
    }
     
    function testPos() {
     
      var test = 0;
     
      for(var p=0; p < Case.length; p++){
     
        if (Case[p].posX == pacman.posX+12) {
          if (Case[p].posY == pacman.posY+12) {
              test = 1;
              Case[p].id = 0
          }
        }
     
      }
     
      return test;
     
    }
    // -----------------------------------------------------------------------------
     
    function create(){
     
        updatef();
     
    }
     
    // -- fonction principale --
     
    function updatef(){
     
        window.requestAnimationFrame(updatef);
     
        //fond
        ctx.fillStyle = 'rgb(0,0,0)';
        ctx.fillRect(0, 0, window.innerWidth,window.innerHeight);
     
      //map
        ctx.strokeStyle = 'rgb(33,33,255)';
        ctx.lineWidth = 2;
     
        exter();
        inter();
        forme();
        ctx.stroke();
     
        rectangle();
     
      //
     
      for(var p=0; p < Case.length; p++){
        if (Case[p].id === 1) {
              ctx.fillStyle = 'rgb(255,184,151)';
              ctx.fillRect(x+Case[p].posX, y+Case[p].posY, 4, 4);
        }
      }
     
      // pacman
      updatePacman();
     
        if (img0.isLoad) {
            ctx.drawImage(img0, pacman.px, pacman.py, pacman.lx, pacman.ly, x+pacman.posX, y+pacman.posY, pacman.lx, pacman.ly);
        }
     
    }

  2. #2
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 211
    Par défaut
    Bonjour,
    tout d'abord je n'ai pas regardé ton code au lien indiqué, il est plus heureux de mettre, si possible, un lien vers une page en ligne.

    Je ferais comme remarque, juste en regardant rapidement le code fourni :

    dans la fonction updatef, en règle général on fait ce qu'il y a à faire avant de relancer la fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function updatef(){
        //fond
        ctx.fillStyle = 'rgb(0,0,0)';
        ctx.fillRect(0, 0, window.innerWidth,window.innerHeight);
     
        // ... la suite ...
        window.requestAnimationFrame(updatef);
    }
    je ne saisie pas trop le principe de fonctionnement de ta fonction updatePacman avec ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      if (Date.now() - pacman.time > pacman.tick) {
          pacman.time = Date.now();
          pacman.deplacement();
      }
    mais bon je n'ai fait que survoler et un lien aiderait pour bien appréhender tout cela

  3. #3
    Candidat au Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Décembre 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Décembre 2019
    Messages : 3
    Par défaut
    Citation Envoyé par NoSmoking Voir le message
    Bonjour,
    tout d'abord je n'ai pas regardé ton code au lien indiqué, il est plus heureux de mettre, si possible, un lien vers une page en ligne.
    Le lien médiafire indiqué contient les images neccessaire au fonctionnement du jeu. Sur les pages en lignes, on ne peux pas supporté d'images.

    Citation Envoyé par NoSmoking Voir le message
    Je ferais comme remarque, juste en regardant rapidement le code fourni :

    dans la fonction updatef, en règle général on fait ce qu'il y a à faire avant de relancer la fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function updatef(){
        //fond
        ctx.fillStyle = 'rgb(0,0,0)';
        ctx.fillRect(0, 0, window.innerWidth,window.innerHeight);
     
        // ... la suite ...
        window.requestAnimationFrame(updatef);
    }
    Merci du conseil !! Malheuresement, ça n'a rien changer à la vitesse du programme.

    Citation Envoyé par NoSmoking Voir le message
    je ne saisie pas trop le principe de fonctionnement de ta fonction updatePacman avec ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      if (Date.now() - pacman.time > pacman.tick) {
          pacman.time = Date.now();
          pacman.deplacement();
      }
    Cela permet au pacman de se déplacer de 8 pixels toute les 15 millisecondes.

    Citation Envoyé par NoSmoking Voir le message
    mais bon je n'ai fait que survoler et un lien aiderait pour bien appréhender tout cela
    Quel type de lien ? le lien médiafire ne suffit pas ?

  4. #4
    Membre très actif
    Homme Profil pro
    bricoleur par les mots
    Inscrit en
    Avril 2015
    Messages
    744
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 80
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : bricoleur par les mots
    Secteur : Distribution

    Informations forums :
    Inscription : Avril 2015
    Messages : 744
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      if (Date.now() - pacman.time > pacman.tick) {
          pacman.time = Date.now();
          pacman.deplacement();
      }
    a ce moment autant mettre un setTimeout tu controlera mieux le temp

  5. #5
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 211
    Par défaut
    Citation Envoyé par oxymore11
    Quel type de lien ? le lien médiafire ne suffit pas ?
    non j'entendais par lien une page en ligne que l'on puisse tester directement, peu sont les personnes qui ouvrent les liens vers des fichiers zippés, et moi le premier.
    J'ai fais une exception et j'ai regardé plus avant ton projet, il y a pas mal de choses à dire

    •••
    La première chose à dire est que tu en fais trop, je veux dire par là que tu redessines des choses qui sont statiques, ici je parle du « fond » et c'est lui visiblement qui te prend une grosse partie des ressources.

    Une autre approche serait de mettre ton fond dans un <canvas> à part et de ne redessiner que ton pacman et tes dots.

    En partant de la structure HTML suivante :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <div id="cadre-canvas">
      <canvas id="canvas-pacman"  width=450 height=500></canvas>
      <canvas id="canvas-fond"    width=450 height=500></canvas>
    </div>
    on superpose les 2 <canvas> en mettant le « fond » par dessus, transparence oblige, et on applique le CSS suivant pour arriver à nos fins :
    Code css : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #cadre-canvas {
      position: relative;
      width: 450px;
      height: 500px;
      margin: auto;
      background-color: #000;
    }
    canvas {
      margin: auto;
      display: block;
      position: absolute;
      left: 0;
      top: 0;
    }
    au passage tu observeras que les dimensions ont été revues très largement à la baisse par rapport à toi, il n'est souhaitable de déclarer que ce dont on a besoin donc exit
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    <canvas id="c1" style="background-color: #EEE;" width="5000" height="5000"></canvas>
    De plus lorsque tu fais un clear de la zone avec un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ctx.fillRect(0, 0, window.innerWidth,window.innerHeight);
    outre l'incohérence des valeurs l'action est bien plus gourmande qu'un juste nécessaire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    Autre point à signaler, c'est que tes variables x et y peuvent être déclarées comme suit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // variables
    var x = 0;//(window.innerWidth/2)-223;
        y = 0;//(window.innerHeight/2)-247;
        score = 0;
    elle sont même limite inutiles !

    •••
    Passons à la partie drawFond qui devient une fonction à part entière que je te livre de façon un peu brute
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function drawFond() {
      const ctx = document.getElementById("canvas-fond").getContext('2d');
      ctx.strokeStyle = "rgb(33,33,255)";
      ctx.lineWidth = 2;
      exter(ctx);
      inter(ctx);
      forme(ctx);
      rectangle(ctx);
      ctx.stroke();
    }
    elle regroupe toutes les fonctions de dessins d'éléments de fond, ce qui change c'est que l'on passe en paramètre le contexte d'affichage, il faut donc
    modifier le prototype, la signature, de ces fonctions
    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
    function exter(ctx) {
      // ton code
    }
    function inter(ctx) {
      // ton code
    }
    function rectangle(ctx) {
      // ton code
    }
    function forme(ctx) {
      // ton code
    }
    function t(ctx, yy) {
      // ton code
    }
    •••
    Quand utiliser cette fonction ?

    En fait une seule fois à l'initialisation dans ta fonction create :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function create() {
      drawFond();
      updatef();
    }
    et uniquement là.

    •••
    Et ma fonction updatef alors ?

    Elle se simplifie pour ne prendre ne compte que ce qui change, cela pourrait donner :
    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
    function updatef() {
      // nettoyage fond
      ctx.fillStyle = 'rgb(0,0,0)';
      ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
      // tracé des dots
      ctx.fillStyle = 'rgb(255,184,151)';
      const nbr = Case.length;
      let ind;
      for (ind = 0; ind < nbr; ind += 1) {
        if (Case[ind].id === 1) {
          ctx.fillRect(x + Case[ind].posX, y + Case[ind].posY, 4, 4);
        }
      }
      // position pacman
      updatePacman();
      // affichage pacman
      if (img0.isLoad) {
        ctx.drawImage(img0, pacman.px, pacman.py, pacman.lx, pacman.ly, x+pacman.posX, y+pacman.posY, pacman.lx, pacman.ly);
      }
      // relance action -> trop rapide à mon avis
      window.requestAnimationFrame(updatef);
    }
    Il y aurait également à dire sur ta fonction updatePacman, mais essaies déjà cela, on verra ensuite pour d'autres optimisations basiques à prendre en compte.

  6. #6
    Candidat au Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Décembre 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Décembre 2019
    Messages : 3
    Par défaut
    Citation Envoyé par NoSmoking Voir le message
    non j'entendais par lien une page en ligne que l'on puisse tester directement, peu sont les personnes qui ouvrent les liens vers des fichiers zippés, et moi le premier.
    J'ai fais une exception et j'ai regardé plus avant ton projet, il y a pas mal de choses à dire
    Wow merci mille fois, je n'en attendais pas tant !!

    Avant ton message, j'ai fini par comprendre que la lenteur du code était en effet provoquée par la création du terrain (j'ai pu corriger tant bien que mal)

    Tes conseils me sont précieux, notamment le code en CSS !! je ne connais rien à ce langage, il va m'être hyper utile, merci encore.

    Juste une question par rapport à ce morceau de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    function create() {
      drawFond();
      updatef();
    }
    Si je comprends bien, la création du « terrain » ne se fait qu’un seule fois au début au lieu de se faire en boucle inutilement ? Mais si c’est le cas, les sprites qui se déplace ne vont pas effacer leur position précédente non ?

    Et ce commentaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      // relance action -> trop rapide à mon avis
      window.requestAnimationFrame(updatef);
    Trop rapide, c’est-à-dire ? on peut ralentir la vitesse à laquelle s’exécute les frames ?

    ----

    Je profite de ce message pour solliciter une nouvelle fois ton aide (plutôt que créer un nouveau post haha) : lorsque j’ai tenté de faire une suite d’addition avec un même chiffre à virgule, le résultat donné par le code était illogique. Par exemple quand on addition plusieurs fois d’affiler une variable avec 1.6, le résulté devient étrange.

    Pour :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    var x = 20;
    console.log(x);
    x += 1.6;
    console.log(x);
    x += 1.6;
    console.log(x);
    x += 1.6;
    console.log(x);
    Mon navigateur obtient ça :
    Nom : Sans e.png
Affichages : 129
Taille : 7,0 Ko
    Tu aurai une explication ou une solution à ce problème ?

Discussions similaires

  1. affichage de fps dans la barre de titre
    Par khayyam90 dans le forum OpenGL
    Réponses: 19
    Dernier message: 02/07/2004, 11h56
  2. Comment obtenir le fps ???
    Par olive-sjs dans le forum OpenGL
    Réponses: 2
    Dernier message: 25/02/2004, 07h32
  3. (Debutant) resolution et fps
    Par silverdelph dans le forum DirectX
    Réponses: 4
    Dernier message: 12/07/2003, 12h50
  4. Ordonner ds l'ordre croissant de 2 champs confondus
    Par Coolbens dans le forum Langage SQL
    Réponses: 11
    Dernier message: 17/06/2003, 16h39
  5. [MFC]Calculer les FPS
    Par inerti@ dans le forum MFC
    Réponses: 6
    Dernier message: 19/03/2003, 18h22

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