Я делаю небольшую игру. Это не экшн, а головоломка, поэтому производительность не так важна. Теперь у меня есть основная игровая область, фоновое изображение. В определенных случаях я хочу нарисовать другие изображения поверх частей фонового изображения. Моя проблема в том, что как фоновое изображение, так и наложенные изображения могут быть анимированными гифками с неизвестным количеством кадров (в основном, выбранными пользователем).
Теперь то, что я хочу сделать, это в основном: нарисовать фоновое изображение и анимировать его (если это гифка), затем нарисовать 0-n анимированных гифок меньшего размера поверх него, положение относительно фонового изображения, заданное в пиксельных координатах. Кроме того, его размер должен изменяться, чтобы изображения увеличивались / перемещались соответственно.
Как может выглядеть конечный результат: http://i.stack.imgur.com/PxdDt.png (только представьте, что это анимировано)
Я нашел решение, которое работает, устанавливая диспетчер компоновки на null и используя абсолютно позиционированные JLabels с иконками, чтобы анимировать их, используя один в качестве фона, а другой добавленный к нему в качестве переднего плана:
background.setSize(backgroundIcon.getIconWidth(), backgroundIcon.getIconHeight());
foreground.setSize(foregroundIcon.getIconWidth(), foregroundIcon.getIconHeight());
background.setLocation(0, 0);
foreground.setLocation(30, 30);
background.setLayout(null);
background.add(foreground);
frame.setLayout(null);
frame.add(background);
(полный код ниже)
Как я слышал, установка диспетчера компоновки на null является проблематичной (особенно, поскольку я хотел бы добавить текст к изображению позже, хотя я бы использовал другую метку внутри фоновой метки, а не саму метку фона или что-то еще ), и изменение размера, похоже, невозможно таким образом, поскольку я не могу изменить размер значка изображения JLabels (нашел несколько решений, которые разбили gif на одно bufferedImage для каждого слоя и изменили их размер, прежде чем снова собрать их вместе, из-за чего он теряет определенные задержки между кадрами и так далее). Кроме того, поскольку позиция должна быть идеальной до пикселя, изменение размера, даже если это возможно, может быть проблематичным из-за ошибок округления.
Итак, есть ли лучший способ сделать это? Могу ли я как-то загрузить анимированные гифки и объединить их вручную (даже если у них может быть разное количество слоев), чтобы мне пришлось рисовать только одно изображение? Есть ли менеджер компоновки, в котором я могу установить позиции компонентов вручную, но который автоматически масштабирует их, если вы изменяете размер окна / панели? Может быть, есть сторонний графический проект, который мог бы делать то, что я хочу, с места в карьер?
В идеале было бы что-то вроде того, что я сделал бы, если бы они не были анимацией, например, создание объединенного изображения, а затем изменение размера и отображение этого.
Полный код:
import java.awt.Dimension;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public final class Tester extends JFrame {
public static void main(String[] args) throws MalformedURLException {
new Tester();
}
private Tester() throws MalformedURLException {
setTitle("Tester");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Icon backgroundIcon = new ImageIcon(new URL("http://s5.favim.com/orig/51/animated-gif-gif-hands-sign-language-Favim.com-542945.gif"));
Icon foregroundIcon = new ImageIcon(new URL("http://i.imgur.com/89HANHg.gif"));
JLabel background = new JLabel(backgroundIcon);
JLabel foreground = new JLabel(foregroundIcon);
// ugly
background.setSize(backgroundIcon.getIconWidth(), backgroundIcon.getIconHeight());
foreground.setSize(foregroundIcon.getIconWidth(), foregroundIcon.getIconHeight());
background.setLocation(0, 0);
foreground.setLocation(30, 30);
background.setLayout(null);
background.add(foreground);
setLayout(null);
add(background);
// set size of frame to size of content
setResizable(false);
getContentPane().setPreferredSize(new Dimension(backgroundIcon.getIconWidth(), backgroundIcon.getIconHeight()));
pack();
setLocationRelativeTo(null);
setVisible(true);
}
}
URL
, как показано здесь или ниже; используйте синтетические изображения, как показано здесь; или используйтеUIManager
значки, как показано здесь. - person trashgod   schedule 26.08.2013