Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 行走动画_Java_Loops_Animation_Bufferedimage - Fatal编程技术网

Java 行走动画

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

所以我一直在看Notch的Metagun源代码,我似乎不明白他是如何让精灵动画化的。现在我所要做的就是循环浏览角色行走动画的一些图像。这是代码,到目前为止,我的输出只显示了行走的第一个图像,即静止的角色: 包装动画

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。