简体   繁体   English

Pyglet:blit_into纹理和alpha

[英]Pyglet: blit_into texture and alpha

I've been using pyglet for a while now and I really like it. 我一直在使用pyglet一段时间,我真的很喜欢它。 I've got one thing I'd like to do but have been unable to do so far, however. 不过,我有一件事我想做但却无法做到。

I'm working on a 2D roleplaying game and I'd like the characters to be able to look different - that is to say, I wouldn't like use completely prebuilt sprites, but instead I'd like there to be a range of, say, hairstyles and equipment, visible on characters in the game. 我正在开发一个2D角色扮演游戏,我希望这些角色能够看起来不同 - 也就是说,我不喜欢使用完全预先构建的精灵,但我希望它能有一系列的比方说,发型和装备,在游戏中的角色上可见。

So to get this thing working, I thought the most sensible way to go on about it would be to create a texture with pyglet.image.Texture.create() and blit the correct sprite source images on that texture using Texture.blit_into. 所以为了让这个东西起作用,我认为最有效的方法是用pyglet.image.Texture.create()创建一个纹理,并使用Texture.blit_into在该纹理上创建正确的精灵源图像。 For example, I could blit a naked human image on the texture, then blit a hair texture on that, etc. 例如,我可以在纹理上显示裸露的人体图像,然后在其上点亮头发纹理,等等。

human_base  = pyglet.image.load('x/human_base.png').get_image_data()
hair_style  = pyglet.image.load('x/human_hair1.png').get_image_data()

texture = pyglet.image.Texture.create(width=human_base.width,height=human_base.height)

texture.blit_into(human_base, x=0, y=0, z=0)
texture.blit_into(hair_style, x=0, y=0, z=1)

sprite = pyglet.sprite.Sprite(img=texture, x=0, y=0, batch=my_sprite_batch)

The problem is that blitting the second image into the texture "overwrites" the texture already blitted in. Even though both of the images have an alpha channel, the image below (human_base) is not visible after hair_style is blit on top of it. 问题是将第二个图像blit到纹理中“覆盖”已经嵌入的纹理。即使两个图像都有一个alpha通道,但是hair_style在它上面是blit之后,下面的图像(human_base)是不可见的。

One reading this may be wondering why do it this way instead of, say, creating two different pyglet.sprite.Sprite objects, one for human_base and one for hair_style and just move them together. 一读这可能会想知道为什么这样做,而不是创建两个不同的pyglet.sprite.Sprite对象,一个用于human_base,另一个用于hair_style,只需将它们移动到一起即可。 One thing is the draw ordering: the game is tile-based and isometric, so sorting a visible object consisting of multiple sprites with differing layers (or ordered groups, as pyglet calls them) would be a major pain. 有一点是绘制顺序:游戏是基于图块和等距的,因此对包含不同图层(或有序组,如pyglet称之为)的多个精灵组成的可见对象进行排序将是一个主要的痛苦。

So my question is, is there a way to retain alpha when using blit_into with pyglet. 所以我的问题是,有没有办法在使用pyglet使用blit_into时保留alpha。 If there is no way to do it, please, any suggestions for alternative ways to go on about this would be very much appreciated! 如果没有办法做到这一点,那么,非常感谢任何有关此方法的替代方法的建议!

正确设置混合功能应该解决这个问题:

pyglet.gl.glBlendFunc(pyglet.gl.GL_SRC_ALPHA,pyglet.gl.GL_ONE_MINUS_SRC_ALPHA)

I ran into the very same problem and couldn't find a proper solution. 我遇到了同样的问题,找不到合适的解决方案。 Apparently blitting two RGBA images/textures overlapping together will remove the image beneath. 显然将两个RGBA图像/纹理重叠在一起将删除下面的图像。 Another approache I came up with was using every 'clothing image' on every character as an independent sprite attached to batches and groups, but that was far from the optimal and reduced the FPS dramatically. 我想出的另一个方法是将每个角色上的每个“衣服形象”用作附加到批次和组的独立精灵,但这远远不是最佳的,并且大大降低了FPS。

I got my own solution by using PIL 我使用PIL得到了自己的解决方案

import pyglet
from PIL import Image
class main(pyglet.window.Window):
    def __init__ (self):
        TILESIZE = 32
        super(main, self).__init__(800, 600, fullscreen = False)
        img1 = Image.open('under.png')
        img2 = Image.open('over.png')
        img1.paste(img2,(0,0),img2.convert('RGBA'))
        img = img1.transpose(Image.FLIP_TOP_BOTTOM)
        raw_image=img.tostring()
        self.image=pyglet.image.ImageData(TILESIZE,TILESIZE,'RGBA',raw_image)

    def run(self):
        while not self.has_exit:
            self.dispatch_events()
            self.clear()
            self.image.blit(0,0)
            self.flip()
x = main()
x.run()

This may well not be the optimal solution, but if you do the loading in scene loading, then it won't matter, and with the result you can do almost almost anything you want to (as long as you don't blit it on another texture, heh). 这可能不是最佳解决方案,但是如果你在场景加载中进行加载,那么它就没关系了,结果你几乎可以做任何你想做的事情(只要你没有把它搞定就可以了)另一种纹理,嘿)。 If you want to get just 1 tile (or a column or a row or a rectangular box) out of a tileset with PIL, you can use the crop function. 如果您想从带有PIL的tileset中仅获得1个tile(或列或行或矩形框),则可以使用裁剪功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM