我想要做的是创建一个动画,创建一个“跑步”的运动。每当我在屏幕上绘制它时,动画中的最后一帧都会留在后面(因此,当精灵移动时,会留下一系列动画帧)。我已经尝试了if语句和当框架改变时改变图像的绘制位置:
if(a2.sceneNum() == 0)
spectre_Draw1 = (screenWidth() / 2 - 120 / 2 + 120 - 6);
else
spectre_Draw1 = 0;
g.drawImage(pic[2], spectre_Draw1, (screenHeight() / 2 - 180 / 2), null);
if(a2.sceneNum() == 1)
spectre_Draw2 = (screenWidth() / 2 - 120 / 2 + 120 - 6);
else
spectre_Draw2 = 0;
g.drawImage(pic[3], spectre_Draw2, (screenHeight() / 2 - 180 / 2), null);
if(a2.sceneNum() == 2)
spectre_Draw3 = (screenWidth() / 2 - 120 / 2 + 120 - 6);
else
spectre_Draw3 = 0;
g.drawImage(pic[4], spectre_Draw3, (screenHeight() / 2 - 180 / 2), null);有没有一种方法可以在删除拖尾图像的同时做到这一点?
发布于 2014-03-08 21:03:17
注意:示例程序中的以下代码存在一些逻辑错误。有关解释和修复的信息,请参阅
我注意到您正在尝试对动画图像使用不同的图像。您知道,您可以使用单个动画子画面(假设它的格式类似于模式的网格),只需在drawImage方法中更改特定x y位置的位置
public abstract boolean drawImage(Image img,
int dx1,
int dy1,
int dx2,
int dy2,
int sx1,
int sy1,
int sx2,
int sy2,
ImageObserver observer)
img - the specified image to be drawn. This method does nothing if img is null.
dx1 - the x coordinate of the first corner of the destination rectangle.
dy1 - the y coordinate of the first corner of the destination rectangle.
dx2 - the x coordinate of the second corner of the destination rectangle.
dy2 - the y coordinate of the second corner of the destination rectangle.
sx1 - the x coordinate of the first corner of the source rectangle.
sy1 - the y coordinate of the first corner of the source rectangle.
sx2 - the x coordinate of the second corner of the source rectangle.
sy2 - the y coordinate of the second corner of the source rectangle.
observer - object to be notified as more of the image is scaled and converted.请参阅完整描述
也就是说,您可以使用javax.swing.Timer来动画源图像并更改其位置。
对于下面看到的所有示例,这里有一些使用相同代码的示例。我只是更改了图像,并相应地更改了SPRITE_ROWS、SPRITE_COLUMNS和DELAY。欲了解更多信息,请访问
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class NerdGirl extends JPanel {
private static final int SPRITE_ROWS = 5;
private static final int SPRITE_COLUMNS = 2;
private static final int DELAY = 150;
private int DIM_W;
private int DIM_H;
private int x1Src;
private int y1Src;
private int x2Src;
private int y2Src;
private BufferedImage img;
public NerdGirl() {
try {
img = ImageIO.read(getClass().getResource("/resources/nerd-girl.jpg"));
} catch (IOException ex) {
Logger.getLogger(NerdGirl.class.getName()).log(Level.SEVERE, null, ex);
}
DIM_W = img.getWidth() / SPRITE_ROWS;
DIM_H = img.getHeight() / SPRITE_COLUMNS;
x1Src = 0;
y1Src = 0;
x2Src = x1Src + DIM_W;
y2Src = y1Src + DIM_H;
Timer timer = new Timer(DELAY, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (x1Src >= img.getWidth() - DIM_H - 5) { // 5 to take care of precision loss
x1Src = 0;
x2Src = x1Src + DIM_W;
if (y1Src >= DIM_H - 5) { // 5 to take care of precision loss
y1Src = 0;
y2Src = y1Src + DIM_H;
} else {
y1Src += DIM_H;
y2Src = y1Src + DIM_H;
}
} else {
x1Src += DIM_W;
x2Src = x1Src + DIM_W;
}
repaint();
}
});
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, getWidth(), getHeight(), x1Src, y1Src, x2Src, y2Src, this);
}
@Override
public Dimension getPreferredSize() {
return (img == null) ? new Dimension(300, 300) : new Dimension(DIM_W, DIM_H);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.add(new NerdGirl());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}






