性能加载图像游戏 class

performance loading images game class

我正在尝试在为游戏中的对象绘制图像的几种方法之间做出选择。

我希望对象有它们自己的 draw() 方法,但我担心我可能会导致不必要的图像副本或其他一些效率下降,无论是否明显。

第一种方式在关卡开始时加载 BufferedImages

public class levelone{

    BufferedImage imageguy;

    public void draw(Graphics2d g){
        g.drawImage(imageguy, null, guy.getx(), guy.gety());
    }

}

第二种方法在 guy.class 中加载图像,然后在 levelone.class 中调用 guy.draw(g); 从那里绘制图像。

第三种方法在 levelone.class 中加载图像并从 guy.class 中绘制它,在 levelone.class 中仅使用 guy.draw(imageguy, g);

请帮助我了解解决此问题的最佳方法。如果不清楚我在问什么,请告诉我,我会尝试使其更易于理解。

这更像是一个设计问题。首先,这个:

...其他一些效率下降,无论是否明显。

... 不是一种非常健康或富有成效的思维方式。如果不明显,则无需担心。否则,如果您要沉迷于每个时钟周期,您还不如用汇编代码编写游戏。

但这里可能存在更广泛的设计级可扩展性问题。

值得注意的是,将 rendering/drawing 逻辑与高级 class 耦合会成为维护负担。这取决于您的项目范围,但如果它是一个相当大的项目,如果您将 drawing/rendering 逻辑与游戏逻辑分开,您将有更多的喘息空间。然后,您可以将全部注意力集中在 "Monster" 或 "Item" 或类似的东西从游戏设计的角度来看需要做什么,而不用担心它会如何绘制。图是别处画的。

但是,如果我们假设您无论如何都希望在这些对象中拥有绘图逻辑,那么您的问题似乎最终归结为您希望为与游戏中的对象相关的图形存储一些图像缓冲区的位置。

简短的回答是,"it depends"。您有信心做出哪些假设?例如,在您发布的代码中:

public void draw(Graphics2d g){
    g.drawImage(imageguy, null, guy.getx(), guy.gety());
}

...如果您所做的只是将对象图像传输到图形,这似乎有点荒谬。如果你要做的只是将项目的图像 blit 到图形,那么你最好完全消除 draw 方法,将 public 访问器公开到图像,并让一个中心位置承担在正确的时间和地点发送这些图像的责任。

到那时,如果您所做的只是存储图像并在您的对象中公开它们的访问器,那么您还不如让外界关注 loading/storing 这些图像并将它们传递给它们,让你的对象干净,完全没有绘图逻辑。这也将为您提供最大的灵活性来优化绘制内容的时间和方式,而不会干扰您的所有对象。

但是您是否总是要从一个对象中复制图像?是否会出现游戏中的对象可能会绘制其他东西、形状、文本等的情况?如果是这样,您可能希望保留 draw 方法。

所以对我来说最终的问题是,你真的想在你的物体内部绘图吗?

  1. 如果没有,那么您将拥有最大的灵活性来优化您的心脏内容,因为您可以将最有效地加载、存储和绘制图形的责任留给中央渲染引擎而不是将责任分散到游戏中的每个对象上(如果您想以不同的方式做事,则可能必须更改 所有 个对象)。

  2. 如果你确实想要这个,那么你不妨将渲染对象所涉及的所有细节完全封装在一个对象中,包括保留它需要这样做的任何资产,这样外界就不会不必为此烦恼,只需调用 'draw' 并传入绘图目标(例如 Graphics2D)。

所以我建议您的 none 提案可能是理想的。但如果有一个选项可能不好,我会说这是你的第三个。即:

The third way loads the image in levelone.class and draws it from guy.class with just guy.draw(imageguy, g); in levelone.class.

这里的问题是你有点两全其美。您正在向外界泄露此 'guy' 的绘图细节,但外界仍然必须依赖 'guy' 通过将这些绘图细节传回来进行绘图。如果不出意外,你真的想把主要责任交给这个人或外部世界,后者更灵活,但前者更封闭。当外界不得不将一个人的形象传回给这个人供他画画时,你就得不到这些好处。如果你真的想让一个人"draw himself",那么你通常希望能够在没有太多外界帮助的情况下做到这一点。将坚定的责任交给一个实体,而不是分散到多个实体。

关于同一图像的不必要副本,无论您使用中央图像缓存做什么,都可以轻松解决。一个简单的方法就是使用地图。加载图像时,在地图上搜索路径。如果它已经存在,return 对已加载图像的引用。否则加载图像并将 path/image 作为 key/value 对插入地图。