Java Swing Огромная Сетка - PullRequest
       2

Java Swing Огромная Сетка

0 голосов
/ 25 марта 2012

Я делаю новую игру, которая генерирует огромную сетку (скажем, 1000x1000).Игрок начинает с середины и перемещается в поисках «очков».Игрок может видеть только часть большей сетки в окне (15x15).Прямо сейчас у меня просто огромное количество прямоугольников, каждый из которых рисует буферизованное изображение блока грязи, который я создал.Вопрос: есть ли лучший тип переменной, который я должен использовать для хранения всех этих изображений?

Вот так выглядит мой класс Dirt (содержит прямоугольник и изображение, сгенерированное в начале):

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 ]

3 голосов
/ 25 марта 2012

Если у вас есть 1 000 000 грязных и только 20 изображений, хранить отходы в каждой грязи - пустая трата времени. Вы можете использовать индекс вместо этого. Так рисовать, а не рисовать

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

вы бы нарисовали

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

Для обновленного вопроса:

Вы, кажется, рисуете всю свою сетку (0-1000,0-1000). То, что вы действительно хотите, это просто нарисовать область 15x15 'viweable'. Так что вместо

    //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, чтобы убедиться, что он все еще начинает рисовать в левом верхнем углу вашего окна.

1 голос
/ 25 марта 2012

сложите все вместе и определите видимое JComponents в JViewPort

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;
    }
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...