2013-03-22 81 views
0

我想從sprite網格使用BufferedImage和ImageIO的精靈圖像。有一個單獨的類來處理加載和存儲精靈圖像;這是問題出現的地方。我使用ImageIO將Sprite網格加載到BuffereImage中,出於某種原因,這會間歇性地阻止paintComponent被執行。然而,當程序確實載入程序正確顯示時,關鍵偵聽器停止工作。如果有幫助,我正在使用NetBeans 7.3。ImageIO.read防止paintComponent執行?

package breakout; 

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.awt.image.BufferedImage; 
import java.util.ArrayList; 
import java.util.Random; 

public class GamePanel extends JPanel implements Runnable { 
    private Paddle paddle; 
    private Breakout boRef; 
    private Circle ball; 
    private Graphics2D g2d, bufferedGraphics; 
    private BufferedImage buffer; 
    private Images images; 
    private final int WIDTH = Constants.WINDOW_WIDTH; 
    private final int HEIGHT = Constants.WINDOW_HEIGHT; 
    private ArrayList<Block> blockList; 
    private int numBlocks, blockRows, blockCols, ballXInc, ballYInc, blockPadding; 
    private int totalWidth, blockX, blockY; 
    private Thread ballThread; 
    private boolean started, gameOver; 
    private String gameOverText; 
    private Random rand; 

    public GamePanel(Breakout ref) { 
     boRef = ref; 
     images = new Images(); <-- Problem 

     numBlocks = 12; 
     blockRows = 4; 
     blockCols = 3; 
     blockList = new ArrayList<>(); 
     blockY = 100; 
     blockPadding = 5; 
     totalWidth = (blockCols * Block.WIDTH) + ((blockCols - 1) * blockPadding); 
     blockX = (WIDTH/2) - (totalWidth/2) - 60; 
     setupBlocks(); 

     rand = new Random();   
     gameOverText = ""; 
     started = false; 
     gameOver = false; 

     buffer = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); 
     bufferedGraphics = buffer.createGraphics(); 
     bufferedGraphics.setBackground(Color.LIGHT_GRAY); 

     ball = new Circle(250, 593, 6); 
     ball.setColor(Color.BLUE); 
     ballThread = new Thread(this); 
     ballXInc = 1; 
     ballYInc = -1; 

     paddle = new Paddle(this, 200, 600, 100, 15, Color.WHITE, Color.BLACK); 

     addKeyListener(new KeyHandler()); 
     setLayout(new BorderLayout()); 
     setFocusable(true); 
     requestFocus(); 
     System.out.println(" END"); 
    } 

private void setupBlocks() { 
    int xPos = Block.WIDTH + blockPadding, yPos = Block.HEIGHT + blockPadding; 
    int xInc = 1, yInc = 1; 

    for(int y = 0; y < blockRows; ++y, yInc++) { 
     for(int x = 0; x < blockCols; ++x, xInc++) { 
      blockList.add(new Block(xPos * xInc + blockX, yPos * yInc + blockY)); 
     } 

     xInc = 1; 
    } 
} 

    @Override public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g2d = (Graphics2D)g; 

     bufferedGraphics.clearRect(0, 0, WIDTH, HEIGHT); 
     System.out.println("HELLO"); 

     //bufferedGraphics.drawImage(images.getImage(), 100, 100, images.getImage().getWidth(), images.getImage().getHeight(), null); <-- DrawSprite 

     if(!gameOver) { 
      for(Block b : blockList) { 
       b.draw(bufferedGraphics); 
      } 

      ball.draw(bufferedGraphics); 
      paddle.draw(bufferedGraphics); 
     } else { 
      bufferedGraphics.setFont(new Font("Times New Roman", Font.BOLD, 48)); 
      bufferedGraphics.drawString(gameOverText, WIDTH/2 - 130, HEIGHT/2); 
     } 

     g2d.drawImage(buffer, 0, 0, WIDTH, HEIGHT, null); 
    } 

    private class KeyHandler extends KeyAdapter { 
     @Override public void keyPressed(KeyEvent e) { 
      if(paddle.x - 10 > -10 && e.getKeyCode() == KeyEvent.VK_LEFT) { 
       paddle.x -= 10; 

       if(!started) { 
        ball.setX(ball.getX() - 10); 
       } 
      } else if(paddle.x + paddle.width + 20 < WIDTH && e.getKeyCode() == KeyEvent.VK_RIGHT) { 
       paddle.x += 10; 

       if(!started) { 
        ball.setX(ball.getX() + 10); 
       } 
      } 

      if(e.getKeyCode() == KeyEvent.VK_SPACE) { 
       if(!started) { 
        ballThread.start(); 
        started = true; 
       } else if(gameOver) { 
        restart(); 
       } 
      } 


      repaint(); 
     } 
    } 
} 



package breakout; 

import java.awt.image.BufferedImage; 
import javax.imageio.ImageIO; 
import java.io.File; 
import java.awt.image.Raster; 
import java.awt.image.WritableRaster; 
import java.awt.Rectangle; 
import java.io.IOException; 

public class Images { 
    private BufferedImage texture, tex; 
    private BufferedImage [] images; 
    private String meshPath = "texture\\textures.png"; 
    private Raster imgRaster; 
    private WritableRaster imgWritableRaster; 

    public static final int TEX_WIDTH = 16; 
    public static final int TEX_HEIGHT = 8; 

    public Images() { 
     images = new BufferedImage[1]; 

     try { 
      texture = ImageIO.read(new File(meshPath)); <-- Seems to be the problem 
     } catch(IOException e) { 
      System.out.println(e.getMessage()); 
     } 

     imgRaster = texture.getData(new Rectangle(TEX_WIDTH * 2, 0, TEX_WIDTH, TEX_HEIGHT)); 
     imgWritableRaster = imgRaster.createCompatibleWritableRaster(); 

     tex = new BufferedImage(texture.getColorModel(), imgWritableRaster, false, null); 
     images[0] = tex; 
    } 

    public BufferedImage getImage() { 
     return images[0]; 
    } 
} 

回答

1

我加載精靈齧合到使用的ImageIO一個BuffereImage,並且出於某種原因此,間歇地,防止的paintComponent被執行。

這種性質的間歇性問題表明可能的線程衝突。我建議你在後臺線程中進行ImageIO.read(...)調用,例如使用SwingWorker對象獲得的後臺線程。

或者,您可以在主線程中讀取您的圖像,然後在圖像全部讀入後開始在Swing線程中排隊的GUI。這可能是我要做的。

public static void main(String[] args) { 
    // read in images here in code that is *not* in a background thread 

    SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     // start GUI in here 
    } 
    }); 
} 

當程序實際上不會正確加載程序顯示,但是,關鍵聽衆停止工作。如果有幫助,我正在使用NetBeans 7.3。

不要使用KeyListener,而要使用Key Bindings。這個教程非常好,如果你搜索這個網站,你會看到一些關於如何在動畫中使用它的例子。其中一些例子實際上是我寫的。例如: