簡體   English   中英

試圖繪制精靈或更改圖片pyglet

[英]trying to draw over sprite or change picture pyglet

我正在嘗試學習pyglet並使用問卷調查的東西練習一些python編碼,但是我無法找到一種方法來使背景圖片在10秒鍾之內被刪除或繪制在上面或某物上。 我是新來的,並且缺乏很多我需要的知識,謝謝您的幫助!

import pyglet
from pyglet.window import Window
from pyglet.window import key
from pyglet import image
import time

card1 = False
cat_image = pyglet.image.load("cat.png")
dog_image = pyglet.image.load("dog.png")
image = pyglet.image.load("backg.png")
background_sprite = pyglet.sprite.Sprite(image)
cat = pyglet.sprite.Sprite(cat_image)
dog = pyglet.sprite.Sprite(dog_image)
window = pyglet.window.Window(638, 404, "Life")
mouse_pos_x = 0
mouse_pos_y = 0
catmeme = pyglet.image.load("catmeme.png")
sprite_catmeme = pyglet.sprite.Sprite(catmeme)

@window.event
def on_draw():
    window.clear()
    background_sprite.draw()
    card_draw1(63, 192, 385, 192)
def card1():
    while time.time() < (time.time() + 10):
        window.clear()
        sprite_catmeme.draw()
@window.event
def card_draw1(x1, y1, x2, y2):
    cat.set_position(x1, y1)
    dog.set_position(x2, y2)
    cat.draw()
    dog.draw()
def card_draw2():
    pass
@window.event
def on_mouse_press(x, y, button, modifiers):
    if x > cat.x and x < (cat.x + cat.width):
        if y > cat.y and y < (cat.y + cat.height):
            card1()
game = True
while game:
    on_draw()
    pyglet.app.run()

順序和執行操作時存在一些缺陷。
我將盡力描述它們,並為您提供一段代碼,使其可能更適合您的需求。

我也認為您對問題的描述有點像XY問題 ,這在您認為您已經接近解決方案的復雜問題上尋求幫助時很常見,因此您正在尋求有關已解決方案的幫助提出來,而不是問題。

我假設您想在10秒鍾內顯示“啟動畫面”,這恰好是您的背景? 然后在其cat.png顯示cat.pngdog.png ,對嗎?

如果是這樣,您可能需要在這里進行一些更改才能使其正常工作:

draw()函數

它並沒有真正更新屏幕,只是將內容添加到圖形內存中。 更新屏幕的是您自己,或者是告訴圖形庫您已經完成了向屏幕中添加內容的工作,現在該更新所有.draw() 'n了。 因此,循環中需要的最后一件事是window.flip() ,以使繪制的內容真正顯示出來。

如果嘗試擺動窗口,您的情況可能會顯示出來,由於pyglet的內部機制如何工作,它應該觸發場景的重新繪制。

如果您不調用.flip() - redraw()調用將永遠不會發生的可能性-同樣,這是Pyglet / GL的內部機制,它告知圖形卡某些內容已更新,我們完成了更新,是時候重繪場景了。

一個場景

這是用戶看到的最常用的詞。
我可能會在文本中提到很多,所以很高興知道這是用戶正在查看的內容,而不是您看到的.draw() 'n或已刪除的內容,這是當前的最新渲染。圖形卡到顯示器。

但是由於圖形緩沖區的工作方式,我們可能已經刪除了內容或將內容添加到了內存中,而尚未實際繪制它。 請記住這一點。

pyglet.app.run()調用

這本身就是一個永無止境的循環,因此在一段while game:循環並沒有任何意義,因為.run()將“掛起”整個應用程序,您要執行的任何代碼都必須在def on_draw或從圖形代碼本身內部生成的event

為了更好地理解這一點,請看一下我的代碼,這些年來,我在SO上粘貼了幾次,它是兩個自定義類的基本模型,繼承了Pyglet的行為,但允許您設計自己的類表現稍有不同。

而且大多數功能都在on_??? 函數,幾乎總是用於捕獲Events的函數。 Pyglet具有很多內置功能,我們將使用自己的功能覆蓋它們(但名稱必須相同)

import pyglet
from pyglet.gl import *

key = pyglet.window.key

class CustomSprite(pyglet.sprite.Sprite):
    def __init__(self, texture_file, x=0, y=0):
        ## Must load the texture as a image resource before initializing class:Sprite()
        self.texture = pyglet.image.load(texture_file)

        super(CustomSprite, self).__init__(self.texture)
        self.x = x
        self.y = y

    def _draw(self):
        self.draw()

class MainScreen(pyglet.window.Window):
    def __init__ (self):
        super(MainScreen, self).__init__(800, 600, fullscreen = False)
        self.x, self.y = 0, 0

        self.bg = CustomSprite('bg.jpg')
        self.sprites = {}
        self.alive = 1

    def on_draw(self):
        self.render()

    def on_close(self):
        self.alive = 0

    def on_key_press(self, symbol, modifiers):
        if symbol == key.ESCAPE: # [ESC]
            self.alive = 0
        elif symbol == key.C:
            print('Rendering cat')
            self.sprites['cat'] = CustomSprite('cat.png', x=10, y=10)
        elif symbol == key.D:
            self.sprites['dog'] = CustomSprite('dog.png', x=100, y=100)

    def render(self):
        self.clear()
        self.bg.draw()

        for sprite_name, sprite_obj in self.sprites.items():
            sprite_obj._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()

x = MainScreen()
x.run()

現在,此代碼有意保持簡單,我通常粘貼在SO上的完整代碼可以在Torxed / PygletGui上找到, gui.py是其中的大部分來源,它是主循環。

我在這里所做的只是通過使用類中的“實際”函數來替換裝飾器 該類本身從傳統的pyglet.window.Window繼承這些函數,並且一旦您將這些函數命名為與一次繼承的函數相同,就將您決定的內容替換Window()的核心功能。在這種情況下,我模仿相同的功能,但添加一些我自己的功能。

on_key_press

這樣的例子就是on_key_press() ,它通常只包含一個pass調用並且不執行任何操作,在這里,我們檢查是否按下了key.C ,如果是的話-我們在self.sprites .. self.sprites添加了一個項目在我們的render()循環中,其中的所有內容都會在背景之上渲染。

這是我使用的圖片:

(名為bg.jpgcat.pngdog.png 注意不同的文件結尾

bg.jpg cat.png dog.png

類:的CustomSprite

CustomSprite是一個非常簡單的類,旨在使您現在的生活更輕松,沒有別的。 它的功能非常有限,但是做得很少。

靈魂的目的是獲取一個文件名,將其作為圖像加載,然后您可以將該對象像傳統的pyglet.sprite.Sprite一樣對待,這意味着您可以在其中移動並以多種方式對其進行操作。

它節省了幾行代碼,必須加載所需的所有圖像,並且如您在gui_classes_generic.py中看到的那樣,您可以向正常的sprite類添加一堆“不可見”且通常不易使用的函數。

我一堆用! 但是代碼變得非常復雜,所以我故意使這篇文章變得簡單。

翻轉功能

即使在我的課堂上,我仍然需要使用flip()來更新屏幕內容。 這是因為.clear()會如您.clear()清除窗口,這也會觸發場景的重繪。

在某些情況下,如果數據足夠大或發生其他事情(例如移動窗口bg.draw() ,則bg.draw()可能會觸發重繪。

但是調用.flip()會告訴GL后端強制重繪。

進一步優化

有一種叫做批處理渲染的東西,基本上,圖形卡被設計為可容納大量數據並一次性渲染,因此在多個項目上調用.draw()只會在GPU甚至沒有機會發光之前阻塞CPU。 閱讀有關批量渲染和圖形的更多信息! 它將為您節省很多幀率。

另一件事是在render()循環中保留盡可能少的功能,並將事件觸發器用作您的主要編碼樣式來源。
Pyglet可以很好地做到快速,特別是如果您僅在事件驅動的任務上執行操作。

盡量避免使用計時器,但是如果您確實需要使用時間來進行操作(例如在一定時間后刪除cat.png ,請使用clock / time事件調用刪除貓的函數。 不要嘗試使用自己的t = time()樣式的代碼,除非您知道將代碼放置在何處以及原因。 有一個很好的計時器,我很少使用。。但是,如果您要開始的話,應該這樣做。

這一直是一堵牆的地獄,我希望它能教給您一些有關圖形和事物生活的知識。 繼續前進,進入這種東西是一個障礙,但是一旦您掌握了它,這將是非常有意義的(我還沒有):)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM