C ++如何使2d引擎平台独立

时间:2013-04-06 10:45:52

标签: c++ cross-platform abstraction pimpl-idiom

使用跨平台的抽象API创建一个简单的2D精灵引擎 ■演示应完全跨平台,并且没有特定于平台的标头 ■跨平台代码与平台相关代码完全隔离,因为在任何独立于平台的文件中都没有任何平台特定标头包含的跟踪。

我有这个任务,但是我对如何跨平台制作东西感到非常困惑。我已经有了一个能够完成它所需要的东西的引擎,但我需要它是跨平台的。我主要想知道我可以包含哪些内容(或者,我如何知道某些内容是否使用平台特定代码),如果我不能包含因为它们是特定于平台的东西,我不知道如何在不使用该功能的情况下使用该功能包括它。根据同学的说法,解决方案在于抽象和Pimpl,但我找不到它。

2 个答案:

答案 0 :(得分:1)

除了像@ddriver建议的那样简单地在多平台库上构建你的2d引擎之外,你可以为像素颜色分配一个大的缓冲区,并编写代码来渲染所有的基元(单个像素,线条,方框,圆形,椭圆,圆弧,纹理/位图/图像,文本字符)。在此缓冲区中完成帧的渲染后,您可以调用其中的任何库,将此缓冲区显示为屏幕上或窗口中的图像。或者,如果您的代码在没有任何支持库的裸硬件上运行,您只需将此缓冲区复制到图形卡的视频缓冲区中即可。

您的API可能如下所示:

typedef struct
{
  unsigned BitsPerPixel; // 8,16,32
  unsigned ColorScheme; // something that tells the order of the R, G and B components and how many bits are in each or if there's a palette used instead of RGB
  unsigned Width; // in pixels
  unsigned Height; // in pixels
  size_t Size; // buffer size in bytes
  void* Buf; // pointer to the beginning of the buffer itself
  // extra info
} tBuffer;

int BufferInit(tBuffer* Buf, unsigned BitsPerPixel, unsigned ColorScheme, unsigned Width, unsigned Height)
{
  Buf->BitsPerPixel = BitsPerPixel;
  Buf->ColorScheme = ColorScheme;
  Buf->Width = Width;
  Buf->Height = Height;
  Buf->Size = Buf->Width * Buf->Height * Buf->BitsPerPixel / 8;
  Buf->Buf = malloc(Buf->Size);
  if (Buf->Buf != NULL)
  {
    memset(Buf->Buf, 0, Buf->Size);
    return 1;
  }
  return 0;
}

void BufferDone(tBuffer* Buf)
{
  free(Buf->Buf);
  Buf->Buf = NULL;
}

unsigned FindClosest8BitPaletteIndex(unsigned R, unsigned G, unsigned B)
{
  // find the palette element that's closest to the given R, G and B
  // and return its index
}

unsigned BufferRgbToColor(tBuffer* Buf, unsigned R, unsigned G, unsigned B)
{
  switch (Buf->BitsPerPixel)
  {
  case 8:
    return FindClosest8BitPaletteIndex(R, G, B);
  case 16:
    return ((R & 0x1F) << 11) | ((G & 0x3F) << 6) | (B & 0x1F); // 5-6-5
  case 32:
    return ((R & 0xFF) << 16) | ((G & 0xFF) << 8) | (B & 0xFF); // (8)-8-8-8
  default:
    return 0; // error
  }
}

void BufferSetPixel(tBuffer* Buf, unsigned X, unsigned Y, unsigned Color)
{
  switch (Buf->BitsPerPixel)
  {
  case 8:
    *((unsigned char*)Buf->Buf + Buf->Width * Y + X) = Color;
    break;
  case 16:
    *((unsigned short*)Buf->Buf + Buf->Width * Y + X) = Color;
    break;
  case 32:
    *((unsigned*)Buf->Buf + Buf->Width * Y + X) = Color;
    break;
  }
}

然后你可以像这样使用它:

tBuffer buf;
if (BufferInit(&buf, 32, 0, 1024, 768))
{
  BufferSetPixel(&buf, 512, 384, BufferRgbToColor(&buf, 0xFF, 0xFF, 0xFF));
  // make the contents of buf.Buf visible in some way
  BufferDone(&buf);
}

这应该会给你一些想法。

答案 1 :(得分:0)

好吧,如果你想要一个独立于平台的引擎,那么你需要一个可移植的库。

首先,有Qt,它本身提供抽象来做OpenGL图形(只是在几个不同的平台上打开OpenGL上下文可能是一个主要的痛苦我的底部区域,但Qt使它便携,灵活,只是在几行代码)。它还有QML,这是一种声明性语言,开发速度更快。围绕Qt建立了许多2d和3d引擎(查看V-Play)。使用QtQuick2,您可以获得硬件加速图形。您甚至可以在运行时在2d对象上键入运行片段和矢量着色器。

然后有像Allegro和SDL这样的库 - 它们相当便携,虽然对移动平台的支持处于一个非常原始的阶段。图书馆本身远比Qt更基本。两者都支持OpenGL,但它们自己的图形功能微乎其微。

还有JUCE,它提供了一些图形功能,虽然你几乎不得不依赖原始OpenGL,但没有高级抽象。

然后有像MoSync或Marmalade这样的库,这些库是专注于移动平台的,并且桌面支持似乎不存在,所以可能不是一个好选择。

我开始使用Qt的原因是因为它是迄今为止最强大,最灵活且独立于所有替代方案的平台。更不用说有很多书,大量的教程,非常详细的文档和一个重要的社区。这是我使用和经常推荐的。您甚至可以免费使用它开发商业应用程序,唯一的条件是您动态链接。