Ir para o conteúdo

Formas

ShapeBatch renderiza primitivas sem textura — retângulos, círculos e linhas — com o mesmo modelo dos sprites: estado NumPy, grupos e um draw call instanciado para o batch inteiro, formas misturadas incluídas.

import fastobjects as fo

win = fo.Window(800, 600)
shapes = fo.ShapeBatch(capacity=1000)

bars = shapes.rects(3, x=[100.0, 200.0, 300.0], y=500.0, w=40.0, h=120.0,
                    color=(0.2, 0.8, 0.3, 1.0))
dots = shapes.circles(50, x=..., y=..., radius=6.0)
grid = shapes.lines(2, x1=[0.0, 400.0], y1=[300.0, 0.0],
                    x2=[800.0, 400.0], y2=[300.0, 600.0], width=1.0)

As três fábricas são vetorizadas como o spawn (escalares ou arrays de tamanho n) e retornam o mesmo tipo SpriteGroupbars.rot += 0.1 e shapes.despawn(dots) funcionam exatamente como com sprites.

As três primitivas

Retângulosrects(n, x, y, w, h, rot=0.0, color=...). A posição é o centro; rot em radianos.

Círculoscircles(n, x, y, radius, color=...). Renderizados como campo de distância (SDF) no fragment shader com bordas anti-aliased de ~1px — nítidos em qualquer tamanho, sem segmentos de polígono. Internamente o bounding box guarda o diâmetro, então grupo.size lê/escreve 2 * radius.

Linhaslines(n, x1, y1, x2, y2, width=1.0, color=...). Linhas são açúcar da API: os endpoints são convertidos (vetorizado) num retângulo rotacionado com a largura dada. Mover uma linha depois significa mover o centro (grupo.pos) ou recriá-la.

Misturando formas

Primitivas diferentes compartilham o mesmo batch e o mesmo draw call:

shapes.rects(1, x=400.0, y=100.0, w=200.0, h=20.0, color=(0.9, 0.2, 0.2, 1.0))
shapes.circles(1, x=400.0, y=300.0, radius=50.0, color=(0.2, 0.5, 0.9, 0.8))
shapes.draw()   # um draw call para as duas

O blending de alpha é o mesmo dos sprites (alpha reto).

Um exemplo completo

import fastobjects as fo

win = fo.Window(800, 600, title="guia de formas")
shapes = fo.ShapeBatch(capacity=64)

spinner = shapes.rects(1, x=400.0, y=300.0, w=160.0, h=24.0,
                       color=(1.0, 0.6, 0.1, 1.0))
shapes.circles(1, x=400.0, y=300.0, radius=8.0, color=(1.0, 1.0, 1.0, 1.0))

@win.frame
def update(dt: float) -> None:
    spinner.rot += 1.5 * dt
    win.clear(0.08, 0.08, 0.10)
    win.draw(shapes)
    if win.keys[fo.KEY_ESCAPE]:
        win.request_close()

win.run()