2013-06-21 141 views
1

在閱讀本文之前,請明白我知道在編寫此代碼時有更好的方法。
這段代碼是很久以前發佈的,我對Java的瞭解比以前更多。儘管如此,我最近查看了代碼,並希望找出導致問題的原因,所以我知道將來會發生什麼。


更新: 我已經下載了JProfiler的實驗。事實證明,當我繪製字符串時,第158行的內存分配有一個巨大的峯值。但是,我不知道它到底意味着什麼,或者它爲什麼會導致巨大的滯後。此代碼如何導致暫停幾秒?

public void draw(Graphics g) { 
    if (isVisible) { 
     for (int i = 0; i < debugList.length - 1; i += 2) { 
      g.setColor(color); 
      g.setFont(font); 
      try { 
       g.drawString(debugList[i] + ":", xPos, yPos + (i * 15)); // Line 158 
       g.drawString(debugList[i + 1], xPos, yPos + 10 + (i * 15)); 
      } 
      catch (NullPointerException e) { 
       if (!errorDisplayed) { 
        System.out 
          .println("There was a problem while displaying the debug variables. Check to make sure you added all of the variables you declared in the debug constructor"); 
        errorDisplayed = true; 
       } 
      } 
     } 
    } 
} 

前陣子我正在一點點的2D平臺遊戲的遊戲,不得不修正錯誤的一個。我認爲修正錯誤的一個很好的方法是有一個調試類,它將在屏幕上顯示變量。事實證明,它效果很好!它顯示屏幕上的所有變量沒有問題!

但是,當我點擊一個鍵後,我調用changeVisible()(在代碼的最底部)方法後,它凍結了我的整個線程大約3秒鐘。

這並不重要,因爲它已經與我做的其他調試類過時了,但我仍然想知道是什麼導致未來項目的峯值。

import java.awt.Color; 
import java.awt.Font; 
import java.awt.Graphics; 

public class Debug { 
    private String[] debugList; 
    private boolean errorDisplayed = false, isVisible = true; 
    private Color color; 
    private int xPos = 0, yPos = 0, currentIndex = 0; 
    private Font font; 
    /** 
    * This constructor will create an array that can fit (numberOfVars) 
    * variables 
    * 
    * @param numberOfVars 
    *   - The amount of variables you wish to display 
    * @param setVisible 
    *   - Will toggle visibility on instantiation (true):on 
    *   (false):off 
    */ 
    public Debug(int numberOfVars, boolean setVisible) { 
     debugList = new String[numberOfVars * 2]; 
     if (setVisible) 
      isVisible = true; 
     else 
      isVisible = false; 
     color = new Color(0, 0, 0); 
     xPos = 20; 
     yPos = 30; 
     font = new Font("SanSerif",Font.BOLD,12); 
    } 

    /** 
    * This constructor will create an array that can fit (numberOfVars) 
    * variables 
    * 
    * @param numberOfVars 
    *   - The amount of variables you wish to display 
    * @param setVisible 
    *   - Will toggle visibility on instantiation (true):on 
    *   (false):off 
    * @param inputXPos 
    *   - The location of the text on the x axis 
    * @param inputYPos 
    *   - The location of the text on the y axis 
    */ 
    public Debug(int numberOfVars, boolean setVisible, int inputXPos, 
      int inputYPos) { 
     debugList = new String[numberOfVars * 2]; 
     if (setVisible) 
      isVisible = true; 
     else 
      isVisible = false; 
     color = new Color(0, 0, 0); 
     xPos = inputXPos; 
     yPos = inputYPos; 
    } 

    /** 
    * This method will initialize the variable you wish to display 
    * 
    * @param objectName 
    *   - the display name of the variable 
    * @param arg 
    *   - the value of the variable you wish to display 
    */ 
    public void addDebug(String objectName, Object arg) { 
     if (currentIndex + 2 <= debugList.length) { 
      debugList[currentIndex] = objectName; 
      debugList[currentIndex + 1] = arg.toString(); 
      currentIndex += 2; 
     } 
    } 

