簡體   English   中英

如何減少我的Java 2D Platformer的滯后?

[英]How to reduce lag in my java 2d platformer?

我正在使用Swing Java開發2D平台游戲,我想知道如何減少從它獲得的延遲。 我的意思是,它並不會太落后,但值得注意的是它有時會變慢。 我有一個在12毫秒處滴答作響的Swing計時器,一個循環功能和一個繪畫功能。

public void cycle() {
    if (guy.getJumpState() == false) {
        if (canExecuteMovement(0, 4)) {
            onGround = false;
            if (guy.getY() > 300) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setY(platform[i].getY() - 4);
                }
            } else {
                // or just move the guy if not.
                guy.moveY(4);
            }
        } else {
            onGround = true;
        }
    } else {
        if (canExecuteMovement(0, -8)) {
            if (guy.getY() < 300) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setY(platform[i].getY() + 8);
                }
            } else {
                // or just move the guy if not.
                guy.moveY(-8);
            }
            jumpCount++;
            if (jumpCount >= 15) {
                jumpCount = 0;
                guy.setJumpState(false);
            }
        } else {
            jumpCount = 0;
            guy.setJumpState(false);
        }
    }

    if (guy.getDirection() == "left") {
        if (canExecuteMovement(-3, 0)) {
            if (guy.getX() < 450) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setX(platform[i].getX() + 3);
                }
            } else {
                // or just move the guy if not.
                guy.moveX(-3);
            }
        }
    } else if (guy.getDirection() == "right") {
        if (canExecuteMovement(3, 0)) {
            if (guy.getX() > 450) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setX(platform[i].getX() - 3);
                }
            } else {
                // or just move the guy if not.
                guy.moveX(3);
            }
        }
    }
}


public void paint(Graphics g) {
    super.paint(g); // something important
    Graphics2D g2d = (Graphics2D) g;

    // draw platforms
    for (int i = 0; i < platformCount; i++) {
        if (platform[i].getX() > -50 && platform[i].getX() < 950 && platform[i].getY() > -50 && platform[i].getY() < 650) {
            g2d.drawImage(platform[i].getImage(), platform[i].getX(), platform[i].getY(), this);
        }
    }

    // draw guy
    g2d.drawImage(guy.getImage(), guy.getX(), guy.getY(), this);

    // destroy unneeded processes
    Toolkit.getDefaultToolkit().sync();
    g.dispose();
}

我該怎么做才能優化這一點並減少延遲? 當我為循環功能本身創建線程時,平台有時會瞬間分開。 我假設是因為線程是異步的,所以它的一半是在paint函數打開時完成的。

一些松散的想法(自從我在Swing中制作動畫以來已經有好幾年了),並且您沒有發布一些可編譯的代碼。

  • 您是否嘗試過paintComponent()--- paint還有很多其他功能。 然后也許您需要將repaint()添加到tick函數。 每次我重新裝油漆時,它都會變得一團糟。
  • 也可以嘗試增加刻度時間---您浪費的時間更少。
  • 我還假設您正在按計時器進行滴答作響。
  • 我不知道為什么要放置圖形對象
  • 也可以嘗試僅刪除同步(沒有它,我就已經完成了可以在許多類中工作的動畫) Toolkit.getDefaultToolkit().sync()

如果這樣做沒有幫助,請使用探查器查找瓶頸。 Visual VM非常不錯。 另外,Visual VM在一段時間內還是jdk的一部分-只需進入bin文件夾並啟動jvisualvm。

編輯:(線程問題)

  • 有人建議使用線程---我不同意。 如果要在EDT之外進行一些工作,請使用SwingWorker
  • 我假設您不是在調用paint()而是在調用repeaint() 如果您確實調用了paint() (無論您使用什么黑魔法都可以使它起作用),請僅調用repaint()即可在適當的時間安排修復。

我會在方法之外創建變量,以免每次調用該方法時都不會創建該變量。 編寫游戲程序的最佳方法是重用事物而不是破壞和創造,因為破壞和創造會消耗大量的計算能力。

Graphics2D g2d = (Graphics2D) g; <---declare it outside your method.

並嘗試查找多余的條件。 我在您說的地方看到了一個(如果向右的方向是...,否則向左的方向...); 只是說(如果方向正確,則...否則...)。 有條件的花費不多,但是當您每秒調用該有條件的1000次時,我認為它加起來了。 (雖然idk,但我這樣做是為了以防萬一,並使事情變得流暢)

在說setjumpstate(false)的地方,這是多余的,因為無論執行什么操作,都將其執行-只需將其移至條件setjumpstate(false)之外即可。

首先,這是一個問題:

// destroy unneeded processes
Toolkit.getDefaultToolkit().sync();
g.dispose();

通常,處置未創建的資源可能是個壞主意。 在這種特定情況下,傳遞給paint()Graphics可能會被層次結構中的所有其他組件使用,因此這可能會導致非常奇怪的結果。

我認為在這里調用Toolkit.sync()是您嘗試消除在后台移動事物時看到的撕裂感的嘗試。 但是,它所做的只是刷新所有未決的繪制指令。 這在這里沒有效果,因為您可能正在繪制一個將在以后完全繪制的后緩沖Swing組件。

消除撕裂的正確方法是在事件線程上執行任何更新,以便在繪制時不會更改屏幕數據。 一種簡單的實現方法是讓您的計時器只調用repaint() ,並在執行任何操作之前讓paint()方法調用cycle()。

為了處理延遲,一種解決方案可能是允許使用可變幀速率。 不必將所有內容每幀移動固定距離,而是計算自上一幀以來的時間並相應地移動所有內容。

暫無
暫無

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

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