Java 行走动画
所以我一直在看Notch的Metagun源代码,我似乎不明白他是如何让精灵动画化的。现在我所要做的就是循环浏览角色行走动画的一些图像。这是代码,到目前为止,我的输出只显示了行走的第一个图像,即静止的角色: 包装动画Java 行走动画,java,loops,animation,bufferedimage,Java,Loops,Animation,Bufferedimage,所以我一直在看Notch的Metagun源代码,我似乎不明白他是如何让精灵动画化的。现在我所要做的就是循环浏览角色行走动画的一些图像。这是代码,到目前为止,我的输出只显示了行走的第一个图像,即静止的角色: 包装动画 import java.awt.*; import java.awt.image.BufferedImage; import javax.imageio.ImageIO; import javax.swing.JComponent; public class SpriteAnim
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
public class SpriteAnimation extends JComponent{
/**
*
*/
private static final long serialVersionUID = 1L;
int frame=0;
public void paint(Graphics g){
try{
BufferedImage still = ImageIO.read(SpriteAnimation.class.getResource("still.png"));
BufferedImage walkRight = ImageIO.read(SpriteAnimation.class.getResource("right.png"));
BufferedImage midWalk = ImageIO.read(SpriteAnimation.class.getResource("mid.png"));
BufferedImage walkLeft = ImageIO.read(SpriteAnimation.class.getResource("left.png"));
BufferedImage[] states={still,walkRight,midWalk};
int frame=0;
do{
frame++;
if(frame>=3){
frame=0;
g.drawImage(states[frame],0,0,null);
}
}
while(true);
}catch(Exception e){
}
}
}
问题在于:
if(frame>=3){
frame=0;
g.drawImage(states[frame],0,0,null);
}
需要:
if(frame>=3){
frame=0;
}
g.drawImage(states[frame],0,0,null);
此外,您的状态数组缺少walkLeft:
这也意味着您可能希望上述代码段中的条件为frame>states.length
注意:您确实应该按照@asermax的评论使用计时器,但这至少可以修复您的错误。问题在于:
if(frame>=3){
frame=0;
g.drawImage(states[frame],0,0,null);
}
需要:
if(frame>=3){
frame=0;
}
g.drawImage(states[frame],0,0,null);
此外,您的状态数组缺少walkLeft:
这也意味着您可能希望上述代码段中的条件为frame>states.length
注意:你真的应该按照@asermax的评论建议使用计时器,但这至少可以修复你的bug。我不知道为什么其他人会这样做,只是试图重构你的代码,而没有提到真正的问题:如果你用Swing制作动画,这个循环有一个很大的禁忌。这样做基本上占用了EDT并使整个GUI停滞 您应该重写代码,以便每次调用paint方法时,SpriteAnimation仅绘制一帧,而动画循环由某种计时器外部管理 快速示例:
public class SpriteAnimation extends JComponent{
private int currentFrame = 0;
private BufferedImage[] frames;
public SpriteAnimation(){
/**
* Load your frames
*/
}
public void paintComponent(Graphics g){
currentFrame++;
if(frame >= 3)
frame = 0;
// we pass this as the ImageObserver in case the images are
// loaded asynchronously
g.drawImage(frames[currentFrame], 0, 0, this);
}
}
在你的主要方法中:
// Timer is a swing timer
Timer timer = new Timer(
100,
new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// main frame is your main animation canvas (eg a JFrame)
mainFrame.repaint();
}
});
timer.start();
我不知道为什么其他人继续尝试重构你的代码,甚至没有提到真正的问题:如果你使用Swing来制作动画,那么这个循环是一个很大的禁忌。你基本上是在占用EDT,并通过这样做来拖延整个GUI 您应该重写代码,以便每次调用paint方法时,SpriteAnimation仅绘制一帧,而动画循环由某种计时器外部管理 快速示例:
public class SpriteAnimation extends JComponent{
private int currentFrame = 0;
private BufferedImage[] frames;
public SpriteAnimation(){
/**
* Load your frames
*/
}
public void paintComponent(Graphics g){
currentFrame++;
if(frame >= 3)
frame = 0;
// we pass this as the ImageObserver in case the images are
// loaded asynchronously
g.drawImage(frames[currentFrame], 0, 0, this);
}
}
在你的主要方法中:
// Timer is a swing timer
Timer timer = new Timer(
100,
new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// main frame is your main animation canvas (eg a JFrame)
mainFrame.repaint();
}
});
timer.start();
第一件事:这里不应该有一个循环。每次必须重绘组件时都会调用paint,但您的代码试图充当动画的主循环,而实际上它应该只绘制一帧。动画循环应该由某种计时器控制,该计时器要求窗口每X毫秒重新绘制一次自身,并且您的绘制方法应该绘制动画的当前帧。1更改形式catch Exception e{..的代码以捕获异常e{e.printStackTrace;//非常有用!.2 whiletrue;永远不要在GUI中这样做!1为了更快地获得更好的帮助,发布一个.2以在JComponent中进行自定义绘制,重写paintComponentGraphics而不是paintGraphics。首先,不应该在那里有循环。每次必须重新绘制组件时都会调用paint,但您的代码会尝试ct作为动画的主循环,当它实际上应该只绘制一帧时。动画循环应该由某种计时器控制,该计时器要求窗口每隔X毫秒重新绘制自身,并且您的绘制方法应该绘制动画的当前帧。1更改形式catch Exception e{..的代码以捕获异常e{e.printStackTrace;//非常有用!.2 whiletrue;永远不要在GUI中这样做!1为了更快地获得更好的帮助,发布一个.2,用于在JComponent中自定义绘制,重写paintComponentGraphics而不是paintGraphics。