    /** 
    * This method will change the text color 
    * 
    * @param newColor 
    *   - the color of the debug text 
    */ 

    public void changeColor(Color newColor) { 
     color = newColor; 
    } 
    /** 
    * This method will change the text font 
    * @param font 
    *   - the font of the debug text 
    */ 
    public void changeFont(Font font) { 
     this.font = font; 
    } 
    /** 
    * This method will update the variable value 
    * 
    * @param objectName 
    *   - the name of the variable you wish to display (must be the 
    *   same name used in addDebug()) 
    * @param arg 
    *   - the value of the variable you wish to display 
    */ 
    public void update(String objectName, Object arg) { 
     for (int i = 0; i < debugList.length; i += 2) { 
      if (debugList[i] != null && debugList[i].equals(objectName)) { 
       if (i < debugList.length + 1) 
        debugList[i + 1] = arg.toString(); 
      } 
     } 
    } 

    /** 
    * This method will draw the debug information 
    * 
    * @param g 
    *   - The graphics you wish to paint on 
    * @param lineSpacing 
    *   - The display space between the variables 
    */ 
    public void draw(Graphics g, int lineSpacing) { 
     if (isVisible) { 
      if (currentIndex == debugList.length) { 
       for (int i = 0; i < debugList.length - 1; i += 2) { 
        g.setColor(color); 
        g.setFont(font); 
        try { 
         g.drawString(debugList[i] + ":", xPos, yPos 
           + (i * lineSpacing)); 
         g.drawString(debugList[i + 1], xPos, yPos + 10 
           + (i * lineSpacing)); 
        } 
        catch (NullPointerException e) { 
         if (!errorDisplayed) { 
          System.out 
            .println("There was a problem while displaying the debug variables. Check to make sure you added all of the variables you declared in the debug constructor"); 
          errorDisplayed = true; 
         } 
        } 
       } 
      } 
     } 

    } 

    /** 
    * This method will draw the debug information 
    * 
    * @param g 
    *   - The graphics you wish to paint on 
    */ 
    public void draw(Graphics g) { 
     if (isVisible) { 
      for (int i = 0; i < debugList.length - 1; i += 2) { 
       g.setColor(color); 
       g.setFont(font); 
       try { 
        g.drawString(debugList[i] + ":", xPos, yPos + (i * 15)); 
        g.drawString(debugList[i + 1], xPos, yPos + 10 + (i * 15)); 
       } 
       catch (NullPointerException e) { 
        if (!errorDisplayed) { 
         System.out 
           .println("There was a problem while displaying the debug variables. Check to make sure you added all of the variables you declared in the debug constructor"); 
         errorDisplayed = true; 
        } 
       } 
      } 
     } 
    } 

    /** 
    * Will toggle the visibility of the debug display 
    */ 
    public void changeVisible() { 
     isVisible = !isVisible; 

    } 
} 

主類(含調試註釋行是很重要的):

package com.bustedearlobes.platformergame; 

import java.applet.Applet; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.Point; 
import java.util.*; 
import javax.swing.JFrame; 
public class Game extends Applet implements Runnable { 
    private static final long serialVersionUID = 1L; 

    public static int pixelSize = 3; 

    public static double sx = 0, sy = 0, dir = 0; 

    public static Dimension windowSize = new Dimension(700,560), pixels = new Dimension(windowSize.width/pixelSize,windowSize.height/pixelSize); 

    public static Point mousePos = new Point(0,0); 

    public static boolean isRunning = false, 
      isMoving = false, 
      isJumping = false, 
      isMouseLeft = false, 
      isMouseRight = false; 

    public static String name = "2D Game"; 

    public static Level level; 
    public static Character character; 
    public static Inventory inventory; 
    public static Sky sky; 
    public static ArrayList<Mob> mobs = new ArrayList<Mob>(); 
    public static ArrayList<BrokenBlocks> brokenBlocks = new ArrayList<BrokenBlocks>(); 
    public static Spawner spawner; 
    public static Sound sound; 
    public static GameFile gameFile; 
    public static JFrame frame; 
    public static Tile tile; 
    public final static double GRAVITYCONSTANT = 1; 

