簡體   English   中英

Pacman在Java問題

[英]Pacman in Java questions

對於我的大學任務,我必須制作一個可聯網的pacman版本。 我認為我最好先制作pacman的本地副本,然后擴展此功能以進行網絡播放。

我不得不說,我對java GUI開發相對較新,並在java中使用這些功能。

我已經開始關注java中游戲開發的上述鏈接以及pacman游戲的一個例子。

我決定將迷宮表示為一個int數組,其中不同的值意味着不同的東西。 但是當主游戲循環中的paint方法運行時,我正在用這種方法重繪整個迷宮。

    for (int i : theGame.getMaze())
    {
        if (i == 4)
        {
            g.setColor(mazeWallColour);
            g.fillRect(curX, curY, cellSize, cellSize);
            curX += 25;
        }
        else
        {
            curX += cellSize;
        }

        index++;


        // Move to new row
        if (index == 25)
        {
            index = 0;
            curX = 10;
            curY += cellSize;
        }
    }

然而,這為我提供了不到1fps。 雖然我已經注意到上面鏈接的示例使用類似的方式重繪每次調用paint方法,我相信這是在一個不可見的圖像(有點像雙緩沖[有點像第一個鏈接使用BufferStrategy]解釋])什么是重繪迷宮的更好方法?

任何指針/建議都很有用。

感謝您的時間。

http://pastebin.com/m25052d5a - 主要游戲類。

編輯:我剛剛發現一些非常奇怪的事情發生后,試圖看看執行了多長時間的代碼。

在我添加的paintClear(Graphics g)方法中

ocean = sprites.getSprite("oceano.gif");
g.setPaint(new TexturePaint(ocean, new Rectangle(0,t,ocean.getWidth(),ocean.getHeight())));
g.fillRect(10, 10,getWidth() - 20,getHeight() - 110);

這讓整個事情順利進行 - 然而當我刪除這些線條時,整個事情變慢了? 可能是什么導致了這個?

更新的代碼

首先,我建議您使用命名常量,而不是在代碼中使用隨機幻數,並考慮使用枚舉作為您的單元格類型。 雖然它不會讓你的代碼運行得更快,但它肯定會讓它更容易理解。 此外,'i'通常用作計數器,而不是返回值。 您應該將其cellType或類似的東西。 我還建議您為舞台地圖使用2D數組,因為它在后勤和概念上都使事情變得更容易。

也就是說,這里有幾件事要嘗試:

setColor()拉出循環並執行一次。 編譯器可能能夠執行循環不變的提升,從而為您(也可能會)執行此操作,但從概念上講,您應該這樣做,因為看起來您希望所有牆都是一種顏色。

嘗試調用drawRect()而不是fillRect() ,看看是否繪制得更快。 我不認為它會,但它值得一試,即使它看起來更丑。 同樣,您可以嘗試創建一個Image ,然后繪制它。 這樣做的好處是,很容易告訴Graphics對象在圖像上實現轉換。 另外,請考慮完全解決這個問題,並確保它的性能受到重大影響。

此外,通常您不需要為其Graphics對象請求父對象並直接在其上實現繪制。 相反,你應該覆蓋它的paintComponent()方法,只使用給你的圖形(可能像你一樣調用輔助方法)。 Swing組件默認是雙緩沖的,因此您不需要自己實現; 讓擺動物體完成它的工作,讓你知道什么時候畫畫。

此外,你最終重新粉刷整個屏幕,這是一種矯枉過正的事情。 如果調用repaint(Rectangle) ,Swing可以選擇僅重繪電路板中明確標記為臟的部分。 更新其中一個精靈時,只在精靈的舊位置和新位置區域調用repaint(r)。 當您完成一個級別並需要一個新的板時,您可以調用repaint()(不帶參數)來重繪整個地圖。

您還應該查看Sun的教程,以獲得有關Swing效率的一些提示。

我仍然認為自己是Java的初學者,但我最近使用你提到的一些技術開發了一個Frogger-esque游戲,其中包含動態地圖和編輯器,我很樂意提供一些幫助。

如上所述,enum是要走的路。 我將我的地圖設置為一個二維數組並為每個不同的類型設置一個枚舉,在我的地圖類中編寫一個方法來接收一個圖像並將地圖中的每個方塊划分為我的枚舉中的每個值。

可以在Coke和Code上找到幫助我進行映射的教程。 所有的源代碼都在那里,如果你需要一只手的任何一個,盡管你似乎對你正在做的事情有一個正確的把握。 如果你仍然需要幫助,我總是可以拖出一些源代碼。

