Апплет Java заикается при первом рисовании BufferedImage (Java2D)

Я пишу игру как java-апплет, используя библиотеки Java2D вместе с классом BufferedImage. Игра подтормаживает (2-3 секунды) при первом отрисовке изображения. Все файлы BufferImage загружаются до начала игры с помощью этого метода:

bufferedImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);       
    try {
           URL url = new URL(a.getCodeBase(), "images//smoke5frames.png");
           bufferedImage = ImageIO.read(url);           
    } catch (IOException e) { e.printStackTrace(); }        
    mSmoke = bufferedImage;

Чтобы нарисовать изображение, я использую этот метод:

public void draw(Graphics2D g) {    
g.drawImage(mTextures[iCurrentFrame], mAffineTransform, null); }

Рассматриваемые изображения представляют собой SheetedSprites, обычно вырезаемые из листа спрайтов с использованием:

for each frame in animation...

myBufferedImage.getSubimage(i * iFrameWidth, 0, iFrameWidth, iHeight);

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

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

Суть в том, что после того, как SheetedSprite был отрисован один раз, вы можете обновить страницу, и проблема больше не возникнет. Игра работает идеально гладко после того, как все было нарисовано до этого. Это имеет место как в IE, так и в Chrome (я не пробовал в других браузерах). В качестве примечания: проблема никогда не возникает в средстве просмотра апплетов Eclipse.

Я думаю, что изображения каким-то образом кэшируются браузером, хотя на самом деле я в тупике. Я также не пробовал загружать/рисовать изображения с другим набором графических библиотек (Slick2D, LWJGL и т. д.). Спасибо за любые предложения!


person Shnagenburg    schedule 20.03.2012    source источник
comment
Откуда вызывается draw(G2D) и как получается графический объект? На самом деле нет, вычеркните именно этот вопрос, предоставьте ответ как SSCCE.   -  person Andrew Thompson    schedule 21.03.2012
comment
Вот zip для проекта, который демонстрирует метод, используемый для рисования изображений: dan.nemmons.net/ stack/UnprofStackQuestion.zip В подклассе Applet я создаю объект Image с размерами экрана. Я получаю элемент Graphics этого изображения с помощью image.getGraphics(). При каждом вызове отрисовки я очищаю графику и передаю ее в игру, которая приводит объект Graphics к Graphics2D. Отсюда игра вызывает sprite.draw(graphics2d) для всех спрайтов. Наконец, в конце метода рисования апплета я рисую изображение на экране.   -  person Shnagenburg    schedule 04.04.2012
comment
Можете ли вы сделать код достаточно коротким, чтобы это был SSCCE, который вы могли бы опубликовать как редактирование? Это то, что я буду смотреть на.   -  person Andrew Thompson    schedule 04.04.2012


Ответы (1)


У меня была эта проблема около 2 лет назад, и я нашел ее решение на замечательном Java-gaming.org. Проблема для меня заключалась в том, что у Java есть проблема с некоторыми типами png-файлов. Некоторые из них вызывали отставание при первом использовании, а некоторые — нет. Этот "верхний-фиксатор-метод" принимает BufferedImage и возвращает BufferedImage, но в промежутке между ними он делает некоторую магию, которая упрощает декодирование изображения для Java (не спрашивайте меня, как). Наслаждаться!

private BufferedImage toCompatibleImage(BufferedImage image)
{
    if(image==null)System.out.println("Image is null");
    // obtain the current system graphical settings
    GraphicsConfiguration gfx_config = GraphicsEnvironment.
            getLocalGraphicsEnvironment().getDefaultScreenDevice().
            getDefaultConfiguration();

    /*
     * if image is already compatible and optimized for current system 
     * settings, simply return it
     */
    if (image.getColorModel().equals(gfx_config.getColorModel()))
            return image;

    // image is not optimized, so create a new image that is
    BufferedImage new_image = gfx_config.createCompatibleImage(
                    image.getWidth(), image.getHeight(), image.getTransparency());

    // get the graphics context of the new image to draw the old image on
    Graphics2D g2d = (Graphics2D) new_image.getGraphics();

    // actually draw the image and dispose of context no longer needed
    g2d.drawImage(image, 0, 0, null);
    g2d.dispose();

    // return the new optimized image
    return new_image; 
}
person Ultroman the Tacoman    schedule 06.12.2013