    private Image screen; 

    public static Debug debug = new Debug(5,false); //Debug 

    public Game() { 
     setPreferredSize(windowSize); 

     addKeyListener(new Listening()); //Debug this is where the key listener is that calls the changeVisible() method 
     addMouseListener(new Listening()); 
     addMouseMotionListener(new Listening()); 
     addMouseWheelListener(new Listening()); 
    } 

    public void start() { // Defining all the objects required 
     requestFocus(); 

     tile = new Tile(); // Loading Images... 
     gameFile = new GameFile(); 
     level = new Level(); 
     character = new Character(Tile.tileSize, Tile.tileSize * 2); 
     isRunning = true; 
     sound = new Sound(); 
     inventory = new Inventory(); 
     sky = new Sky(); 
     spawner = new Spawner(10); 
     debug.changeFont(new Font("San Serif",Font.PLAIN,10)); // Debug 
     debug.addDebug("Player", character); // Debug 
     debug.addDebug("Side X", sx); // Debug 
     debug.addDebug("Side Y", sy); // Debug 
     debug.addDebug("Sky", sky); // Debug 
     debug.addDebug("Level.animation", level.animation); // Debug 
     new Thread(this).start(); 
    } 

    public void stop() { 
     isRunning = false; 
    } 

    public void tick() { 
     character.tick(); 
     level.tick(pixels.width/Tile.tileSize + 2,pixels.height/Tile.tileSize + 2); 
     sky.tick(); 
     inventory.tick(); 
     for (int i = 0; i < mobs.toArray().length;i++) 
      mobs.get(i).tick(); 
     for (int i = 0; i < brokenBlocks.toArray().length;i++) 
      brokenBlocks.get(i).tick(); 

     debug.update("Player", character); // Debug 
     debug.update("Side X", sx); // Debug 
     debug.update("Side Y", sy); // Debug 
     debug.update("Sky", sky); // Debug 
     debug.update("Level.animation", level.animation); // Debug 
    } 

    public void render() { 
     Graphics g = screen.getGraphics(); 

     g.setColor(new Color(100,100,255)); 
     g.fillRect(0,0,pixels.width, pixels.height); 

     sky.render(g); 
     level.render(g,pixels.width/Tile.tileSize + 2,pixels.height/Tile.tileSize + 2); 
     for (int i = 0; i < brokenBlocks.toArray().length;i++) 
      brokenBlocks.get(i).render(g); 
     for (int i = 0; i < mobs.toArray().length;i++) 
      mobs.get(i).render(g); 
     character.render(g); 
     inventory.render(g); 
     debug.draw(g); // Debug 
     g = getGraphics(); 
     g.drawImage(screen,0,0,windowSize.width,windowSize.height,0,0,pixels.width,pixels.height,null); 
     g.dispose(); 
    } 
    public static void main(String[] args) { 
     Game game = new Game(); 

     frame = new JFrame(); 
     frame.add(game); 
     frame.setTitle(name); 
     frame.setResizable(false); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 

     game.start(); 
    } 

    public void run() { 
     screen = createVolatileImage(pixels.width, pixels.height); 
     while(isRunning) { 

      tick(); 
      render(); 

      try { 
       Thread.sleep(5); 
      } catch (Exception e) { 
      } 
     } 
    } 

} 
+0

你是怎麼使用這段代碼的?發佈您的主要課程。 – Makky

+0

在上面發表。 – CHess

+0

-1捕捉'NullPointerException' –

回答

1

我不能立即看到的問題是什麼,可能除了一個事實,即debugList是一個列表,而不是一個HashMap。 (不知道這有多大的影響。)

但是,我可以告訴你如何找出自己。查看一個名爲JProfiler的工具。它允許您在代碼中查看逐行執行時間,這可以讓您看到瓶頸在哪裏。說明here

+0

我已經下載了JProfiler的一個實驗。事實證明,第158行的內存分配有一個巨大的峯值。查看我的帖子以獲取更多詳細信息 – CHess