Игровая доска Java Swing

Я работаю над большой игрой «Монополия» в качестве проекта в школе и столкнулся с довольно большой проблемой производительности. Прямо сейчас у меня есть метод рисования, который рисует всю доску каждый раз, когда он вызывается... это большая проблема, потому что доску нужно рисовать только один раз в начале и только тогда, когда кто-то покупает дом или что-то в этом роде. Единственными компонентами, которые я хочу часто рисовать, являются игроки, потому что именно они больше всего двигаются и нуждаются в покраске.

Вот метод покраски моей доски:

public void paint(Graphics g){
        super.paint(g);
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        //Draw all the spots
        for(int i = 0; i < spots.length; i++){
            g2d.setColor(Color.white);
            g2d.fill(spots[i].getRect());
            if(spots[i] instanceof Property){
                if(i < 10){
                    g2d.setColor(spots[i].getColor());
                    Rectangle temp = new Rectangle(spots[i].getRect().x,spots[i].getRect().y,spots[i].getRect().width,spots[i].getRect().height/3);
                    g2d.fill(temp);
                    g2d.setColor(Color.black);
                    g2d.drawString(((Property)spots[i]).getName(), spots[i].getRect().x, spots[i].getRect().height);
                }else if(i >= 10 && i < 20){
                    g2d.setColor(spots[i].getColor());
                    Rectangle temp = new Rectangle(spots[i].getRect().x+spots[i].getRect().width-spots[i].getRect().width/3,spots[i].getRect().y,spots[i].getRect().width/3,spots[i].getRect().height);
                    g2d.fill(temp);
                }else if(i >= 20 && i < 30){
                    g2d.setColor(spots[i].getColor());
                    Rectangle temp = new Rectangle(spots[i].getRect().x,spots[i].getRect().y+spots[i].getRect().height-spots[i].getRect().height/3,spots[i].getRect().width,spots[i].getRect().height/3);
                    g2d.fill(temp);
                    g2d.setColor(Color.black);
                    g2d.drawString(((Property)spots[i]).getName(), spots[i].getRect().x, spots[i].getRect().y);
                }else if(i >= 30 && i < 40){
                    g2d.setColor(spots[i].getColor());
                    Rectangle temp = new Rectangle(spots[i].getRect().x,spots[i].getRect().y,spots[i].getRect().width/3,spots[i].getRect().height);
                    g2d.fill(temp);
                }
            }else if(spots[i] instanceof Railroad){
                if(i == 5)
                    g2d.drawImage(imgTrain3, spots[i].getRect().x, spots[i].getRect().y+spots[i].getRect().height/4, null);
                else if(i == 15)
                    g2d.drawImage(imgTrain4, spots[i].getRect().x+spots[i].getRect().width/4, spots[i].getRect().y, null);
                else if(i == 25)
                    g2d.drawImage(imgTrain1, spots[i].getRect().x, spots[i].getRect().y+spots[i].getRect().height/4, null);
                else if(i == 35)
                    g2d.drawImage(imgTrain2, spots[i].getRect().x+spots[i].getRect().width/4, spots[i].getRect().y, null);
            }else if(spots[i] instanceof Chance){
                if(i == 7)
                    g2d.drawImage(imgChance2, spots[i].getRect().x, spots[i].getRect().y, null);
                else if(i == 22)
                    g2d.drawImage(imgChance2, spots[i].getRect().x, spots[i].getRect().y+spots[i].getRect().height/3, null);
                else if(i == 36)
                    g2d.drawImage(imgChance3, spots[i].getRect().x, spots[i].getRect().y, null);
            }else if(spots[i] instanceof Community){
                if(i == 2)
                    g2d.drawImage(imgComm1, spots[i].getRect().x, spots[i].getRect().y+spots[i].getRect().height/3, null);
                else if(i == 17)
                    g2d.drawImage(imgComm2, spots[i].getRect().x, spots[i].getRect().y, null);
                else if(i == 33)
                    g2d.drawImage(imgComm3, spots[i].getRect().x+spots[i].getRect().width/3, spots[i].getRect().y, null);
            }else{
                g2d.setColor(spots[i].getColor());
                g2d.fill(spots[i].getRect());
            }
        }
        //Draw the outline of every spot
        g2d.setColor(Color.black);
        for(Spot index : spots)
            g2d.draw(index.getRect());
        //Draw the outline of the whole board
        g2d.drawRect(newX, newY, boardSize, boardSize);
        //Draw the Players location
        for(Player index : players)
             g2d.drawImage(index.getImage(), index.getLoc().x, index.getLoc().y, null);
    }

