[英]Java 2D Game Tile Rendering Optimization
我一直在嘗試制作基於2D Tile的游戲,但是在出現某些問題之前並沒有走很多。 游戲非常好,除了它非常慢並且在拼貼之間不斷出現空格。 我嘗試將所有平鋪圖像合並到一個圖像中以使其更平滑地加載,但是沒有用。 我需要有關如何優化游戲以獲得更好的fps的幫助。
大部分多媒體廣告
Player p = new Player();
static Map m = new Map();
Hotbar h = new Hotbar();
static Zombie z = new Zombie();
public static void main(String args[]) {
Thread t1 = new Thread(new Display());
t1.start();
Thread t2 = new Thread(z);
t2.start();
Thread t3 = new Thread(m);
t3.start();
}
@SuppressWarnings("static-access")
public void run() {
while (true) {
try {
oldTime = currentTime;
currentTime = System.currentTimeMillis();
elapsedTime = currentTime - oldTime;
fps = (int) ((1000 / 40) - elapsedTime);
Thread.sleep(fps);
} catch (Exception e) {
e.printStackTrace();
}
if (started) {
p.playerMovement();
p.width = getWidth();
p.height = getHeight();
h.width = getWidth();
h.height = getHeight();
if (p.maptiles != null) {
z.maptiles = new Rectangle[p.maptiles.length];
z.maptiles = p.maptiles;
}
} else {
}
repaint();
}
}
大部分地圖類
BufferedImage backLayer;
BufferedImage backLayer2;
@SuppressWarnings("static-access")
public void createBack() {
backLayer = new BufferedImage(mapwidth * 32, mapheight * 32, BufferedImage.TYPE_INT_ARGB);
Graphics g = backLayer.getGraphics();
Graphics2D gd = (Graphics2D) g;
Color daycolor = new Color(0, 150, 255, 255);
Color nightcolor = new Color(0, 50, 100, Math.abs(time / daylength - 510 / 2));
Color backtilecolor = new Color(10, 10, 20, Math.abs(time / daylength - 510 / 4));
g.setColor(daycolor);
g.fillRect(0, 0, p.width, p.height);
g.setColor(nightcolor);
g.fillRect(0, 0, p.width, p.height);
time++;
if (time > 510 * daylength)
time = 0;
if (time < 100 * daylength || time > 410 * daylength) {
z.SpawnZombie();
} else {
}
g.setColor(backtilecolor);
int i = 0;
for (int x = 0; x < mapwidth; x++) {
for (int y = 0; y < mapheight; y++) {
if (mapdatasky[i] == 0) {
p.mapsky[i] = new Rectangle(x * 32 - p.playerX, y * 32 - p.playerY, 32, 32);
}
if (mapdatasky[i] >= 1) {
g.drawImage(tiles[mapdatasky[i]], x * 32 - p.playerX, y * 32 - p.playerY, 32, 32, null);
mapsky[i] = new Rectangle(x * 32 - p.playerX, y * 32 - p.playerY, 32, 32);
p.mapsky[i] = new Rectangle(x * 32 - p.playerX, y * 32 - p.playerY, 32, 32);
gd.fill(mapsky[i]);
}
i++;
}
}
backLayer2 = backLayer;
}
BufferedImage middleLayer;
BufferedImage middleLayer2;
@SuppressWarnings("static-access")
public void createMiddle() {
middleLayer = new BufferedImage(mapwidth * 32, mapheight * 32, BufferedImage.TYPE_INT_ARGB);
Graphics g = middleLayer.getGraphics();
Color fronttilecolor = new Color(20, 20, 40, Math.abs(time / daylength - 510 / 4));
int i = 0;
for (int x = 0; x < mapwidth; x++) {
for (int y = 0; y < mapheight; y++) {
if (mapdata[i] == -1) {
spawnX = x * 32 - p.width;
spawnY = y * 32 - p.height;
p.spawnX = spawnX;
p.spawnY = spawnY;
}
if (mapdata[i] == 0) {
p.mapsky[i] = new Rectangle(x * 32 - p.playerX, y * 32 - p.playerY, 32, 32);
}
if (mapdata[i] > 0) {
g.drawImage(tiles[mapdata[i]], x * 32 - p.playerX, y * 32 - p.playerY, 32, 32, null);
maptiles[i] = new Rectangle(x * 32 - p.playerX, y * 32 - p.playerY, 32, 32);
p.maptiles[i] = new Rectangle(x * 32 - p.playerX, y * 32 - p.playerY, 32, 32);
}
if (!p.breaking) {
tileid = -1;
}
if (tileid == i) {
g.setColor(new Color(100, 0, 0, 100));
g.fillRect(x * 32 - p.playerX + 16 - timer / (breaktime / 16), y * 32 - p.playerY + 16 - timer / (breaktime / 16), (timer / (breaktime / 16)) * 2, (timer / (breaktime / 16)) * 2);
}
i++;
}
}
g.setColor(fronttilecolor);
g.fillRect(0, 0, p.width, p.height);
middleLayer2 = middleLayer;
}
BufferedImage both;
BufferedImage both2;
public void mergeLayers() {
both = new BufferedImage(mapwidth * 32, mapheight * 32, BufferedImage.TYPE_INT_ARGB);
Graphics g = both.getGraphics();
g.drawImage(backLayer2, 0, 0, mapwidth * 32, mapheight * 32, null);
g.drawImage(middleLayer2, 0, 0, mapwidth * 32, mapheight * 32, null);
both2 = both;
}
public void renderMap(Graphics g) {
g.drawImage(both2, 0, 0, mapwidth * 32, mapheight * 32, null);
if (placetimer > 0)
placetimer--;
}
@Override
public void run() {
while (true) {
try {
oldTime = currentTime;
currentTime = System.currentTimeMillis();
elapsedTime = currentTime - oldTime;
fps = (int) ((1000 / 100) - elapsedTime);
Thread.sleep(fps);
if (!mapset) {
setMap();
mapset = true;
}
createBack();
createMiddle();
mergeLayers();
} catch(Exception e) {
e.printStackTrace();
}
}
}
這是圖塊之間渲染錯誤的圖片
游戲截圖:
我同意在這里進行審核可能是適當的。
但一般提示:如果出於性能原因添加了此“合並”(createBack / createMiddle / mergeLayers):請勿這樣做! 在那里,您將繪制所有圖塊(還有可能也看不到的一些圖塊,當使用g.drawImage直接繪制它們時,它們可能會被剪切掉)。 首先將許多小圖像繪制成大圖像,然后在屏幕上繪制大圖像,這幾乎比直接在屏幕上直接繪制小圖像要快。
如果添加了此“合並”以解決出現的“條紋”:不要這樣做! 條紋來自與繪制圖像不同的線程更改的坐標。 您可以通過更改計算圖塊及其坐標的方式來避免這種情況。 該代碼有點太...“復雜”指出,所以在這里我將使用一些偽代碼:
void paintTiles(Graphics g)
{
for (Tile tile : allTiles)
{
g.drawImage(tile, player.x, player.y, null);
}
}
這里的問題是, 當繪畫線程遍歷所有圖塊時,另一個線程可能會更改玩家坐標。 例如,某些player.x=10
貼可能用player.x=10
和player.y=20
繪制,然后另一個線程更改玩家坐標,因此其余player.x=15
用player.x=15
和player.y=25
並且您會注意到這是在磁貼之間出現的“條紋”。
在最佳情況下,可以很容易地解決此問題:
void paintTiles(Graphics g)
{
int currentPlayerX = player.x;
int currentPlayerY = player.y;
for (Tile tile : allTiles)
{
g.drawImage(tile, currentPlayerX, currentPlayerY, null);
}
}
這樣,“當前”玩家坐標將在圖塊上進行迭代時保持不變。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.