2

我正在开发一款游戏,我需要加载多个图像文件(png、gif 等),我最终希望将其转换为 BufferedImage 对象。在我的设置中,我想从一个 zip 文件“Resources.zip”中加载所有这些图像。该资源文件将包含图像、地图文件和音频文件——所有这些都包含在各种整齐有序的子目录中。我想这样做是因为它(希望)使我的程序的小程序和应用程序版本中的资源加载变得容易。我也希望对于小程序版本,这种方法可以让我轻松显示游戏资源 zip 文件的加载进度(最终可能达到 10MB,具体取决于游戏的精细程度,尽管我希望将其保持在该大小以下,以使其对浏览器友好)。

我在下面包含了我的 zip 处理类。这个想法是,我有一个单独的资源处理类,它创建一个 ZipFileHandler 对象,用于从 Resources.zip 文件中提取特定资源。

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class ZipFileHandler
{
private ZipFile zipFile;

public ZipFileHandler(String zipFileLocation)
{
    try
    {
        zipFile = new ZipFile(zipFileLocation);
    }
    catch (IOException e) {System.err.println("Unable to load zip file at location: " + zipFileLocation);}
}

public byte[] getEntry(String filePath)
{
    ZipEntry entry = zipFile.getEntry(filePath);
    int entrySize = (int)entry.getSize();
    try
    {
        BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
        byte[] finalByteArray = new byte[entrySize];

        int bufferSize = 2048;
        byte[] buffer = new byte[2048];
        int chunkSize = 0;
        int bytesRead = 0;

        while(true)
        {
            //Read chunk to buffer
            chunkSize = bis.read(buffer, 0, bufferSize); //read() returns the number of bytes read
            if(chunkSize == -1)
            {
                //read() returns -1 if the end of the stream has been reached
                break;
            }

            //Write that chunk to the finalByteArray
            //System.arraycopy(src, srcPos, dest, destPos, length)
            System.arraycopy(buffer, 0, finalByteArray, bytesRead, chunkSize);

            bytesRead += chunkSize;
        }

        bis.close(); //close BufferedInputStream

        System.err.println("Entry size: " + finalByteArray.length);

        return finalByteArray;
    }
    catch (IOException e)
    {
        System.err.println("No zip entry found at: " + filePath);
        return null;
    }
}
}

我使用这样的 ZipFileHandler 类:

ZipFileHandler zfh = new ZipFileHandler(the_resourceRootPath + "Resources.zip");
    InputStream in = new ByteArrayInputStream(zfh.getEntry("Resources/images/bg_tiles.png"));

    try
    {
        BufferedImage bgTileSprite = ImageIO.read(in);
    }
    catch (IOException e)
    {
        System.err.println("Could not convert zipped image bytearray to a BufferedImage.");
    }

好消息是,它有效!

但我觉得可能有更好的方法来做我正在做的事情(而且我对使用 BufferedInputStreams 还很陌生)。

最后,我的问题是:

这甚至是个好主意吗?

有没有更好的方法以对小程序和应用程序友好的方式在单个下载/流中加载一大堆游戏资源文件?

我欢迎所有的想法和建议!

谢谢!

4

2 回答 2

1

获取多个资源并将它们放在一个压缩文件中是多个 Web 应用程序的工作方式(即 GWT)。加载一个大文件比加载多个小文件更便宜。这假设您将在应用程序中使用所有这些资源。如果不是延迟加载也是一个可行的选择。
话虽如此,通常最好让应用程序正常工作,然后进行分析以找出瓶颈所在。如果不是这样,您最终会得到很多复杂的代码,并且您需要更长的时间才能让您的应用程序正常工作。10%-20% 的代码需要 80-90% 的时间来执行。在项目基本完成之前,您只是不知道那是哪 10-20%。
如果您的目标是学习技术和修补,那么进展顺利 - 看起来不错。

于 2011-03-28T22:37:45.207 回答
1

如果您使用的是 Java 程序,通常认为将其捆绑为 jar 文件是一种很好的做法。那么为什么不把你的类简单地放在这个 jar 文件中(当然是在目录中)。然后你可以简单地使用

`InputStream stream = MayClass.class.getResourceAsStream(imagePath);`

加载每个图像的数据,而不必自己处理所有 zip(它也适用于实际上不在文件系统上的 jar,例如小程序中的 http url)。

我还假设 jar 将被缓存,但您应该使用外部 zip 文件测量和比较性能与您的解决方案。

于 2011-03-28T22:52:04.707 回答