我目前正在開發一個用 Java(FX) 撰寫的 2D 自上而下的游戲。每個新游戲世界都會根據 Perlin Noise 創建一個隨機地圖(背景和植被),創建的物件數量介于 5000 - 7000 之間。植被的各個部分(樹木、灌木、巖石等)被表示作為用影像“填充”的矩形。
在玩游戲時,玩家可以隨時退出當前世界并創建一個新的隨機世界。這樣做時,將創建 5000 - 7000 個新物件,它們都需要一個影像。
據我所知,JavaFX 中有兩種方法可以將影像添加到矩形:
- 通過使用 rectangle.setFill(new ImagePattern(new Image(path)))
- 或者通過添加 CSS 樣式類并使用 -fx-fill: url(path)
使用第一個選項我很快就遇到了 OutOfMemoryErrors,而第二個選項運行得非常順利。我決定啟動 VisualVM 來看看記憶體使用量的實際差異有多大,這太瘋狂了。請參閱下面 VisualVM 的螢屏截圖以了解一個想法(正在創建 3 個新世界):
選項1
選項2
雖然這兩個選項都將影像資料存盤在記憶體的位元組 [] 中,但我想知道記憶體使用量的巨大差異來自哪里?CSS是否能夠以某種方式“填充”矩形而不創建某種影像容器和影像本身?如果是這樣,是否有可能使其適應 JavaFX 的 setFill() 方法?我錯過了什么???
uj5u.com熱心網友回復:
您似乎正在Image為每個矩形創建一個新的。如果您要創建 5000-7000 個矩形,那么您就有 5000-7000Image個實體,它們可能會復制大量相同的影像資料。
相反,只需快取Images 以便每個路徑只加載一個:
private final Map<String, Image> imageCache = new HashMap<>();
然后就
// rectangle.setFill(new ImagePattern(new Image(path));
rectangle.setFill(new ImagePattern(imageCache.computeIfAbsent(path, Image::new)));
如果您的“世界”使用不同的影像,它們之間沒有共享,您可以imageCache.clear()在加載新世界之前呼叫。根據您的用例,快取ImagePattern而不是快取可能是有益的Image,盡管我猜這ImagePattern是一個非常輕量級的圍繞它使用的影像的包裝器。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/446922.html