По сути, тонна текста для представления доски, и это делается каждый раз, когда доска перекрашивается. Любой совет?

Бонусный вопрос: я также только начал работать над анимацией движения для игроков после того, как они катятся (в настоящее время просто прыгают к месту назначения). Я создал таймер, который занимает 1 секунду на каждый бросок (например, если вы выбросили 5, перемещение занимает 5 секунд). Единственная проблема в том, что у меня нет хорошей идеи, как показать медленное перемещение фигуры игрока от начального местоположения до конечного. Просто нужно, чтобы кто-то дал мне основную идею, чтобы я мог двигаться в правильном направлении.


person mbreen    schedule 04.03.2012    source источник
comment
+1, Круто. Я просто искал идею, с чего начать... Монополия отлично подходит для моего нового проекта.   -  person ApprenticeHacker    schedule 04.03.2012
comment
Спасибо! Это определенно забавная игра для разработки и наблюдения за тем, как все это складывается воедино.   -  person mbreen    schedule 04.03.2012


Ответы (2)


Покрасьте доску в BufferedImage. В методе рисования нарисуйте изображение доски, затем нарисуйте фигуры поверх.

Кстати, при использовании Swing не рисуйте в контейнерах верхнего уровня, вместо этого используйте JComponent или JPanel. Для последних двух переопределите paintComponent(Graphics), а не paint(Graphics).

person Andrew Thompson    schedule 04.03.2012
comment
Таким образом, он по-прежнему рисует доску при каждом вызове перерисовки, но поскольку это изображение, оно более эффективно? В настоящее время я вижу видимое отставание, когда игрок движется, будет ли это менее заметно с BufferedImage? - person mbreen; 04.03.2012
comment
@mbreen: Попробуйте :-). Да, это будет быстрее, и вам все равно придется время от времени рисовать всю доску, если ваше окно Java закрыто другими окнами. - person Paŭlo Ebermann; 04.03.2012
comment
Если действительно нужно много времени, чтобы нарисовать БГ, то да. Но должна быть возможность рисовать сотни объектов за вызов метода рисования без заметной задержки. Возможно, было бы лучше рассмотреть публикацию SSCCE, чтобы мы могли более подробно изучить используемый процесс в целом. Кроме того, настоятельно рекомендуем поискать любые примеры рендеринга из учебника, который нашел toto2. Попробуйте увеличить их от рисования 1 ..шара (линии, ..что угодно) до рисования десятков из них - и посмотрите, как они работают. - person Andrew Thompson; 04.03.2012
comment
Хорошо, я искал хорошее объяснение класса BufferedImage, но я не могу найти ничего, что я понимаю/могу реализовать. Поправьте меня, если я ошибаюсь: я создаю переменную BufferedImage board = new BufferedImage(); затем я создаю метод, который делает все то же самое, что и мой метод рисования, за исключением того, что на этот раз он рисует изображение... тогда мой метод рисования рисует это изображение? - person mbreen; 04.03.2012
comment
Да, тогда paint something to the new image! - person Andrew Thompson; 04.03.2012
comment
У меня все еще много проблем с этим ... если бы я дал вам ссылку на весь мой класс по доске, не могли бы вы быстро взглянуть на него, чтобы увидеть, что я делаю неправильно? Я был бы очень признателен за это. - person mbreen; 04.03.2012
comment
Извини, нет. Ранее я собирался упомянуть следующее: чтобы быстрее получить помощь, опубликуйте SSCCE. Только потому, что дать несколько общих советов казалось простым, я воздержался. Но теперь определенно пришло время для SSCCE. SSCCE будет достаточно коротким, чтобы опубликовать его в вопросе (новый — подсказка, подсказка). - person Andrew Thompson; 04.03.2012
comment
Хорошо, это нормально. Спасибо вам за вашу помощь! - person mbreen; 04.03.2012

Вы можете избежать перерисовки всей поверхности с помощью: jComponent.repaint(someRectangle). См. также этот пример.

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

Анимации в Swing см. в этом руководстве. Вы заметите, что оба примера, на которые я ссылаюсь в этом посте, взяты из официального учебника по Swing< /а>.

person toto2    schedule 04.03.2012