2012-03-25 81 views
0

我正在製作一個可以產生巨大柵格的新遊戲(可以說是1000x1000)。玩家從中間開始尋找「積分」。玩家只能看到窗口中較大網格的一部分(15x15)。現在我只有一大堆矩形,每個矩形都繪製了我創建的一個泥土塊的bufferedimage。問題:我應該使用更好的變量類型來存儲所有這些圖像嗎?Java Swing巨大柵格

這是我的污垢類是什麼樣子(持有RECT,並在開始時產生的圖像):

public class Dirt extends Spot{ 
    private int index; 

    public Dirt(int temp){ 
     index = temp; 
    } 

    public Image getImageIndex(){return index;} 
} 

這裏是除了我Board類的繪製所有污物:

public class Board extends JPanel{ 
    private final int BLOCK_SIZE;         //Holds the size of each block 
    private final int SIZE;          //Holds the size of the board 
    private DirtImages[] imgs_Dirt = new DirtImages[20]; //Holds 20 random dirt images - generated at begtinning 

    private Spot[][] spots; 

    public Board(int size, int blocksize){ 
     SIZE = size; 
     BLOCK_SIZE = blocksize; 
     //Board 
     setSize(SIZE,SIZE); 
     //Timer Label 
     add(JTimerLabel.getInstance()); 

     //Create 20 random Images of dirt to use for the rest of dirts 
     for(int i = 0; i < 20; i++){ 
      imgs_Dirt[i] = new DirtImages(new Rectangle(0,0,BLOCK_SIZE,BLOCK_SIZE)); 
      add(imgs_Dirt[i]); 
     } 

     //Create Dirt 
     spots = new Dirt[500][500]; 
     java.util.Random randomGenerator = new java.util.Random(); 
     for(int i = 0; i < spots.length; i++){ 
      for(int j = 0; j < spots.length; j++) 
       spots[i][j] = new Dirt(randomGenerator.nextInt(20)); 
     } 
    } 

    public void paint(Graphics g){ 
     super.paint(g); 
     Graphics2D g2d = (Graphics2D)g; 
     g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 

     //Draw Grid #First 
     for(int i = 0; i < spots.length; i++){ 
      for(int j = 0; j < spots.length; j++) 
       if(spots[i][j] != null) 
        g2d.drawImage(imgs_Dirt[((Dirt)spots[i][j]).getImageIndex()].getImage(), BLOCK_SIZE*i,BLOCK_SIZE*j,BLOCK_SIZE,BLOCK_SIZE, null); 
     } 

     Toolkit.getDefaultToolkit().sync(); 
     g2d.dispose(); 
     requestFocus(); 
    } 

只是爲了澄清。我創建了20個污垢圖像,以便污漬(塗漆時)看起來不像是平鋪的,而是隨機的。所以在我的一系列Dirt中,每個Dirt指向一個隨機圖像。

附加問題:現在我創建了我的巨大網格,我將如何製作它,以便玩家從中心開始繪製周圍的單元格。目前我從數組左上角的數組開始。我應該創建一個布爾標誌爲每個污垢是否應該繪製?

+2

如果是相同的泥土塊,保持一個實例和油漆它與需要的地方。順便說一句 - 對於'JPanel'覆蓋'paintComponent(Graphics)'而不是'paint(Graphics)' – 2012-03-25 15:49:55

+0

http://codereview.stackexchange.com/ – 2012-03-25 15:52:12

+0

或者創建一個JLabel網格並填充ImageIcons - 允許它們在JLabels中共享。 – 2012-03-25 17:32:10

回答

3

如果你有100萬污垢和20個圖像,在每個污垢中存儲圖像是一種浪費。您可以改用索引。所以畫畫,而不是拉

((Dirt)spots[i][j]).getImage() 

你將抓

imgsDirt[((Dirt)spots[i][j]).getImageIndex()] 

對於更新的問題:

你似乎繪製你的整個網格(0-1000,0-1000) 。你真正想要的只是繪製15x15'可揮杆'區域。因此,而不是

//Draw Grid #First 
    for(int i = 0; i < spots.length; i++){ 
     for(int j = 0; j < spots.length; j++) 

這將是

//Draw Grid #First 
    for(int i = player.xpos-7; i < player.xpos+7; i++){ 
     for(int j = player.ypos - 7; j < player.ypos+7; j++) 

您需要在您的drawImage方法的適當轉移,以確保它仍然開始在你的窗口的左上角畫。

+0

除此之外,爲什麼每個實例都需要存儲一個矩形?他們是瓷磚...所有相同的大小 – Ozzy 2012-03-25 16:04:35

+0

太棒了!這是我錯過的一個很好的觀點。工作正常。 – mbreen 2012-03-25 16:08:32

+0

現在我只需要弄清楚爲什麼每次我調用重繪方法時,污垢圖像會改變它們的模式... – mbreen 2012-03-25 16:14:24

1

把所有的一起,並與確定可見JComponentsJViewPort

import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.Random; 
import javax.swing.*; 

public class TilePainter extends JPanel implements Scrollable { 

    private static final long serialVersionUID = 1L; 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       JFrame frame = new JFrame("Tiles"); 
       frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       frame.getContentPane().add(new JScrollPane(new TilePainter())); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 
    private final int TILE_SIZE = 50; 
    private final int TILE_COUNT = 100; 
    private final int visibleTiles = 10; 
    private final boolean[][] loaded; 
    private final boolean[][] loading; 
    private final Random random; 

    public TilePainter() { 
     setPreferredSize(new Dimension(TILE_SIZE * TILE_COUNT, TILE_SIZE * TILE_COUNT)); 
     loaded = new boolean[TILE_COUNT][TILE_COUNT]; 
     loading = new boolean[TILE_COUNT][TILE_COUNT]; 
     random = new Random(); 
    } 

    public boolean getTile(final int x, final int y) { 
     boolean canPaint = loaded[x][y]; 
     if (!canPaint && !loading[x][y]) { 
      loading[x][y] = true; 
      Timer timer = new Timer(random.nextInt(500), 
        new ActionListener() { 

         @Override 
         public void actionPerformed(ActionEvent e) { 
          loaded[x][y] = true; 
          repaint(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE); 
         } 
        }); 
      timer.setRepeats(false); 
      timer.start(); 
     } 
     return canPaint; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Rectangle clip = g.getClipBounds(); 
     int startX = clip.x - (clip.x % TILE_SIZE); 
     int startY = clip.y - (clip.y % TILE_SIZE); 
     for (int x = startX; x < clip.x + clip.width; x += TILE_SIZE) { 
      for (int y = startY; y < clip.y + clip.height; y += TILE_SIZE) { 
       if (getTile(x/TILE_SIZE, y/TILE_SIZE)) { 
        g.setColor(Color.GREEN); 
       } else { 
        g.setColor(Color.RED); 
       } 
       g.fillRect(x, y, TILE_SIZE - 1, TILE_SIZE - 1); 
      } 
     } 
    } 

    @Override 
    public Dimension getPreferredScrollableViewportSize() { 
     return new Dimension(visibleTiles * TILE_SIZE, visibleTiles * TILE_SIZE); 
    } 

    @Override 
    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { 
     return TILE_SIZE * Math.max(1, visibleTiles - 1); 
    } 

    @Override 
    public boolean getScrollableTracksViewportHeight() { 
     return false; 
    } 

    @Override 
    public boolean getScrollableTracksViewportWidth() { 
     return false; 
    } 

    @Override 
    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { 
     return TILE_SIZE; 
    } 
}