Comment réduire le décalage dans mon jeu de plateforme java 2d?


Je fais un jeu de plateforme 2d en java Swing, et je me demande comment réduire le décalage que j'en tire. Je veux dire, il ne traîne pas trop mal mais il est perceptible que cela ralentit parfois. J'ai une minuterie de swing à 12 millisecondes, une fonction de cycle et une fonction de peinture.

public void cycle() {
    if (guy.getJumpState() == false) {
        if (canExecuteMovement(0, 4)) {
            onGround = false;
            if (guy.getY() > 300) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setY(platform[i].getY() - 4);
                }
            } else {
                // or just move the guy if not.
                guy.moveY(4);
            }
        } else {
            onGround = true;
        }
    } else {
        if (canExecuteMovement(0, -8)) {
            if (guy.getY() < 300) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setY(platform[i].getY() + 8);
                }
            } else {
                // or just move the guy if not.
                guy.moveY(-8);
            }
            jumpCount++;
            if (jumpCount >= 15) {
                jumpCount = 0;
                guy.setJumpState(false);
            }
        } else {
            jumpCount = 0;
            guy.setJumpState(false);
        }
    }

    if (guy.getDirection() == "left") {
        if (canExecuteMovement(-3, 0)) {
            if (guy.getX() < 450) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setX(platform[i].getX() + 3);
                }
            } else {
                // or just move the guy if not.
                guy.moveX(-3);
            }
        }
    } else if (guy.getDirection() == "right") {
        if (canExecuteMovement(3, 0)) {
            if (guy.getX() > 450) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setX(platform[i].getX() - 3);
                }
            } else {
                // or just move the guy if not.
                guy.moveX(3);
            }
        }
    }
}


public void paint(Graphics g) {
    super.paint(g); // something important
    Graphics2D g2d = (Graphics2D) g;

    // draw platforms
    for (int i = 0; i < platformCount; i++) {
        if (platform[i].getX() > -50 && platform[i].getX() < 950 && platform[i].getY() > -50 && platform[i].getY() < 650) {
            g2d.drawImage(platform[i].getImage(), platform[i].getX(), platform[i].getY(), this);
        }
    }

    // draw guy
    g2d.drawImage(guy.getImage(), guy.getX(), guy.getY(), this);

    // destroy unneeded processes
    Toolkit.getDefaultToolkit().sync();
    g.dispose();
}

Que puis-je faire pour optimiser cela et provoquer moins de décalage? Lorsque je crée un thread pour la fonction cycle elle-même, les plates-formes se séparent parfois pendant une fraction de seconde. Je suppose parce que puisque le fil est asynchrone, la moitié est effectuée pendant que la fonction paint continue.

Author: Qasim, 2012-01-24

3 answers

Quelques pensées lâches (cela fait des années que je n'ai pas fait d'animation dans Swing), et vous n'avez pas posté de code compilable.

  • Avez-vous essayé de faire paintComponent () - - - paint fait beaucoup d'autres choses. Et puis peut-être que vous devez ajouter repaint() pour cocher la fonction. Chaque fois que je rechargeaded peindre enden dans un désordre.
  • Essayez également d'augmenter le temps de tick --- vous perdrez moins de temps à réparer.
  • Aussi, je suppose que vous faites des tiques par des minuteries.
  • Je ne sais pas pourquoi vous disposez objet graphique
  • Essayez également de supprimer la synchronisation (j'ai fait des animations qui fonctionnent sur de nombreux oeses sans elle) Toolkit.getDefaultToolkit().sync()

Si cela n'aide pas, utilisez profiler pour trouver un goulot d'étranglement. Visual VM est assez agréable. Visual VM fait également partie du jdk pendant un certain temps --- il suffit d'aller dans le dossier bin et de lancer jvisualvm.

MODIFIER: (problèmes de thread)

  • Certaines personnes ont suggéré d'utiliser des threads --- que je diasgree. Si vous voulez faire du travail en dehors de l'EDT veuillez utiliser SwingWorker
  • Je suppose que vous n'appelez pas paint() mais appelez simplement repeaint(). Si vous appelez paint() (quelle que soit la magie noire que vous faites également pour la faire fonctionner), veuillez simplement appeler repaint() qui programmera le repaing au moment approprié.
 2
Author: jb., 2012-01-24 09:31:43

Tout d'abord, ce bit ici est un problème:

// destroy unneeded processes
Toolkit.getDefaultToolkit().sync();
g.dispose();

En général, disposer d'une ressource que vous n'avez pas créée est probablement une mauvaise idée. Dans ce cas spécifique, le Graphics passé dans paint() est probablement utilisé par tous les autres composants de la hiérarchie, donc cela pourrait provoquer des résultats vraiment étranges.

Appelant Toolkit.sync() voici je pense que votre tentative d'éliminer le déchirement que vous voyiez lorsque vous déplacez des choses en arrière-plan. Mais tout ce qu'il fait est de vider toutes les instructions de tirage en attente. Qui a aucun effet ici car vous dessinez probablement sur un composant Swing tamponné en arrière qui sera entièrement dessiné plus tard.

La bonne façon d'éliminer le déchirement est d'effectuer des mises à jour sur le thread d'événement, de sorte que vous ne modifiez pas les données de l'écran pendant le dessin. Une façon simple d'implémenter cela serait de demander à votre minuterie d'appeler simplement repaint() et d'avoir la méthode paint() call cycle() avant de faire quoi que ce soit.

Pour traiter le décalage, une solution pourrait être d'autoriser une trame variable taux. Au lieu de tout déplacer à une distance fixe chaque image, calculez le temps écoulé depuis la dernière image et déplacez tout en conséquence.

 1
Author: Russell Zahniser, 2012-01-23 23:52:31

Je créerais vos variables en dehors de la méthode afin qu'elle ne soit pas créée chaque fois que vous appelez cette méthode. La meilleure façon de programmer des jeux est de réutiliser les choses au lieu de détruire et de créer car détruire et créer coûte beaucoup de puissance de calcul.

Graphics2D g2d = (Graphics2D) g; <---declare it outside your method.

Et essayez également de trouver des conditions redondantes. J'en ai vu un où vous dites (si direction droite alors ..., sinon si direction à gauche ...); dites simplement (si direction droite alors ... autre ...). Les conditions ne coûtent pas beaucoup, mais quand vous appelez ce conditionnel 1000 fois par seconde, je pense que cela s'additionne. (idk cependant, mais je le fais juste au cas où et pour rendre les choses fluides)

Où vous dites setjumpstate(false) c'est redondant parce que quoi qu'il arrive, il est exécuté - déplacez-le simplement en dehors du conditionnel.

 1
Author: Alex Bedro, 2012-07-10 21:15:56