Переместить изображение на JFrame без перекраски () - PullRequest
1 голос
/ 19 августа 2011

Я пытаюсь построить 2d игру.

У меня есть статическое фоновое изображение и изображение персонажа.Когда я нажимаю клавишу перемещения (WASD), Mainclass (где находится keylistener) вызывает функцию в классе с именем Player. Функция изменяет местоположение персонажа (Изображение).И после того, как эта функция вызвана, я использую repaint (), чтобы перерисовать символ на новой позиции.Если я удаляю фон, я вижу старые изображения, оставшиеся с других позиций.Так что это означает, что мне нужно перекрасить плеер и фон для каждого шага.

Может быть, есть лучшее решение для этого?В худшем случае: это онлайн-игра, в которой движется много игроков, и каждые 100 миллисекунд перерисовка запрашивается для обновления положений каждого игрока.У меня такое ощущение, что это вытянет всю память компьютера игроков или, по крайней мере, игра не будет чувствовать себя так хорошо

Ответы [ 5 ]

4 голосов
/ 19 августа 2011

Не рисуйте непосредственно на панели содержимого JFrame.Вместо этого переопределите paintComponent() в JComponent.Это AnimationTest обращается в JPanel, который по умолчанию имеет двойную буферизацию.В примере также показан один из подходов к исследованию временного бюджета, посвященного живописи.

2 голосов
/ 19 августа 2011

Я думаю, что перекраска - единственное решение, когда-то я создал 2-мерную автомобильную игру-симулятор, и вот что я делаю, я также изменяю координаты всех объектов автомобилей, а затем перекрашиваю все это. Я попытался смоделировать 2000 объектов Car, работающих в 100 мс, перекрасить на всех из них без проблем. хе-хе веселье

2 голосов
/ 19 августа 2011

Насколько я знаю, другого решения нет.Перекрашивание каждые 100 мс обычно не требует большого объема памяти на большинстве компьютеров.

1 голос
/ 19 августа 2011

(я использовал jpanel внутри jframe) и использую bufferedimage из java.awt.image

Вместо этого вы можете попробовать использовать JLabel с иконками. Затем все, что вам нужно сделать, это вызвать метод метки setLocation(...). Swing RepaintManager позаботится о перерисовке старого местоположения и нового местоположения.

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

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class AnimationBackground extends JLabel implements ActionListener
{
    int deltaX = 2;
    int deltaY = 3;
    int directionX = 1;
    int directionY = 1;

    public AnimationBackground(
        int startX, int startY,
        int deltaX, int deltaY,
        int directionX, int directionY,
        int delay)
    {
        this.deltaX = deltaX;
        this.deltaY = deltaY;
        this.directionX = directionX;
        this.directionY = directionY;

        setIcon( new ImageIcon("dukewavered.gif") );
        setSize( getPreferredSize() );
        setLocation(startX, startY);
        new javax.swing.Timer(delay, this).start();
    }

    public void actionPerformed(ActionEvent e)
    {
        Container parent = getParent();

        //  Determine next X position

        int nextX = getLocation().x + (deltaX * directionX);

        if (nextX < 0)
        {
            nextX = 0;
            directionX *= -1;
        }

        if ( nextX + getSize().width > parent.getSize().width)
        {
            nextX = parent.getSize().width - getSize().width;
            directionX *= -1;
        }

        //  Determine next Y position

        int nextY = getLocation().y + (deltaY * directionY);

        if (nextY < 0)
        {
            nextY = 0;
            directionY *= -1;
        }

        if ( nextY + getSize().height > parent.getSize().height)
        {
            nextY = parent.getSize().height - getSize().height;
            directionY *= -1;
        }

        //  Move the label

        setLocation(nextX, nextY);
    }

    public static void main(String[] args)
    {
        JPanel panel = new JPanel(null)
        {
            Image image = new ImageIcon("mong.jpg").getImage();

            protected void paintComponent(Graphics g)
            {
                g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
                super.paintComponent(g);
            }
        };
        panel.setOpaque(false);
//      panel.add( new AnimationBackground(10, 10, 2, 3, 1, 1, 10) );
        panel.add( new AnimationBackground(300, 100, 3, 2, -1, 1, 20) );
        panel.add( new AnimationBackground(200, 200, 2, 3, 1, -1, 20) );
        panel.add( new AnimationBackground(50, 50, 5, 5, -1, -1, 20) );
//      panel.add( new AnimationBackground(0, 000, 5, 0, 1, 1, 20) );
        panel.add( new AnimationBackground(0, 200, 5, 0, 1, 1, 80) );

        JFrame frame = new JFrame();
        frame.setContentPane(panel);
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.setSize(400, 400);
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}

Вам потребуется предоставить фоновое изображение и изображение для метки, где код создает ImageIcon.

0 голосов
/ 19 августа 2011

Эффективно перерисовать только часть вашего компонента.Прочитайте этот учебник .

По сути, вам нужно вызвать component.repaint(posX, posY, length, height) дважды : один раз на старом месте изображения игрока (перекрасит фон), а затем на новомposition.

(Это решение было также предложено G_H в комментариях.)

...