簡體   English   中英

用Java更新和渲染2D游戲

[英]Updating and rendering for a 2D game in Java

因此,我正在用Java制作2D游戲,而實際上我對Java並沒有太多的經驗。 我目前使用一個非常簡單的循環,該循環使用一個擺動定時器,每10毫秒左右運行一次,看起來像這樣:

public void actionPerformed(ActionEvent e) {
update();
repaint();
}

但是,出於顯而易見的原因,我需要一些更實用的東西。 這些原因包括更多的滯后意味着更少的FPS和更慢的移動/其他更新。 我在這里的3D Java游戲教程中找到了以下代碼。 它會在程序啟動時開始運行,據我所知,它可以工作。 但是,我並沒有完全理解它:(tick()是更新程序,render()渲染屏幕)

    long currenttime;
    long previoustime = System.nanoTime();
    long passedtime;
    int frames = 0;
    double unprocessedseconds = 0;
    double secondspertick = 1 / 60.0;
    int tickcount = 0;
    boolean ticked = false;     

    while (gameIsRunning) {
        currenttime = System.nanoTime();
        passedtime = currenttime - previoustime;
        previoustime = currenttime;
        unprocessedseconds += passedtime / 1000000000.0;

        while (unprocessedseconds > secondspertick) {
            tick();
            unprocessedseconds -= secondspertick;
            ticked = true;
            tickcount++;
            System.out.println(tickcount);
            if (tickcount % 60 == 0) {
                System.out.println(frames + " FPS");
                previoustime += 1000;
                frames = 0;
            }
        }
        if (ticked) {
            render();
            frames++;
        }
        render();           
        frames++;
    }

在我找到的教程中沒有解釋該代碼。有人可以將其分解並解釋嗎? 我也在這里尋找想法,該頁面上帶有渲染線程和更新線程的最后一段代碼對我來說很有意義。 我應該使用哪種方法? 以上之一,還是完全不同? 另外,您可能會說這是我在stackoverflow上遇到的第一個問題。 預先感謝,喬希

tick()可能正在更新游戲對象的物理屬性(位置,速度等)。每次更新都會多次調用tick(),因為某些模擬無法處理太大的時間步而不會變得不穩定。

在線上有一篇熱門文章,解釋了為什么會這樣,以及為什么使用固定的時間步是正確的過程。 看看這個。

游戲的每次更新都會以1/60秒(即每秒60幀)的增量進行。 重復此過程,直到聚合中剩余的時間不到1/60秒。 匯總只是一個花哨的總和。

然后,將游戲當前狀態的快照呈現到屏幕上。

我不會對它進行太深的了解,但是實際上,這段代碼應該在render()期間通過聚合中的剩余時間來內插每個對象的位置。

long currenttime;
long previoustime = System.nanoTime();
long passedtime;
int frames = 0;
//this is an aggregate, games usually step in fixed units of time.
//this is usually because physics simulations can't handle too large of time steps.
double unprocessedseconds = 0;
double secondspertick = 1 / 60.0;
int tickcount = 0;
boolean ticked = false;     

while (gameIsRunning) {
    //get elapsed nano seconds from the epoch (january 1st, 1970)
    currenttime = System.nanoTime();
    //take difference of current time in nanos and previous time in nanos
    passedtime = currenttime - previoustime;
    previoustime = currenttime;
    //divide to get the elapsed time in seconds.
    unprocessedseconds += passedtime / 1000000000.0;

    while (unprocessedseconds > secondspertick) {
        tick();
        unprocessedseconds -= secondspertick;
        ticked = true;
        tickcount++;
        System.out.println(tickcount);
        if (tickcount % 60 == 0) {
            System.out.println(frames + " FPS");
            previoustime += 1000;
            frames = 0;
        }
    }
    if (ticked) {
        render();
        frames++;
    }
    render();           
    frames++;
}

喬希,祝你好運。

編輯:

我沒有使用一個線程進行更新並使用一個線程進行渲染的游戲經驗。 因此,我無法提供建議。 如果您幾乎沒有多線程經驗,那么我會避免使用它,因為只有復雜的游戲才可能需要這種方法,而多線程會增加許多您可能不想處理的問題。

多線程游戲引擎將在渲染和更新之間消耗比單線程游戲更多的內存,或者最終將彼此依賴。 這是因為兩個線程無法同時操作相同的數據。 因此,兩個線程操作的唯一方法是對那些數據結構進行同步,或者通過更新線程向渲染線程提供不可變數據來進行渲染。

編寫多線程游戲引擎將是線程化的良好入門。 它可以教你很多東西。 取決於您要從中獲得什么。

如果您要制作2D游戲,我會更加有信心,您將不需要一個線程來進行更新,也不需要一個線程來進行渲染。

如果您真的想追求這一點, 這就是我要采取的方法。

您只需要一個while循環即可控制渲染。

我做引擎的方式就像前面解釋的那樣,我是多線程的。 基本上,如果將處理和繪制游戲的工作分為兩個部分,則它會變得更快,但會消耗更多的資源。 我做了一些類似的事情:

public class Engine implements Runnable {

    //Sets classes
    Engine tick = new Engine(true);
    Engine render = new Engine(false);
    Thread tickThread = new Thread(tick);
    Thread renderThread = new Thread(render);

    boolean job;
    boolean isRunning = false;

    long sleepTime = 5L;

    public Engine(boolean job) {
         //Sets what the thread does
         this.job = job;
    }

    public static void startEngine() {
         //Starts Engine
         isRunning = true;
         tickThread.start();
         renderThread.start();
    }

    public void tick() {
         //Process things
    }

    public void render() {
         //Draw things
    }

    public void run() {
         //Do engine base things
         while(isRunning) {
              if(job) {
                   tick();
              } else {
                   render();
              }
              Thread.sleep(sleepTime);
         }
    }

}

這絕不是先進的。 這只是一個簡單的多線程游戲引擎的示例。 老實說,當我開始制作游戲時,我使用了確切的代碼。 可以使用它,但應根據您的用途進行一些調整。 我的意思是說您有一個正在移動的對象,並且該對象同時被渲染。 如果對象的位置是50,並且在增加,並且render方法正在繪制它,則該對象可以先移至51,然后移至52,然后再次進行渲染。 通常,處理速度比圖形更快。 另一個示例:假設您有一個ArrayList,並且不斷地對其進行刪除和添加對象。 有時,您可以刪除一個對象,就像render方法將要繪制它一樣,並導致空指針異常,因為它試圖繪制不存在的對象。 (我使用了“ if(object.get(i)!= null)”並以這種方式解決)我希望這至少可以有所幫助(兩年后,大聲笑),並幫助您了解多線程的基礎就像(如果您還沒有)。

暫無
暫無

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

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