pyxen.draw

Le module draw dessine des formes directement à l’écran, frame après frame. Appelez-le depuis update() : ce que vous dessinez appartient à cette frame, et la suivante repart de zéro, donc vous le redessinez à chaque frame tant qu’il doit rester visible.

from pyxen import *

def update():
    draw.circle(64, 64, 20, fill=(1, 0.2, 0.3, 1))
    draw.line(0, 0, 128, 128, color=(1, 1, 1, 1))

Rien n’est créé : il n’y a aucune entité à conserver ni rien à détruire. Le débogueur à remonter le temps garde ce que chaque frame a dessiné : quand vous mettez en pause et revenez en arrière, chaque frame montre ses formes comme pendant la partie.


draw ou un composant Shape ?

Pyxen propose les mêmes primitives deux fois. Elles sont identiques à l’écran et ne diffèrent que par leur durée de vie.

Composant Shapedraw
Durée de vieExiste jusqu’à la destruction de l’entitéChaque frame le redessine
PositionPosition, rotation et échelle de l’entitéCoordonnées monde que vous passez
CoûtUne entité complète : transform, calque, stockage de composantsQuelques quads dans le tampon de frame
DébogueurListée et inspectée comme une entitéMontré dans chaque frame où vous revenez
Utile pourLes objets du jeu — vaisseaux, murs, interface fixeL’image de l’état de votre jeu : traînées, superpositions, barres d’interface

Choisissez Shape quand la chose est un élément de votre jeu. Choisissez draw quand vous peignez l’image d’un état que vos entités portent déjà : gardez cet état dans des entités et des composants, où le débogueur et l’Inspecteur le voient, et dessinez-le à chaque frame.


Couleurs

Chaque argument de couleur accepte un tuple (r, g, b, a) dont les composantes vont de 0.0 à 1.0, ou un Color.

draw.rect(10, 10, 40, 20, fill=(1, 0, 0, 1))        # rouge opaque
draw.rect(10, 40, 40, 20, fill=(1, 0, 0, 0.35))     # rouge à 35 %

Les formes pleines ne dessinent rien par défaut. draw.rect, draw.triangle et draw.circle démarrent avec fill et stroke entièrement transparents : un appel qui n’en passe aucun est donc invisible — c’est la surprise la plus fréquente avec ce module. draw.line et draw.polyline utilisent au contraire un blanc opaque par défaut et apparaissent toujours.


Fonctions

draw.line(x1, y1, x2, y2, color=(1,1,1,1), width=1)

Une ligne droite entre deux points.

ArgumentTypeDescription
x1, y1floatPoint de départ, en coordonnées monde.
x2, y2floatPoint d’arrivée.
colortupleCouleur du trait. Blanc opaque par défaut.
widthfloatÉpaisseur du trait en pixels. Vaut 1 par défaut.
def update():
    draw.line(0, 64, 128, 64, color=(0.3, 1, 0.5, 1), width=2)

draw.polyline(points, color=(1,1,1,1), width=1, closed=False)

Une suite de segments reliés entre eux.

ArgumentTypeDescription
pointstuple ou FloatBufferSéquence à plat (x1, y1, x2, y2, …) — pas une liste de paires.
colortupleCouleur du trait. Blanc opaque par défaut.
widthfloatÉpaisseur du trait en pixels.
closedboolSi True, relie le dernier point au premier.
def update():
    draw.polyline((10, 10, 40, 60, 80, 20, 110, 70),
                  color=(1, 0.8, 0.2, 1), width=2)

Les points sont à plat volontairement : c’est déjà la forme d’un FloatBuffer, si bien qu’un tracé calculé une fois peut être passé tel quel à draw.polyline à chaque frame, sans le reconstruire.


draw.rect(x, y, width, height, fill=None, stroke=None, stroke_width=1)

Un rectangle aligné sur les axes. x, y est son coin, pas son centre.

ArgumentTypeDescription
x, yfloatPosition du coin.
width, heightfloatTaille en pixels.
filltupleCouleur intérieure. Omettez pour ne pas remplir.
stroketupleCouleur du contour. Omettez pour ne pas en tracer.
stroke_widthfloatÉpaisseur du contour. Vaut 1 par défaut.
def update():
    # Une barre de vie : fond sombre, remplissage vif, fin contour.
    draw.rect(4, 4, 60, 6, fill=(0.1, 0.1, 0.1, 1))
    draw.rect(4, 4, 60 * health / max_health, 6, fill=(0.2, 1, 0.4, 1))
    draw.rect(4, 4, 60, 6, stroke=(1, 1, 1, 0.5))

draw.triangle(x1, y1, x2, y2, x3, y3, fill=None, stroke=None, stroke_width=1)

Un triangle passant par trois points.

ArgumentTypeDescription
x1, y1, x2, y2, x3, y3floatLes trois sommets.
filltupleCouleur intérieure. Omettez pour ne pas remplir.
stroketupleCouleur du contour. Omettez pour ne pas en tracer.
stroke_widthfloatÉpaisseur du contour.
def update():
    draw.triangle(64, 20, 84, 60, 44, 60, fill=(1, 1, 0.3, 1))

draw.circle(x, y, radius, fill=None, stroke=None, stroke_width=1, segments=12)

Un cercle autour d’un point central.

ArgumentTypeDescription
x, yfloatPosition du centre.
radiusfloatRayon en pixels.
filltupleCouleur intérieure. Omettez pour ne pas remplir.
stroketupleCouleur du contour. Omettez pour ne pas en tracer.
stroke_widthfloatÉpaisseur du contour.
segmentsintNombre de segments droits approximant la courbe. Vaut 12 par défaut.

Un cercle est en réalité un polygone. Douze segments suffisent à paraître rond en petite taille ; augmentez la valeur pour les grands cercles, et baissez-la quand vous voulez un polygone visible.

def update():
    draw.circle(64, 64, 24, fill=(0.2, 0.4, 1, 1), segments=32)
    draw.circle(64, 64, 30, stroke=(1, 1, 1, 0.4), segments=32)

Remarques

  • Les appels à draw ont leur place dans update(). Depuis start(), ils dessinent une seule frame puis disparaissent.
  • Le dessin se fait en coordonnées monde : la caméra le déplace donc. Pour une interface qui reste en place, dessinez relativement à camera ou gardez l’interface sur une caméra fixe.
  • Tout ce qui est dessiné dans une frame passe au-dessus des sprites dessinés cette frame-là.