简体   繁体   English

pyglet - 用alpha加载/ blitting图像

[英]pyglet - loading/blitting image with alpha

I'm trying to make a simple application with pyglet. 我正在尝试使用pyglet创建一个简单的应用程序。 My main problem so far is that I can't seem to blit an image with alpha - all of the transparent pixels are converted into black pixels. 到目前为止,我的主要问题是我似乎无法使用alpha对图像进行blit - 所有透明像素都会转换为黑色像素。 I'm not sure whether the problem is with the loading of the image or the blitting. 我不确定问题是关于加载图像还是blitting。 Here is a very basic overview of how I'm trying to render the image: 以下是我如何渲染图像的基本概述:

import pyglet
import pyglet.clock

window = pyglet.window.Window()

window.config.alpha_size = 8

#fancy text
text = pyglet.resource.image("text.png")

#background image
bg = pyglet.resource.image("bg.png")

bg.blit(0, 0)
text.blit(100, 100)

pyglet.app.run()

Any help is appreciated. 任何帮助表示赞赏。 Thanks in advance. 提前致谢。

You most likely just need to enable GL ALPHA blends. 您很可能只需要启用GL ALPHA混合物。

from pyglet.gl import *
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

But first of all, your code is not able to run. 但首先,您的代码无法运行。 Mostly because you don't declare a window.event function to handle the on_draw where you normally render things. 主要是因为你没有声明window.event函数来处理通常渲染事物的on_draw

Secondly, you never clear your window (which will cause a mess). 其次,你永远不会清除你的窗户(这将导致一团糟)。

Here's a minimal working example of your code: 这是代码的最小工作示例:

import pyglet
import pyglet.clock

window = pyglet.window.Window()

window.config.alpha_size = 8

#fancy text
text = pyglet.resource.image("text.png")

#background image
bg = pyglet.resource.image("bg.png")

@window.event
def on_draw():
    window.clear()

    bg.blit(0, 0)
    text.blit(100, 100)

pyglet.app.run()

Now this generates this: 现在生成这个:

在此输入图像描述

And here's a working example of how you use the GL_BLEND feature: 这是一个如何使用GL_BLEND功能的工作示例:

import pyglet
import pyglet.clock
from pyglet.gl import *

window = pyglet.window.Window()

window.config.alpha_size = 8

#fancy text
text = pyglet.resource.image("text.png")

#background image
bg = pyglet.resource.image("bg.png")

@window.event
def on_draw():
    window.clear()
    glEnable(GL_BLEND)

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
    bg.blit(0, 0)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
    text.blit(100, 100)

pyglet.app.run()

This yields a result like so: 这会产生如下结果:

在此输入图像描述

However, this code will quickly become messy. 但是,这段代码很快就会变得混乱。
So there's two things you can do. 所以你可以做两件事。 You can first, put your images into sprite objects. 您可以先将图像放入精灵对象中。 Secondly, make this a bit more object oriented. 其次,使这更加面向对象。

First, we'll use sprites. 首先,我们将使用精灵。

self.fancy_background = pyglet.sprite.Sprite(pyglet.image.load('bg.png'))
self.fancy_background.draw()  # not blit!

Sprites automatically uses transparency, which makes your life (and code) a lot easier. 精灵自动使用透明度,这使您的生活(和代码)更容易。

Secondly, we'll put these into a batch. 其次,我们将这些放入批处理中。
Batches are made to bunch A LOT of sprites so you can call .draw() on the batch, and all sprites in that batch gets insta-rendered. 批量生成一堆精灵,因此您可以在批处理上调用.draw() ,并且该批处理中的所有精灵都会进行insta渲染。

self.background = pyglet.graphics.Batch()
self.fancy_background = pyglet.sprite.Sprite(pyglet.image.load('bg.png'), batch=self.background)
self.background.draw() # background, not fancy_background! And also not blit!!

Last and most certainly not least. 最后也是最重要的。
We'll put this into a class so we can do cool stuff later on. 我们将它放入课堂中,以便我们以后可以做很酷的事情。

import pyglet
import pyglet.clock
from pyglet.gl import *

key = pyglet.window.key

class main(pyglet.window.Window):
    def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
        super(main, self).__init__(width, height, *args, **kwargs)
        self.x, self.y = 0, 0

        self.background = pyglet.graphics.Batch()
        self.texts = pyglet.graphics.Batch()

        self.fancy_background = pyglet.sprite.Sprite(pyglet.image.load('bg.png'), batch=self.background)
        self.fancy_text = pyglet.sprite.Sprite(pyglet.image.load('text.png'), batch=self.texts)

        self.mouse_x = 0
        self.mouse_y = 0
        self.alive = 1

    def on_draw(self):
        self.render()

    def on_close(self):
        self.alive = 0

    def on_mouse_motion(self, x, y, dx, dy):
        self.mouse_x = x
        self.mouse_y = y

    def on_mouse_press(self, x, y, button, modifiers):
        if button == 1: # Left click
            pass

    def on_key_press(self, symbol, modifiers):
        if symbol == key.ESCAPE: # [ESC]
            self.alive = 0

    def render(self):
        self.clear()

        self.background.draw()
        self.texts.draw()

        self.flip()

    def run(self):
        while self.alive == 1:
            self.render()

            # -----------> This is key <----------
            # This is what replaces pyglet.app.run()
            # but is required for the GUI to not freeze
            #
            event = self.dispatch_events()

if __name__ == '__main__':
    x = main()
    x.run()

在此输入图像描述

BAM. BAM。

This code will enable you to create custom functions and custom "player objects" later on for instance. 这段代码可以让您稍后创建自定义函数和自定义“播放器对象”。 Also you can do collision detection easier and the code just looks a lot more structured (I threw in a little bonus features such as keyboard and mouse events). 此外,您可以更轻松地进行碰撞检测,并且代码看起来更加结构化(我投入了一些额外的功能,如键盘和鼠标事件)。

Note tho, that the position of the sprites will default to x=0, y=0 as shown in the last picture. 注意,精灵的位置将默认为x=0, y=0如上图所示。 You can set the position with x=100 either on the variable/handle or when creating the sprite. 您可以在变量/句柄上或创建精灵时设置x=100的位置。

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

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