Java Swing动画精灵 [英] Animated Sprites with Java Swing
问题描述
有人能告诉我如何减慢精灵外观以创建更流畅的动画?当我运行代码时,它出现在JPanel中的最后一个(第27个)精灵。动画处理速度太快了!
Can someone tell me how can I slowdown the sprites appearance to create a more smooth animation? When I run the code it appears the last (27th) sprite in the JPanel. The animation processing is too fast!
有人告诉我有关Swing Timer的问题,但遗憾的是我曾尝试过几次,而且我无法让代码运行良好:(
Someone told me about Swing Timer, but unfortunately I tried several times with that and I couldn't put the code to run well :(
这是我到目前为止的代码:
Here is the code that I have so far:
package sprites;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Sprites extends JFrame {
public static void main(String[] args) {
JFrame frm1 = new JFrame();
frm1.setSize(400, 400);
frm1.setLocationRelativeTo(null);
frm1.setResizable(false);
frm1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Painel1 pn1 = new Painel1();
frm1.getContentPane().add(pn1);
frm1.setVisible(true);
}
}
class Painel1 extends JPanel {
BufferedImage img;
public Painel1() {
setBackground(Color.yellow);
try
{
img = ImageIO.read(new File("images/dummy.png"));
}
catch (IOException e)
{}
}
@Override
public void paintComponent(Graphics g) {
int[][] spriteSheetCoords = {{8, 10, 119, 129},
{138, 10, 118, 130},
{267, 10, 118, 132},
{402, 11, 113, 132},
{538, 12, 106, 134},
{671, 13, 103, 133},
{804, 12, 102, 132},
{23, 161, 100, 134},
{157, 162, 96, 134},
{287, 159, 95, 135},
{418, 158, 95, 133},
{545, 159, 99, 133},
{673, 159, 102, 134},
{798, 158, 108, 130},
{9, 309, 116, 126},
{137, 309, 118, 127},
{274, 310, 110, 128},
{412, 311, 102, 129},
{541, 312, 103, 130},
{671, 312, 104, 131},
{806, 312, 98, 132},
{29, 463, 94, 135},
{155, 462, 98, 135},
{279, 461, 104, 135},
{409, 461, 106, 135},
{536, 461, 109, 135},
{662, 461, 112, 133}};
Image subSprite;
for (int i = 0; i <= 26; i++) {
super.paintComponent(g);
subSprite = img.getSubimage(spriteSheetCoords[i][0], spriteSheetCoords[i][1], spriteSheetCoords[i][2], spriteSheetCoords[i][3]);
g.drawImage(subSprite, 140, 120, null);
}
}
}
假设要创建一个从第一个精灵循环到最后一个(第27个)精灵。
It is suppose to create a loop from the 1st sprite to the last (the 27th) sprite.
推荐答案
-
首先你在每一行之间都有很多空格,这使得你很难阅读代码。
First of all you have a lot of white spaces between each line, it makes it hard to read the code.
是的,你可以尝试使用Swing 计时器
,这是一个示例和另一个示例和另一个示例。
Yes, you could try using a Swing Timer
, here is an example and another example and another example.
你有一个空的 catch
块,这是不安全的,至少这样做:
You have an empty catch
block which is not secure, at least do this:
catch (IOException e){
e.printStackTrace();
}
你没有把你的程序放在事件调度线程(EDT)解决它只需更改 main
方法如下:
You're not placing your program on the Event Dispatch Thread (EDT) to solve it just change your main
method as follows:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
//Your constructor here
}
});
}
您正在扩展 JFrame
但没有使用它生成的框架,同时你正在创建一个 JFrame
的实例,删除在代码中扩展JFrame
。相关阅读: Java Swing使用扩展JFrame与调用它在课堂内
You're extending JFrame
but not making use of the frame generated by it, and at the same time you're creating an instance of a JFrame
, remove the extends JFrame
in your code. Related reading: Java Swing using extends JFrame vs calling it inside of class
而不是调用 frm1.setSize(400,400);
覆盖 Painel1
的 getPreferredSize()
方法以返回新的维度
400,400
并致电 frm1.pack()
Instead of calling frm1.setSize(400, 400);
override the Painel1
's getPreferredSize()
method to return a new Dimension
of 400, 400
and call frm1.pack()
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
动画处理太快!
The animation processing is too fast!
动画处理速度不是太快,但循环的会阻止要在它结束之前绘制的GUI,这就是为什么你只看到最后一个精灵被绘制的原因。
It's not the animation processing too fast, but the for
loop prevents the GUI to be painted before it ends, that's why you're only seeing the last sprite being painted.
考虑到以上所有要点,您现在可以使用以下代码,其中包括使用Swing Timer以及已包含的上述建议:
With all the above points in mind, you now can have your code as follows, which includes the use of a Swing Timer and the above recommendations already included:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Sprites {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frm1 = new JFrame();
Painel1 pn1 = new Painel1();
frm1.getContentPane().add(pn1);
frm1.pack();
frm1.setVisible(true);
frm1.setLocationRelativeTo(null);
frm1.setResizable(false);
frm1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
}
class Painel1 extends JPanel {
int[][] spriteSheetCoords = { { 8, 10, 119, 129 }, { 138, 10, 118, 130 }, { 267, 10, 118, 132 },
{ 402, 11, 113, 132 }, { 538, 12, 106, 134 }, { 671, 13, 103, 133 }, { 804, 12, 102, 132 },
{ 23, 161, 100, 134 }, { 157, 162, 96, 134 }, { 287, 159, 95, 135 }, { 418, 158, 95, 133 },
{ 545, 159, 99, 133 }, { 673, 159, 102, 134 }, { 798, 158, 108, 130 }, { 9, 309, 116, 126 },
{ 137, 309, 118, 127 }, { 274, 310, 110, 128 }, { 412, 311, 102, 129 }, { 541, 312, 103, 130 },
{ 671, 312, 104, 131 }, { 806, 312, 98, 132 }, { 29, 463, 94, 135 }, { 155, 462, 98, 135 },
{ 279, 461, 104, 135 }, { 409, 461, 106, 135 }, { 536, 461, 109, 135 }, { 662, 461, 112, 133 } };
int i = 0;
BufferedImage img;
private ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
i++;
if (i == spriteSheetCoords.length) {
i = 0;
}
revalidate();
repaint();
}
};
public Painel1() {
Timer timer = new Timer(50, actionListener);
timer.setInitialDelay(0);
timer.start();
setBackground(Color.yellow);
try {
img = ImageIO.read(new File("/home/jesus/Pictures/tokyo.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void paintComponent(Graphics g) {
Image subSprite;
super.paintComponent(g);
subSprite = img.getSubimage(spriteSheetCoords[i][0], spriteSheetCoords[i][1], spriteSheetCoords[i][2], spriteSheetCoords[i][3]);
g.drawImage(subSprite, 140, 120, null);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
正如你所看到的那样,定时器
延迟了50ms,使精灵的过渡变得更顺畅,你可以随意调整。
As you can see the Timer
has a delay of 50ms to make the transition of the sprites smoother, you can adjust it as you please.
这篇关于Java Swing动画精灵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!