首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 2D游戏Tile渲染优化

Java 2D游戏Tile渲染优化
EN

Stack Overflow用户
提问于 2014-02-06 17:19:35
回答 1查看 1.5K关注 0票数 1

我一直在尝试做一个2D瓷砖为基础的游戏,但没有走到很远之前,有些东西出了问题。游戏是好的,除了它是极其缓慢和空间不断出现之间的瓷砖。我试着把所有的瓷砖图像放到一个图像中来加载,以使它更流畅,但它没有工作。我需要帮助如何优化我的游戏为更好的fps。

大部分显示类

代码语言:javascript
复制
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();
    }
}

大多数映射类

代码语言:javascript
复制
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();
        }
    }
}

下面是瓷砖之间呈现错误的图片

游戏截图:

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-02-06 17:43:24

我同意在这里进行一次审查也许是适当的。

但是一般提示:如果出于性能原因,添加了这个“合并”(createBack/create年中/mergeLayers):不要这么做!在这里,您正在绘制所有的瓷砖(可能还有一些无论如何都看不见的瓷砖,当它们直接用g.drawImage绘制时,这些瓷砖可能会被剪裁掉)。把许多小的图像画成一个大的图像,然后在屏幕上画一个大的图像,很难比直接在屏幕上画小图像的速度更快。

如果您添加了这个“合并”来解决出现的“条纹”:不要这样做!这些条纹来自正在改变的坐标,与正在绘制图像的线程不同。您可以通过更改计算瓷砖及其坐标的方式来避免这种情况。代码有点太..。为了指出这一点,我将在这里使用一些伪代码:

代码语言:javascript
复制
void paintTiles(Graphics g)
{
    for (Tile tile : allTiles)
    {
        g.drawImage(tile, player.x, player.y, null);
    }
}

这里的问题是,当(画图线程)遍历所有的tiles时,另一个线程可能会更改播放器的坐标。例如,一些瓷砖可能使用player.x=10player.y=20绘制,然后其他线程更改播放器的坐标,因此其余的瓷砖被绘制为player.x=15player.y=25 --您会注意到这是在瓷砖之间出现的“条带”。

在最好的情况下,这个问题可以很容易地解决:

代码语言:javascript
复制
void paintTiles(Graphics g)
{
    int currentPlayerX = player.x;
    int currentPlayerY = player.y;

    for (Tile tile : allTiles)
    {
        g.drawImage(tile, currentPlayerX, currentPlayerY, null);
    }
}

这样,“当前”播放器的坐标将保持不变,同时迭代瓦片。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21609676

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档