我目前正在使用Java製作基於2D回合的策略遊戲。在這個階段,我正在測試不同種類的AI。如何在JPanel中快速更新圖形
AI通過向一個名爲gameLoop的函數發送一個x和y變量來與遊戲進行交互,該函數通常會由一個mouseClicked函數調用。這使得他們可以直接模擬讓他們與遊戲互動更容易的人類用戶。下面是一些我的代碼的概述:
paintComponent() {
drawTiles();
drawUnits();
if(unitSelected && gameState == DISP_MOVE)
drawMoveSpots();
}
gameLoop(int x, int y) {
// various logic based
// on the values of x and y
// logic may set unitSelected to true or false
// may also change gameState bteween normal and displayMoveSpots
repaint();
}
我的問題,現在從這樣一個事實的AI被執行的代碼比重繪發生得更快。當發生這種情況時,我開始在我的各種繪圖函數中出現錯誤,如NullPointerException和ConcurrentModificationException,因爲gameLoop內部的邏輯比重新繪製可能發生的變化更快。如果我手動延遲人工智能調用gameLoop的頻率或者只有兩個人在玩,錯誤消失。
從我對Java文檔的研究和閱讀中,我知道repaint立即返回並將所有圖形調用放到EventQueue上,直到Java決定有足夠的調用來保證實際重新繪製。目前唯一能找到的解決方案是將gameLoop中發生的邏輯代碼放入匿名可運行類中,並使用SwingUtilities.invokeAndWait調用代碼,但這對我來說不是一個有效的解決方案,因爲這會導致實際的人爲交互從點擊到錯誤。我曾考慮過使用鎖來爲gameLoop的邏輯部分/ repaint提供互斥(所以一次只能執行一個),但我不確定在處理Java圖形時這是否是一種好的做法。
在這一點上,我接受任何建議,我可以做什麼來緩解我的問題。
謝謝。
這聽起來像是一個Canvas和bufferstrategy的工作。這樣你的邏輯和繪圖代碼就可以在同一個線程上運行。 – Nikki
我不完全清楚,但你可以嘗試將信息保存在一個'Graphics'變量中。讓我們的代碼不斷地改變它,同時自動調用'repaint()'並定期更新圖形。 – Astrobleme
@ambigram_maker *「..嘗試將信息保存在Graphics變量中。」*或者,如果它是Java虛擬機傳遞的'Grphics'對象,**不這樣做。**'Graphics'實例從一個重繪到下一個是暫時的。我們不應該試圖保留對它的引用。 *「讓我們的代碼不斷改變它,同時自動調用repaint()並定期更新圖形。」* ..什麼? –