2016-06-22 1 views
0

Je travaille sur un jeu en Java, basé sur l'aventure du jeu Atari. J'ai fait fonctionner correctement la partie KeyListener de base, mais j'ai ajouté une autre instruction if, en utilisant une autre classe, pour tester si le joueur allait frapper un mur et arrêter le mouvement si c'était le cas. La méthode que j'ai utilisée a également utilisé des instructions if, et quand j'ai couru le code, il y avait un retard MAJEUR. J'ai d'abord essayé une boucle en boucle, mais ça a fait encore pire. Quoi qu'il en soit, pour que ça ne soit pas trop lent? Cela ne semble pas si complexe qu'un programme à exécuter, et je dois encore ajouter une autre instruction if pour pouvoir passer dans une autre pièce, donc je dois faire quelque chose pour réduire massivement le décalage.Java jeu retard, trop si la déclaration?

Voici la classe:

class Player extends JPanel implements KeyListener{ 
    private char c = 'e'; 
    int x = 400; 
    int y = 400; 
    int mapX = 0; 
    int mapY = 0; 


    public Player() { 
     this.setPreferredSize(new Dimension(800, 500)); 
     addKeyListener(this); 
    } 

    public void addNotify() { 
     super.addNotify(); 
     requestFocus(); 
    } 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Environment Layout = new Environment(); 
     Layout.drawRoom(mapX,mapY,g); 
     g.fillRect(x , y , 20, 20);  
    } 
    public void keyPressed(KeyEvent e) { } 
    public void keyReleased(KeyEvent e) { } 
    public void keyTyped(KeyEvent e) { 
     c = e.getKeyChar(); 
     repaint(); 
     Environment Layout = new Environment(); 
     if(Layout.isWall(x,y,c)){} 
     else{ 
     if (c == 'a'){ 
      x = x - 3; 
     } 
     else if (c == 'w'){ 
      y = y - 3; 
     } 
     else if (c == 's'){ 
      y = y + 3; 
     } 
     else if (c == 'd'){ 
      x = x + 3; 
     }   
     } 
    } 

    public static void main(String[] s) throws IOException{ 
     JFrame f = new JFrame(); 
     f.getContentPane().add(new Player()); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.pack(); 
     f.setVisible(true); 
    } 
} 

La méthode de salle de tirage je dans c'était juste de mettre l'arrière-plan de la pièce en place.

Voici la méthode isWall de la classe Environnement:

public boolean isWall(int moveX, int moveY, char let){ 
     BufferedImage room = null; 
     try { 
     room = ImageIO.read(new File(xNum + "," + yNum + ".png")); 
     } 
     catch (IOException e) { 
     } 
     int[][] walls = convertImage(room); 
     boolean blocked = false; 
     if(let == 'w') { 
     if(walls[moveY-8][moveX] == -3584){blocked = true;} 
     } 
     else if(let == 's') { 
     if(walls[moveY+20][moveX] == -3584){blocked = true;} 
     } 
     else if(let == 'a') { 
     if(walls[moveY][moveX-5] == -3584){blocked = true;} 
     } 
     else if(let == 'd') { 
     if(walls[moveY][moveX+20] == -3584){blocked = true;} 
     } 
     return blocked;  
    } 

la méthode convertImage convertit seulement l'image de la pièce dans un tableau int, pour la valeur des couleurs. -3584 est la couleur des murs. Il est possible que ce soit ce qui est en retard, mais cela semblait être le meilleur moyen pour que chaque pièce fasse automatiquement les murs. J'ai également essayé une minuterie, mais soit j'ai mal fait, soit cela n'a pas aidé.

Je peux donner plus de mon code si c'est nécessaire, mais l'aide avec ceci serait très appréciée. Je suis relativement nouveau dans ce genre de choses, donc il me manque probablement quelque chose de grand. Merci.

+0

Obtenez un profileur. – Robert

Répondre

4

Le retard ici ne provient certainement pas des instructions if. Ce sont vraiment rapides. Je pense que le plus gros problème est dans isWall. Notez que chaque fois que vous voulez vérifier si un mur est présent, vous

  1. Ouvrir un fichier,
  2. lire le contenu du fichier,
  3. convertir le contenu du fichier d'une image à une grille de pixels, et
  4. lire exactement un pixel.

