图形

Rect、Triangle、Circle、Line 和 Polyline 是图形组件。创建实体时把其中一个交给它, 这个实体就会每帧绘制该图形,直到你销毁它为止。

from pyxen import *

def start():
    world.spawn(x=110, y=90, shape=Rect(48, 32, fill=(0.4, 0.7, 1.0, 1.0)))
    world.spawn(x=210, y=90, shape=Circle(24, stroke=(1.0, 0.6, 0.3, 1.0), stroke_width=2))

图形是真正的实体,因此实体能做的一切都适用:用 entity.x 和 entity.y 移动它,用 entity.rotation 旋转它,给它设置父级,用补间动画驱动它,把它放到某个图层,用 entity.visible 隐藏它。


用图形组件还是 draw?

Pyxen 用两种方式提供了同样的五个基本图形。它们在屏幕上完全一样,区别只在于存活时间。 另一半请看 draw。

图形组件draw
存活时间一直存在,直到你销毁该实体一帧
位置实体的位置、旋转与缩放你传入的世界坐标
开销一个完整实体:transform、图层、组件存储帧缓冲中的若干个四边形
适合游戏中的物体——飞船、墙壁、固定界面程序化图形、调试显示、HUD 条、拖尾

如果那个东西本身就是游戏里的 存在,用图形组件;如果你只是把自己已经在管理的数据画出来,用 draw。


三个常见的坑

图形在创建时确定,之后无法更改。 并不存在 entity.shape,读取它会抛出 ValueError: component schema does not exist。这与可以赋值的 sprite 和 text 不同。 要更换图形,请销毁该实体并重新创建。

entity.color 不会给图形着色。 它对精灵有效;图形使用自己的 fill 和 stroke 绘制,并忽略它。 请把颜色设置在图形本身上。

描边宽度的参数有两个名字。 Rect、Triangle 和 Circle 使用 stroke_width;Line 和 Polyline 使用 width。两者含义相同。


颜色

每个颜色参数都接受分量取值 0.0–1.0 的 (r, g, b, a) 元组,或者一个 Color。

Rect(40, 20, fill=(1, 0, 0, 1))        # 不透明的红色
Rect(40, 20, fill=(1, 0, 0, 0.35))     # 35% 的红色

既没有 fill 也没有 stroke 的图形什么都不画。 两者初始都是完全透明的,所以 Rect(40, 40) 是一个有效但看不见的实体——这是这里最常见的意外。两个都传,就会得到带描边的填充图形。


类型

Rect(width, height, fill=None, stroke=None, stroke_width=1, pivot=None)

矩形。

参数类型说明
width、heightfloat尺寸,单位像素。
fill元组内部颜色。省略则不填充。
stroke元组描边颜色。省略则不描边。
stroke_widthfloat描边宽度。默认为 1。
pivot元组实体位置所指向的那个点,以图形内的像素表示。默认是角;(width/2, height/2) 表示居中。

Rect 是唯一带 pivot 的图形,它同时也是旋转所围绕的点。

def start():
    world.spawn(x=110, y=90, shape=Rect(48, 32, fill=(0.4, 0.7, 1.0, 1.0)))
    # 以自身位置为中心,因此会原地旋转。
    world.spawn(name="spinner", x=210, y=90,
                shape=Rect(48, 32, stroke=(1.0, 0.6, 0.3, 1.0), stroke_width=2,
                           pivot=(24, 16)))

def update():
    world.get(name="spinner").rotation += 0.02

Triangle(x1, y1, x2, y2, x3, y3, fill=None, stroke=None, stroke_width=1)

经过三个点的三角形,坐标相对于实体位置。

参数类型说明
x1、y1、x2、y2、x3、y3float三个顶点,相对实体的偏移。
fill元组内部颜色。省略则不填充。
stroke元组描边颜色。省略则不描边。
stroke_widthfloat描边宽度。
world.spawn(x=160, y=90, shape=Triangle(0, -20, 18, 14, -18, 14, fill=(1, 1, 0.3, 1)))

Circle(radius, fill=None, stroke=None, stroke_width=1, segments=12)

以实体为中心的圆。

参数类型说明
radiusfloat半径,单位像素。
fill元组内部颜色。省略则不填充。
stroke元组描边颜色。省略则不描边。
stroke_widthfloat描边宽度。
segmentsint用于逼近曲线的直线段数。默认为 12。

圆实际上是多边形。在较小尺寸下 12 段就足够圆润;画大圆时调高,想要刻意看出多边形时调低—— segments=6 就是一个六边形。

world.spawn(x=110, y=90, shape=Circle(28, fill=(0.5, 1.0, 0.7, 1.0), segments=6))
world.spawn(x=210, y=90, shape=Circle(28, fill=(1.0, 0.5, 0.7, 1.0), segments=32))

Line(x1, y1, x2, y2, stroke=None, width=1)

两点之间的直线,相对于实体。

参数类型说明
x1、y1float起点,相对实体的偏移。
x2、y2float终点。
stroke元组线条颜色。
widthfloat线宽。注意是 width,不是 stroke_width。
world.spawn(x=60, y=90, shape=Line(0, 0, 80, -40, stroke=(0.3, 1, 0.5, 1), width=2))

Polyline(points, stroke=None, width=1, closed=False, fill=None)

一串首尾相连的线段。

参数类型说明
points元组或 FloatBuffer扁平序列 (x1, y1, x2, y2, …),不是坐标对的列表。
stroke元组线条颜色。
widthfloat线宽。注意是 width,不是 stroke_width。
closedbool为 True 时把最后一个点连回第一个点。
fill元组填充围成的区域。与 closed=True 搭配最有用。

点之所以是扁平排列,是有意为之:FloatBuffer 本来就是这个形状,因此算好一次的路径可以原样传给 Polyline,无需重新构建。

world.spawn(x=250, y=90,
            shape=Polyline((0, 0, 30, -25, 60, 0), stroke=(1, 0.9, 0.2, 1), width=3))