我试图在游戏中为对象绘制图像的几种方法之间做出决定。
我希望对象拥有自己的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中加载图像,并从level.class中只有guy.draw(imageguy, g);
的guy.class中绘制它。
请帮助我了解解决此问题的最佳方法。如果我不清楚我在问什么,请告诉我,我会尝试让它更易于理解。
答案 0 :(得分:0)
这更像是一个设计问题。首先,这个:
......其他一些效率下降,明显与否。
......不是一种非常健康或富有成效的思维方式。如果它不明显,那就不值得担心了。否则,如果您要在每个时钟周期内进行观察,您也可以使用汇编代码编写游戏。
但是,可能存在更广泛的规模设计级可伸缩性问题。
值得注意的是,将渲染/绘图逻辑与高级类耦合会成为维护负担。这取决于你的项目的范围,但如果它是一个相当大的项目,如果你将绘图/渲染逻辑与游戏逻辑分开,你将有更多的喘息空间。然后你可以全神贯注于从游戏设计的角度来看“怪物”或“物品”或类似东西需要做什么,而不用担心它会如何被绘制。绘图在其他地方完成。
但是如果我们假设您想要在这些对象中包含绘图逻辑,那么您的问题似乎最终归结为您希望为与游戏中的对象相关的图形存储一些图像缓冲区。
简短的回答是,“这取决于”。您有信心做出哪些假设?例如,在您发布的代码中:
public void draw(Graphics2d g){
g.drawImage(imageguy, null, guy.getx(), guy.gety());
}
...如果您所做的只是将对象图像blit到图形,这似乎有点荒谬。如果您要做的只是将项目的图像blit到图形,那么您可以直接消除draw
方法,公开图像的公共访问者,并让一个中心位置负责在合适的时间和地点拍摄这些图像。
在这一点上,如果您所做的只是存储图像并在对象中暴露访问者,那么您也可以让外界关注加载/存储这些图像并将它们点亮,留下您的对象干净,没有绘画逻辑。这也将为您提供最大的灵活性,以便在不侵入所有物体的情况下优化绘制事物的时间和方式。
但是你总是只想从一个物体上看图像吗?是否会出现游戏中的物体可能会绘制其他物品,形状,文字等的情况?如果是这样,您可能希望保留draw
方法。
所以对我来说最终的问题是,你真的想在你的物体内画画吗?
如果没有,那么您将拥有最大的灵活性来优化您的内心,因为您可以最有效地负责加载和存储以及将图形绘制到中央渲染引擎,而不是将责任分散到游戏中的每个对象(如果您想以不同的方式做事,可能需要更改所有)。
如果你确实需要这个,那么你也可以完全封装在对象内部渲染对象所涉及的所有细节,包括保留它需要做的任何资产,以便外部世界不必打扰它,可以调用'draw'并传入绘图目标(例如Graphics2D)。
所以我建议你的提案可能都不理想。但如果有一个选项可能不好,我会说这是你的第三个。那就是:
第三种方法在levelone.class中加载图像并从中绘制 guy.class with guy.draw(imageguy,g);在levelone.class中。
这里的问题是你有两种世界中最糟糕的情况。你正在把这个'家伙'的绘图细节泄漏到外面的世界,但是外面的世界仍然需要依靠'家伙'来绘制那些绘图细节来进行绘图。如果没有别的,你想要真的在这里给予家伙或外部世界主要责任,后者更灵活,但前者更加封装。当外面的世界必须将一个人的形象传回给那个人画画的那个人时,你就不会得到这些好处。如果你真的想让一个人“画画”,那么你通常希望能够在没有太多外界帮助的情况下做到这一点。赋予一个实体公司的责任,而不是将其传播到多个实体。
关于同一图像的不必要副本,无论您使用中央图像缓存做什么,都可以轻松解决。一种简单的方法就是使用地图。加载图像时,在地图中搜索路径。如果它已存在,则返回对已加载图像的引用。否则加载图像并将路径/图像作为键/值对插入到地图中。