您上面列出的代碼不能成為1fps問題的根源......我的代碼遠遠超過了運行速度更快的代碼。

你可以對該代碼進行基准測試並確保它是問題的根源嗎?

看起來你對Thread.sleep的調用並沒有達到預期目的,但我不認為這是你麻煩的根源。 你有:

Thread.sleep(Math.max(0, startTime - System.currentTimeMillis()));

startTime將始終小於System.currentTimeMillis(),因此startTime - System.currentTimeMillis()將始終為負,因此您的睡眠將始終為0毫秒。 它與您顯示的示例不同,因為該示例在執行計算之前將startTime增加40毫秒。 它正在計算將繪圖時間填充到40毫秒的睡眠時間。

無論如何,回到你的問題。 我建議您測量一下,以確定您的時間花在哪里。 在知道什么是緩慢之前,沒有必要進行優化。 您已經知道如何使用System.currentTimeMillis()。 嘗試使用它來衡量所有時間的位置。 這一切都花在了牆上嗎?


編輯 - 我看到這被標記為已被接受,所以我應該推斷當你修復睡眠時間后問題就消失了嗎? 我沒有很多Java GUI經驗,但我可以推測,也許你的代碼正在挨餓其他重要的線程。 通過將線程設置為具有最大優先級並且只調用sleep(0),您幾乎可以保證進程中沒有其他線程可以執行任何操作。 這是Raymond Chen博客的一篇文章 ,解釋了原因。

我不是游戲開發者,但這種幀速率似乎很慢。

我不太確定您的代碼是如何工作的,但是提高渲染性能的一種可能性是找到顯示器中那些變化不大的部分(例如迷宮的牆壁)並避免重新創建它們每一幀。

創建一個包含常量元素(迷宮?,背景)的BufferedImage,然后為每個幀重新繪制它。 在這個Buffered圖像的頂部,繪制可變元素(PacMan,鬼,點等)。

Romain Guy的優秀書籍Filthy Rich Clients討論了這種技術以及許多其他Java2D性能提示。

只是讓你不用擔心它是Java,我在頻譜分析儀(如o-scope)上工作,整個GUI部分(跟蹤,菜單,按鈕和滾輪處理)都是用Java完成的。 當我到達那里它得到1fps,當我離開它是12-20。 這有很多處理正在進行,並且運行在非常慢的處理器上。

查看僅更新需要更新的GUI部分。 通常,您可以重繪整個屏幕,但只需將剪切區域設置為真正更新的部分。

關注內循環 - 他們是速度殺手。

盡量避免分配和釋放大量對象。 我不是說不要使用對象,我說不要為每個像素創建一個:)

祝好運

哇,給別人學習Java是一個非常棘手的問題。

我的建議? 從對象的角度思考。 你能寫一些沒有模仿游戲本身行為的用戶界面的東西嗎? 一旦你開始工作,你就可以專注於用戶界面的特殊問題。 是的,從網絡部分之前的本地版本開始。

我不是游戲玩家。 我想知道Java2D API會讓你的生活更美好嗎?

你需要多長時間才能完成它?

這可能聽起來很明顯但是你的性能問題是因為你正在重新繪制整個迷宮,這不需要完成,而是你只需要重繪迷宮的改變部分。

我以前解決這個問題的方法是將迷宮的更新從實際的重繪分離到不同的線程(有點像線程MVC)。 每次更改迷宮中的單元格時都會將其標記為“臟”,重繪線程會立即檢查,然后僅重繪臟單元格。

很抱歉極端通用的建議

默認情況下,Java / Swing是雙緩沖區。 如果你正在使用Swing,你不需要像其他答案所說的那樣單獨進行雙緩沖。

我同意Allain的觀點,即您列出的代碼不能成為1fps的原因。 我編寫了效率極低的Java / Swing動畫代碼,運行速度比你描述的快得多。 做一些更多的測試來縮小緩慢的原因。

如果可能,您應該保留迷宮的圖像,並在一個庫調用中繪制它。 它可能也不需要是全分辨率 - 如果你想要一個塊狀,8位的感覺,我希望圖形庫非常樂意讓8 ^)

此外,正如其他人所提到的,您可以通過僅重繪需要更新的屏幕部分來節省時間。 這可能很煩人,但它可以讓您顯着提高幀速率。 一定要做一些實驗,以確保在施加所需的努力之前就是這種情況!

暫無
暫無

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

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