La lecture des fichiers à partir du disque est extrêmement lente par rapport aux valeurs en mémoire. Par exemple, un disque dur magnétique normal fonctionne à environ 7200 tr/min, de sorte que le temps de recherche est mesuré en millisecondes. D'un autre côté, votre processeur peut faire environ un milliard d'opérations par seconde, de sorte que les autres opérations prennent des nanosecondes. Cela signifie qu'un disque lu est à peu près un million de fois plus lent que d'autres opérations, ce qui est presque certainement d'où vous obtenez le décalage de!

Pour résoudre ce problème, pensez à réécrire votre code isWall afin que vous ne lisiez le fichier et n'effectuiez la conversion qu'une seule fois, et que vous ayez fait cela, il suffit de rechercher la partie de l'image dont vous avez besoin. Cela convertit des tonnes de lectures de fichiers (lentement glaciales) en un seul fichier (lent mais inévitable) lu, suivi de tonnes de lectures de mémoire rapides.

+0

Cela, a travaillé, merci beaucoup. Cela donne beaucoup plus de sens. Quelqu'un m'avait dit que c'était peut-être les déclarations if, et je pensais que cela semblait un peu étrange. – RacistPlatypus

0

Vous semblez déplacer vos murs plus loin que si vous déplacez votre lecteur.

Est-il possible que votre objet joueur se bloque dans un mur en produisant "bloqué = vrai" en continu?Votre personnage gagne + - 3 dans toutes les directions, mais vos murs semblent incohérents et vont de 8 à 20 jusqu'à 5 à 20 à droite.

+0

J'ai peut-être mal nommé les variables, moveY et moveX c'est plus de donner le mouvement théorique, les distances incompatibles sont temporaires, juste pour le rendre un peu meilleur dans mes tests, car avec certains murs le joueur 'tape' avant qu'il ne touche le mur, et sur certains il est parti partiellement dedans, en raison du x et y ne marquant pas les bords du bloc. Quoi qu'il en soit, ce n'est pas le problème, ça pourrait aller bien (pas beaucoup mieux, grâce à certaines de ces réponses). – RacistPlatypus

+0

* beaucoup mieux lol, pas, pas beaucoup mieux – RacistPlatypus

0

Ceci est une extension de la réponse de @ templatetypedef. Au lieu de charger les fichiers d'image lors de l'appel de la méthode isWall, vous pouvez envisager de mettre en cache tous les murs au début du jeu. Au lieu de charger les fichiers d'image lors de l'appel de la méthode isWall.

Alors je pense;

  1. ont une structure de données HashMap codée par <String, Integer>. Où String est vos coordonnées. Par exemple. Coordonner string = "100,238"
  2. analyser tous les fichiers image .png dans les répertoires et stocker les coordonnées en tant que clé et la valeur peut être n'importe quelle valeur fictive comme 1 ou 2.
  3. Ensuite, lorsque isWall() est appelée. Compte tenu des coordonnées X et Y, créez la chaîne de coordonnées comme indiqué au point 1 et vérifiez si la clé existe. Si c'est le cas, nous savons que c'est un morceau de mur d'autre pas.

Cela devrait considérablement réduire la contention du disque d'E/S.

À l'avenir, si vous souhaitez étendre la solution pour incorporer des API telles que isTreasureChest() ou isMonster(). Il peut être étendu en créant un appel de classe immuable "Room" ou "Tile" pour représenter l'objet. Ensuite, modifiez le HashMap à prendre en <String, Room>.

+1

Quel est le point de stockage des coordonnées qui ne sont pas un mur? Il suffit de stocker les murs et si une coordonnée n'est pas une carte/collection, alors ce n'est pas un mur. Cela diminuerait la mémoire nécessaire pour la carte/collection. – Tom

+1

Bonne idée. Puisque l'intention de l'appelant était de vérifier si X, Y est un mur. Mais il y a des avantages à tout stocker, par exemple si l'appelant veut vérifier d'autres choses, pas seulement des murs. Par exemple. hasTreasureChest ou hasMonster etc. Ensuite, le paramètre value peut être modifié pour inclure ces indicateurs. –

+1

Eh bien oui, alors il aurait besoin d'une sorte de classe 'Room' avec d'autres drapeaux pour une certaine coordonnée. Mais je n'utiliserais toujours pas de String pour les coordonnées: P. Le problème est que vous devez répéter deux faits partout où vous construisez ces chaînes: l'ordre des valeurs (x, y ou y, x) et le délimiteur char. Une classe immuable dédiée serait la meilleure, à mon avis. – Tom