发布于 2015-01-30 12:12:45
我知道它说“避免回复其他答案”,但作为一个新注册者(但长期用户),我只有资格写“答案”或建议编辑。我不能添加评论到一个答案,直到我被提升!:-)
然而,peeskillet的答案中的源代码中有太多的错误,无法简单地定义为“建议的编辑”:-)
SPRITE_ROWS = 5;SPRITE_COLUMNS = 2;DIM_W = img.getWidth() / SPRITE_ROWS;DIM_H = img.getHeight() / SPRITE_COLUMNS;
在下面的代码中,程序显然试图正确地处理网格中的动画图片的行和列,但这只是因为这两个都是向后的,所以程序才能工作。(例如,在样本nerdgirl的图像网格中有5个列和2个行)。
if (x1Src >= img.getWidth() - DIM_H - 5) { // 5以保证精确性
"DIM_H“应为"DIM_W"
如列表所示,如果单个图像的高度明显大于它们的宽度,或者原始网格的每一行中都有许多图像,则此代码将导致过早跳转到网格中的下一行动画图像(不显示每行中的最后一幅图像)。对于nerdgirl示例(833x639),如果整个网格只高10个像素,则每行中的最后一张图像将不会显示。(DIM_H = 319,img.getWidth()-DIM_H-5 = 503,最后一帧显示x1Src =498时..only成功了!)
如图所示,
这是因为下面的if-test:
if (y1Src >= DIM_H - 5) { // 5 to take care of lack of prec
y1Src = 0;..。应该是:
if (y1Src >= imag.getHeight() - DIM_H - 5) { // 5 to take car
y1Src = 0;..as当前代码只显示2行sprite图像,即使有更多。(这解释了为什么扑动的鸟样本在没有显示最终的全白框架的情况下工作"ok“…仔细观察,它只显示前2行图像)。
if (x1Src >= img.getWidth() - DIM_W - SPRITE_COLUMNS) { // - SPRITE_COLUMNS处理未对齐源图像(参见示例) if (y1Src >= img.getHeight() - DIM_H - SPRITE_ROWS) { // - SPRITE_ROWS处理未对齐源图像(参见示例)
这是因为在计算动画图像的宽度和高度时,可能的“精度损失”不会超过每行和每列中的每帧1个,这是由于整数舍入造成的。例如,833x639的nerdgirl样本计算了166x319的动画帧大小,因此在5个图像之后,我们显示了原始图像的830,638。
然而,我建议下面的内容将使这两个if语句更加清晰和简单:
if (x2Src > img.getWidth()) { // Beyond end of Row
if (y2Src > img.getHeight()) { // Beyond Last Row..。还有一些其他的小调整,如下所示。
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class NerdGirl extends JPanel {
private static int SPRITE_COLUMNS = 5; // Number of columns of sprite images in source file
private static int SPRITE_ROWS = 2; // Number of rows of sprite images in source file
private static final int DELAY = 100; // inter-frame pause in milliseconds
private int dim_W; // Width of an individual animation frame
private int dim_H; // Height of an individual animation frame
private int x1Src; // top-left coordinates of current frame
private int y1Src;
private int x2Src; //bottom-right coordinates of current frame
private int y2Src;
private BufferedImage img;
public NerdGirl() {
try {
img = ImageIO.read(getClass().getResource("images/nerdgirl.jpg"));
SPRITE_ROWS = 2;
// Other sample files
//img = ImageIO.read(getClass().getResource("images/explosion.png"));
//SPRITE_ROWS = 3;
//img = ImageIO.read(getClass().getResource("images/birdflight.png"));
//SPRITE_ROWS = 3;
//img = ImageIO.read(getClass().getResource("images/running_man.png"));
//SPRITE_ROWS = 4;
//SPRITE_COLUMNS = 6;
} catch (IOException ex) {
Logger.getLogger(NerdGirl.class.getName()).log(Level.SEVERE, null, ex);
}
dim_W = img.getWidth() / SPRITE_ROWS;
dim_H = img.getHeight() / SPRITE_COLUMNS;
x1Src = 0;
y1Src = 0;
x2Src = x1Src + dim_W;
y2Src = y1Src + dim_H;
Timer timer = new Timer(DELAY, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Move right to next frame (next column)
x1Src += dim_W;
x2Src += dim_W;
if (x2Src > img.getWidth()) { // Past end of current row.
x1Src = 0; // Back to start of row
x2Src = dim_W;
y1Src += dim_H; // Move down to next Row
y2Src += dim_H;
if (y2Src > img.getHeight()) { // Below bottom of source grid of images
y1Src = 0; // Back to Top.
y2Src = dim_H;
}
}
repaint();
}
});
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, getWidth(), getHeight(), x1Src, y1Src, x2Src, y2Src, this);
}
@Override
public Dimension getPreferredSize() {
return (img == null) ? new Dimension(300, 300) : new Dimension(dim_W, dim_H);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.add(new NerdGirl());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}如果网格都被编译为单个帧大小的整数倍(就像跑步者png image @ 900x600的情况一样-即使提供的示例有图片“重叠”-参见上面的图像链接),那么坐标检查的程序代码可能会更容易:
Timer timer = new Timer(DELAY, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Move right to next frame (next column)
x1Src += dim_W;
if (x1Src == img.getWidth()) { // At end of current row.
x1Src = 0; // Go Back to start of row
y1Src += dim_H; // Move down to next Row
if (y1Src == img.getHeight()) { // Past all images
y1Src = 0; // Back to Top.
}
}
x2Src += dim_W;
y2Src += dim_H;
repaint();
}
});
timer.start();
}但是,由于输入样本网格在整体大小和组成上不可靠,因此建议使用较早的代码,因为它将处理这些不一致。
从长远来看,我希望我的回答能为其他人节省一些宝贵的时间!
干杯,
发布于 2021-06-21 19:13:12
如果有人仍然有这个问题,我找到了答案,你可以使用paintComponent(),或者如果你坚持使用那个函数,你可以在循环或计时器中使用repaint()作为你的内容窗格。如下代码所示:
public void run(){
getContentPane().repaint();
}https://stackoverflow.com/questions/22265452
复制相似问题