簡體   English   中英

Pyglet。 如何動態更改頂點的圖片(動畫)。 OpenGL的

[英]Pyglet. How to change picture(animate) for vertices dynamically. OpenGL

環境:

Python:3.6.6
pyglet版本:1.3.2

代碼庫:

abstract_model.py

import pyglet


def get_texture_group(file, order_group_index):
    texture = pyglet.image.load(file).texture
    order_group = pyglet.graphics.OrderedGroup(order_group_index)
    return pyglet.graphics.TextureGroup(texture, order_group)


class AbstractModel(object):

    def _create_as_vertex(self):
        v_x = self.cell_data.get("x") * 32
        v_y = self.cell_data.get("y") * -1 * 32

        texture_group = self.map_type_iamge.get(self.cell_data.get("t"))
        x_offset = self.x_offset * self.scale

        x, y, z = v_x + x_offset, v_y, self.z
        x_ = (texture_group.texture.width * self.scale + x_offset + v_x)
        y_ = (texture_group.texture.height * self.scale + v_y)

        tex_coords = ('t2f', (0, 0, 1, 0, 1, 1, 0, 1))

        self.vertices = self.batch.add(
            4, pyglet.gl.GL_QUADS,
            texture_group,
            ('v3f', (x, y, z,
                     x_, y, z,
                     x_, y_, z,
                     x, y_, z)),
            tex_coords)

    def _animate(self, dt):
        # lets assume that I have list of pyglet.graphics.TextureGroup
        # and they should somehow be drawn one after other
        print("I need change image. dt=", dt, self)
        pyglet.clock.schedule_once(self._animate, 1)

ground3d.py

import os
import pyglet

import settings
from models import abstract_model


GROUND_DIR = os.path.join(settings.STATIC_DIR, "ground")

order_group_index = 0

map_type_iamge = {
    1: abstract_model.get_texture_group(os.path.join(GROUND_DIR, "w1.png"), order_group_index),
    2: abstract_model.get_texture_group(os.path.join(GROUND_DIR, "t1.png"), order_group_index),
    1001: abstract_model.get_texture_group(os.path.join(GROUND_DIR, "t1_direction.png"), order_group_index),
}


class Ground3D(abstract_model.AbstractModel):

    def __init__(self, cell_data, batch):

        self.batch = batch
        self.cell_data = cell_data
        self.map_type_iamge = map_type_iamge
        self.scale = 1
        self.x_offset = 0
        self.z = 0
        self.entity = None

        self._create_as_vertex()
        pyglet.clock.schedule_once(self._animate, 1)

說明:

我有模型(只是平直的例子),它應放在3個維度上。 這些模型應該是動畫的,比如picture_1,在第二張圖片之后,......等等。
正如我從上一個問題中所理解的那樣,在3D批處理中使用pyglet.sprite.Sprite()並不是一個好主意。

題:

我如何在self.vertices上更改圖片(使用TextureGroup或任何其他方法)?

或者我使用哪些arroach /類來實現它。 我找不到任何這樣的例子(對於我的簡單視覺)通常情況作為三維平面模型的動畫。

關於vertices旋轉/移動/調整大小有很多例子,但是如何建立一個正確的問題(動畫方面)來獲得谷歌的答案 - 我不知道。

PS :如果你, 讀者 ,對這個主題有任何有用的鏈接(對於pyglet或僅用於OpenGL),我將非常感謝你在評論中分享這個鏈接。

紋理坐標。

對於所有動畫的所有幀,你應該有一個紋理圖集。

優選地,一切都應該具有相同的動畫速度和相同的幀數。

假設有兩個精靈,整個動畫有2幀,它們存儲在64x64紋理圖譜中。 (編輯:對不起歧義,64x64 PIXELS,只是因為它可能意味着我們有64x64平鋪圖集,在我提到的其他地方也一樣)

現在,您需要一個具有全局值的全局計時器,它指示當前動畫幀 ,而不是游戲幀。 它應該與幀速率無關。

所述值應該每隔一段時間以您想要的速度更新,如下所示:

current_frame = (current_frame + 1) % animation_length

由於我們在此示例中有2個幀,因此結果如下:

# init
animation_length = 2
current_frame = 0

# updates:
current_frame = (0 + 1) % 2 # 1 % 2 -> 1
current_frame = (1 + 1) % 2 # 2 % 2 -> 0
...

現在,只有在幀更改時才需要更新所有精靈的UV。

UV從左到右開始從0到1(據我記得,為了這個例子,他們這樣做,噓)。

由於我們每個都有2個幀,我們可以像這樣計算UV坐標中的“tile”:

tile_width = 1.0 / frames # 2 frames each, width will be 0.5
tile_height = 1.0 / sprites # 2 sprites each, height will be 0.5 too, perfect

現在,在第一幀,你生成你的UV正常,你只需要垂直ID或其他東西,並使用tile_height * sprite_id來獲得當前的V坐標,你的U計算像tile_width * current_frame

這假設你已經有sprite批處理所以你所做的就是在更新時查看每個sprite,基本上只需用新幀重新計算新的UV,這意味着所有的精靈都會將它們的幀更改為下一個!

如果你想擁有一個獨立於彼此的系統,比如說某些系統的動畫非常慢,而對其他系統來說更快,那么你需要不同的精靈批量或正確計算你需要在哪里更新頂點緩沖區數組中的UV。 其他所有內容都完全相同,除非現在current_frame不是全局的,而是包含在內,優先包含在管理動畫定時器的某個列表或單獨對象中。

您不需要在着色器中更改任何內容,只需要對框架使用正確的UV,就可以進行設置。

順便說一句,這是非常基本的,你可以自己應用一些邏輯,所以你可以在紋理中使用16x16網格的32x32像素,每行精靈有4種不同的動畫,這些可以是精靈的狀態(攻擊,運行等) ),但你如何做到完全取決於你,最重要的是,讓它發揮作用。 祝好運。

但是,如果按照我說的方式進行,那么狀態將是另一個整數,UV為狀態,假設所有狀態具有完全相同的寬度,它將是這樣的:

state_width = 1 / states
tile_width = 1 / (states * frames_per_state)
U = state_width * current_state + tile_width * current_frame

現在,出現了一個問題,玩家可以在最后一個攻擊框架開始他的動畫。

這是正常的,有行動的實體應該都有個別的計時器,我上面描述的,是大量的精靈,只是背景,如草。 現在,當您將其分割時,您可以通過適當的方式在分配新狀態時當前幀重置為0。

如果你的實體是對象,你可以編寫適當的方法,每次使用這些精靈重建精靈批處理時重新計算UV,然后定時器本身就可以包含在對象中。

我們需要畫一些東西嗎? 檢查動畫狀態,改變了嗎,沒有? 發送之前計算過的UV,否則,稍等一下,我們需要重新計算,然后再將它們添加到VBO,好吧,渲染你的東西,最后,它會顯得好像你有動畫,即使真的,它是只是一個簡單但很棒的UV操作。

祝好運。

暫無
暫無

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

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