2014-02-06 95 views
1

我一直试图做一个2D基于区块的游戏,但没有得到很远,有一些东西,之前出问题。游戏很好,除非它非常缓慢,空间不断出现在瓷砖之间。我试图将所有的图片加载到一张图片中,以使图片更平滑,但没有奏效。我需要帮助我如何优化我的游戏以获得更好的fps。的Java 2D游戏瓷砖渲染优化

大多数展示类

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(); 
     } 
    } 
} 

这里是瓷砖

之间的渲染错误的图片

游戏截图: Screenshot

+0

这将是更适合的代码审查现场。 –

回答

2

我同意审查可能是ap在这里成功。

但一般提示:如果添加此“合并”(createBack/createMiddle/mergeLayers)性能方面的原因:不要这样做!在那里你正在绘制所有的瓷砖(并且可能还有一些不可见的东西,当它们直接用g.drawImage绘制时可以被删除)。绘画许多小图像转换成一个大的图像,然后画在屏幕上大图像,当然只会摆在首位直接在屏幕上画小图像快....

如果添加此“合并“解决出现的”条纹“:不要这样做!条纹来自不同线程的坐标,而不是绘制图像的坐标。您可以通过改变计算方块的方式和坐标来避免这种情况。该代码是稍微有点...“复杂”指出来,所以我会用一些伪这里:

void paintTiles(Graphics g) 
{ 
    for (Tile tile : allTiles) 
    { 
     g.drawImage(tile, player.x, player.y, null); 
    } 
} 

这里的问题是,画线程遍历所有瓷砖中,其他线程可能会改变玩家的坐标。例如,一些瓦片可涂上player.x=10player.y=20,那么其他线程改变了玩家的坐标,因此剩余的瓷砖都画着player.x=15player.y=25 - 你会发现这是一个“带”砖之间出现。

在最好的情况下,这可以相当容易地解决:

void paintTiles(Graphics g) 
{ 
    int currentPlayerX = player.x; 
    int currentPlayerY = player.y; 

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

这样,“当前”的球员坐标将保持不变,同时遍历瓷砖。

+0

谢谢,我从来没有意识到它会使用来自其他线程的不同玩家坐标。你会建议我保留现有的线索还是把它们放在一起? – NickM13

+0

我不能给出建议,不知道游戏的(预期)架构。 “通常”是渲染线程(Event Dispatch Thread)和单个游戏线程,我认为对于一个“简单”的拼图游戏来说,这应该足够了。更多的线程往往使事情在同步方面更为复杂,只要没有真正*要执行耗时的任务*,很难有多个线程,这是值得冒这个险的好处,但是......一切没有任何有关游戏的知识 – Marco13