簡體   English   中英

讓動畫更流暢

[英]Make animation more smoother

我正在嘗試使用 JPanel 和 painComponent 創建一些動畫(每當按下鍵時就會運行的男孩)。 所以,首先我聲明了一些圖像、圖像數組和一些繪圖方法。 我創建了計時器並將其添加到構造函數中。

Image img1;
Image img2;
Image img3;
Image img4;

int index = 0;

Image currentImage l;
Image[] images = new Image[4]

public class Animation extends JPanel implements ActionListener
{

    public Animation()
    {
     loadImages();
     getTimer();
     imgAdder();
     addFirstImage();
    }

    public void serCurrentImage(Image currentImage)
  {
     this.currentImage = currentImage;
   }
     public void getTimer()
   {
     Timer timer = new Timer(20,this)
      timer.start();
   }
     public void imgAdder()
   {
     images[1] = img1;
        ...
   }
     public void addFirstImage()
   {
      currentImage = img1;
   }
      private void loadImages()
   {
       try
   {
      BufferedImage img = ImageIO.read(getClass.getResource(“/resources/images/img1.png”);
      img1 = img;
      // and so on for every image
    }catch(IOexception ioe )
     ioe.printStackTrace();
    }
  }
     public void paintComponent (Graphics g)
     {
           super.paintComponent(g);
           g.drewImage(currentImage,0,0,this);
           requestsFocus();
      }
            public class FieldKeyListener extends KeyAdapter
    {
            public void move()
      {
            setCurrentImage(image[index]);
             index++;
             if( index == 4 )
                      index = 0;
       }
             public void keyPressed(KeyEvent e)
       {
             super.keyPressed(e);
             int key = e.getKeyCode();
             if(key == Key.Event.VK_LEFT)
             move();
       }
     }
}

然后使用我的數組的循環通過paintComponent繪制所有圖像。 我還聲明了擴展 KeyAdapter 的類。 一切似乎都很好,我的動畫也能正常工作,但問題是它沒有我想要的那么順利。 當我按住鍵時,圖像變化太快,處理看起來不自然。 例如,我想要每秒更改 3 或 4 個圖像而不是 20 個。我可以用錯誤的方法添加計時器嗎? 可能有時間延遲之類的東西。 我不知道它究竟是如何工作的,我應該在計時器中提及哪個偵聽器作為參數。 Ps 我只是初學者,我的代碼在編碼標准方面可能看起來不正確。 此外,我只寫了項目的關鍵部分,這些部分代表了問題。 我希望你能幫我解決這個問題。 提前致謝。

動畫是一門復雜的學科,有很多枯燥的理論。 基本上,動畫是隨時間變化的幻覺。 這非常重要,因為您在動畫中所做的一切都將基於時間。

在像游戲這樣的東西中,你會有一堆實體以不同的時間速率在玩。 挑戰之一是花時間設計一種解決方案,允許實體在與刷新周期(即幀數)分離的情況下在一段時間內播放,除非您的精靈具有正確的幀數以匹配您的刷新循環,但即便如此,我還是會擔心,因為系統不夠靈活,無法適應操作系統和硬件無法跟上的情況。

下面是一個簡單的例子,它需要一個精靈表(存儲在單個圖像中的一系列圖像)、預期圖像/幀的數量以及完成一個完整周期的時間。

它計算單個幀大小並根據精靈動畫的時間量返回一個幀...

public class Sprite {

    private BufferedImage source;
    private int imageCount;
    private int imageWidth;

    // How long it takes to play a full cycle
    private Duration duration;
    // When the last cycle was started
    private Instant startedAt;

    public Sprite(BufferedImage source, int imageCount, int cycleTimeInSeconds) throws IOException {
        this.source = source;
        this.imageCount = imageCount;
        imageWidth = source.getWidth() / imageCount;
        duration = Duration.ofSeconds(cycleTimeInSeconds);
    }

    public BufferedImage getFrame() {
        if (startedAt == null) {
            startedAt = Instant.now();
        }
        Duration timePlayed = Duration.between(startedAt, Instant.now());
        double progress = timePlayed.toMillis() / (double)duration.toMillis();
        if (progress > 1.0) {
            progress = 1.0;
            startedAt = Instant.now();
        }
        int frame = Math.min((int)(imageCount * progress), imageCount - 1);
        return getImageAt(frame);
    }

    protected BufferedImage getImageAt(int index) {
        if (index < 0 || index >= imageCount) {
            return null;
        }
        int xOffset = imageWidth * index;
        return source.getSubimage(xOffset, 0, imageWidth, source.getHeight());
    }

}

注意:它還需要一種重置或停止的方法,所以你可以強制精靈回到開始,但我會留給你

接下來,我們需要一些播放動畫的方法

public class TestPane extends JPanel {

    private Sprite sprite;

    public TestPane(Sprite sprite) {
        this.sprite = sprite;
        Timer timer = new Timer(5, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                repaint();
            }
        });
        timer.start();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(400, 400);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        BufferedImage img = sprite.getFrame();
        int x = (getWidth() - img.getWidth()) / 2;
        int y = (getHeight() - img.getHeight()) / 2;
        g2d.drawImage(img, x, y, this);
        g2d.dispose();
    }

}

這里沒有什么特別的,它是一個簡單的 Swing Timer設置為高分辨率(5 毫秒),它不斷更新 UI,從精靈請求下一幀並繪制它。

這里的重要部分是精靈和刷新周期是獨立的。 希望角色走得更快,更改精靈持續時間,希望角色走得更慢,更改精靈持續時間,刷新周期不需要更改(或任何其他實體)

所以,從...

精靈表

相同的循環,第一次超過 1 秒,第二次超過 5 秒

快走 慢走

您還可以查看諸如How to create a usable KeyReleased method in java 之類的內容,它演示了鍵綁定和集中式Set作為“動作”存儲庫的使用

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM