在C++中使我的游戏独立于图形 API
Making my game independent from graphic API in C++
我想让我的游戏独立于所使用的底层图形 API(以便在我想将其移植到另一个平台时减少耦合(。
我目前正在使用 SDL,最初我想将SDL_Renderer封装在一个GraphicAPI_SDL类中,实现我的通用 GraphicAPI 接口。此 API 将创建Image_SDL(封装一个SDL_Texture(,它实现了我的通用映像接口。
我的问题是,当我想使用我的 GraphicAPI 实例渲染图像时,底层GraphicAPI_SDL必须将图像转换为Image_SDL,以便获得SDL_Texture。而这样的演员阵容很丑陋。
处理这种情况的最佳方法是什么?我已经将加载到GraphicAPI_SDL中的每个SDL_Texture存储在我的中,每个 Image 实例只有一个与矢量中纹理索引对应的整数,因此只有 GraphicAPI_SDL 类直接使用 SDL,但是有没有更好的方法继续(例如使用模式(?
如果您使用的是 SDL 2.0(并且只是在制作 2D 游戏(,那么您已经在很大程度上与底层图形 API 分离。SDL 2.0 可以在您设置窗口时自动为您的系统选择正确的渲染器(DirectX 或 OpenGL(,您的代码根本不需要担心。但是,如果您的游戏需要较低级别的绘图控制(即,您正在制作 3D 游戏(,则需要自己处理渲染器。
有关更多信息,请参阅此处:http://wiki.libsdl.org/MigrationGuide#Video
请参阅Irrlicht,它有一个简单但良好的架构,可以满足您在可移植性方面的标准。基本模式是适配器、调解器和工厂方法。这种便携性的关键是良好的界面。我们需要GraphicsApi
、MeshRenderer
和Texture
的抽象类,以及所有图形API的实现。
对于 DirectX9:
-
GraphicsApiDX9
实现GraphicsApi
-
MeshRendererDX9
实现MeshRenderer
-
TextureDX9
实现Texture
对于 OpenGL:
-
GraphicsApiGL
实现GraphicsApi
-
MeshRendererGL
实现MeshRenderer
-
TextureGL
实现Texture
等等。 GraphicsApiDX9
创建TextureDX9
,以保持指向IDirect3DTexture9
的内部指针,以及创建纹理的IDirect3DDevice9
。您正在使用创建的 1 槽Texture
界面,因此您不关心它是如何创建的。
首先,没有平台独立性这样的东西。在每个平台上,您都被迫做出一些假设,这些假设在您的下一个平台上可能是正确的,也可能是不正确的。在任何抽象平台中,您都会做出一些假设(例如平台支持纹理,矩阵变换,四元数,不支持3D等(。抽象平台所做的一切都会产生不必要的复杂性。
只有当您考虑支持 2 个或更多平台时,抽象平台才开始有意义,此时您可以抽象出常见概念(如纹理和矩阵转换(。
因此,除非您计划支持多个平台,否则您能做的最好的事情就是确保您的应用程序正确分层。
SDL 和 OpenGL ES 在大量平台上受支持,除非您计划将游戏移植到专业游戏机,否则 SDL 和 OpenGL ES 涵盖了大多数基础。
我的解决方案(从我的爱好黑客 2d 游戏引擎中剪切的片段(看起来像这样。我从任何类型的纹理的句柄开始(这是独立于图形库的(:
struct MGTexHandle
{
MGTexHandle();
~MGTexHandle();
void* tex;
};
然后,在我的图形库接口类中,我保留了所有方法的通用接口,没有库特定类型。该实现必须移植到每个图形库(我测试过的唯一一个是SDL2(。
例如,将图像加载到独立于图形库的纹理对象(texHandle 参数(:
void* MGWindow::loadBMPImage(std::string fileName, bool transparent)
{
SDL_Surface* loadedImage = NULL;
SDL_Texture* optimizedImage = NULL;
loadedImage = SDL_LoadBMP(fileName.c_str());
if(loadedImage != NULL)
{
if(transparent)
{
// TODO: Make it possible to have other color codes than
// zero represent transparency
SDL_SetColorKey(loadedImage, SDL_TRUE, 0);
}
optimizedImage = SDL_CreateTextureFromSurface(m_Renderer, loadedImage);
SDL_FreeSurface(loadedImage);
}
return (void*)optimizedImage;
}
void MGWindow::loadBMPImage(std::string fileName, MGTexHandle &texHandle, bool transparent)
{
if(texHandle.tex)
{
SDL_DestroyTexture(static_cast<SDL_Texture*>(texHandle.tex));
}
texHandle.tex = loadBMPImage(fileName, transparent);
}
将纹理渲染到屏幕上如下所示:
void MGWindow::drawSprite(const MGTexHandle &imageTexture, int srcX, int srcY, int dstX, int dstY, int width, int height)
{
increaseDrawnSpritesCounter();
SDL_Rect srcRect;
srcRect.x = srcX;
srcRect.y = srcY;
srcRect.w = width;
srcRect.h = height;
SDL_Rect dstRect;
dstRect.x = dstX;
dstRect.y = dstY;
dstRect.w = width;
dstRect.h = height;
SDL_RenderCopy(m_Renderer, static_cast<SDL_Texture*>(imageTexture.tex), &srcRect, &dstRect);
}
标头的开头如下所示:
class MGWindow : public IMGWindow
{
private:
int m_Width;
int m_Height;
int m_Bpp;
bool m_Fullscreen;
std::string m_Title;
SDL_Window* m_Screen;
SDL_Renderer* m_Renderer;
...
IMGWindow
是一个纯虚拟接口。
我可以模拟和存根图形,并执行相当复杂的自动集成测试,涉及除库特定图形例程之外的所有组件。这就是界面的重点,而不是有一天能够移植到另一个库,但现在这也应该非常简单。
- 用于访问容器<T>数据成员的正确 API
- 如何使用Luacneneneba API正确读取字符串和表参数
- C++MySQL C api用户输入行
- C++图形类指针混淆
- 如何使用 AWS Transcribe C++ API 中的'StartTranscriptionJobRequest'?
- 将std::string传递给WriteConsole API
- EvtExportLogneneneba API正在将远程计算机的事件日志保存到远程PC本身.如何将其保存到主机
- Microsoft C++ 用于图形 API 的 Rest SDK
- 在C++中使我的游戏独立于图形 API
- C++图形API带有一个小的学习曲线-linux
- C++中的Facebook图形API
- 是否可以使用 Moz2D 图形 API 在桌面应用程序中绘图
- 图形API上的包装器
- facebook图形API使用libcurl/其他库
- 图形库API设计
- 是否有C或c++的高级图形绘制API ?
- 对于需要生成一些图形的c++项目,推荐使用哪个graphviz库API
- 我可以标记通知为已读,使用图形api
- 便携式图形API
- 图形时间线创建用于分析多线程c++程序的软件API