为调色板图像分配不同的调色板索引

发布于 2025-01-01 14:57:46 字数 549 浏览 2 评论 0原文

我正在用 Python 和 Pygame 编写游戏。为此,图形将采用旧视频游戏机(如 NES)的风格。因此,图形由具有 2 位(4 色)图像的单个图块集文件组成,我希望在加载这些图像时能够为这些图像分配任意 4 色调色板。

我想要做的是使用 8 位(256 色)调色板模式,将调色板分为 64 个子调色板,每个子调色板 4 种颜色。每次我从 2 位图形文件加载 16x16 图块时,我都想为其分配这些虚拟 4 色调色板之一。因此,在原始图块集文件中,调色板索引将为 0-3,因为它是 2 位索引文件。我想将此文件中的图块加载到内存中,并使用一个函数将调色板索引从 0-3 重新分配给我选择的任何调色板偏移量,这样当我将其传输到屏幕时,它就会以我选择的 4 色进行着色调色板——很像 NES 硬件的工作原理。解释起来有点麻烦,所以也许这张图片让它更清楚一点:

在此处输入图像描述

我环顾四周Pygame 和 PIL 的手册并没有找到任何可以让我像这样操作调色板文件的东西。是否还有其他库需要研究,或者是否有我没有看到的更简单的解决方案?

I'm writing a game with Python and Pygame. For this, the graphics will be in the style of old video game consoles like the NES. Therefore, the graphics consist of a single tileset file with 2-bit (4-colour) images, and I want to be able to assign an arbitrary 4-colour palette to these images when loading them.

What I want to do is use an 8-bit (256-colour) palette mode, with a palette that I have divided into 64 sub-palettes of 4 colours each. Every time I load a 16x16 tile from the 2-bit graphics file, I want to assign one of these virtual 4-colour palettes to it. So, in the raw tile set file, the palette indices are going to be 0-3, because it is a 2-bit indexed file. I want to load tiles from this file into memory, and use a function to reassign the palette indices from 0-3 to whatever palette offset I choose, so that when I blit it to screen, it is coloured in my choice of 4-colour palette -- much like the NES hardware works. This gets a little hairy to explain, so maybe this picture makes it a little clearer:

enter image description here

I have looked around the manuals of Pygame and PIL and found nothing that lets me manipulate paletted files like this. Are there any other libs to look into, or is there a simpler solution I'm not seeing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眉目亦如画i 2025-01-08 14:57:46

虽然我个人没有这样做,但在 PyGame 中我相信您正在搜索的调用是:
http://pygame.org/docs/ref/surface.html#Surface.set_palette

Although I personally have not done this, in PyGame I believe the call you're searching for is:
http://pygame.org/docs/ref/surface.html#Surface.set_palette

£噩梦荏苒 2025-01-08 14:57:46

您可以使用 pygame.Surface.set_palette_at() 来完成此操作。在您的情况下,您有 64 个块有四种颜色,因此要重新为特定块着色,您可以使用:

for n, newRGBA in enumerate(fourNewColours):  # where fourNewColours are the RGBA tuples you want to plop into the palette.
    GameSurface.set_palette_at(palette_offset + n, newRGBA)  # where palette_offset is the number of the first palette index you want to replace (adding n to increment your way through the new colours).

这就是替换四种颜色的各个块的方法。首先将每个调色板推入游戏表面可能会更复杂,因为 pygame 似乎近似 blit 图像的调色板,而不是直接替换目标表面的索引。更复杂,因为我不知道如何对具有重复索引 RGBA 值的像素重新着色。 (例如,如果调色板 14/2 和调色板 40/1 都是(90,91,200,255)。我不知道 pygame 是否会将具有该 RGBA 值的所有像素分配给调色板索引 57(来自 Pal14/2)并且对于 Pal40/1,无到 idx 160,或者两者是否保持不同。
如果您想即时对图像重新着色,这可能会成为一个问题。如果您采取稍长的路线并根据需要更改游戏调色板,然后稍后使用相关的新调色板位块传输(或重新位块传输)表面,那么它应该可靠地工作。

希望这有用(尽管已经过去两年半了)!

如果您想查看此答案的较长版本,请查看 此链接。

You can do this with pygame.Surface.set_palette_at(). In your case, you have four colours for sixty-four blocks, so to recolour a specific block, you might use:

for n, newRGBA in enumerate(fourNewColours):  # where fourNewColours are the RGBA tuples you want to plop into the palette.
    GameSurface.set_palette_at(palette_offset + n, newRGBA)  # where palette_offset is the number of the first palette index you want to replace (adding n to increment your way through the new colours).

This is how you might replace individual blocks of four colours. Pushing every palette into the game surface to start with may be more complicated, since pygame seems to approximate blit'd images' palettes instead of replacing the destination surface's indices directly. More complicated because I don't know how you'd go about recolouring pixels with duplicate index RGBA values. (For instance if Palette 14/2 and Palette 40/1 are both (90,91,200,255), for example. I don't know if pygame will assign all pixels with that RGBA value to palette index 57 (from Pal14/2) and none to idx 160 for Pal40/1, or if the two will remain distinct.
This could become an issue if you want to recolour images on the fly. It ought to work reliably if you take the slightly longer route and alter the game palette as needed, then blit (or re-blit) surfaces with the relevant new palettes later.

Hope that's useful (even though it's well over two and a half years later)!

If you want to see a longer-form version of this answer, check out this link.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文