图形
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、height | float | 尺寸,单位像素。 |
fill | 元组 | 内部颜色。省略则不填充。 |
stroke | 元组 | 描边颜色。省略则不描边。 |
stroke_width | float | 描边宽度。默认为 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、y3 | float | 三个顶点,相对实体的偏移。 |
fill | 元组 | 内部颜色。省略则不填充。 |
stroke | 元组 | 描边颜色。省略则不描边。 |
stroke_width | float | 描边宽度。 |
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)
以实体为中心的圆。
| 参数 | 类型 | 说明 |
|---|---|---|
radius | float | 半径,单位像素。 |
fill | 元组 | 内部颜色。省略则不填充。 |
stroke | 元组 | 描边颜色。省略则不描边。 |
stroke_width | float | 描边宽度。 |
segments | int | 用于逼近曲线的直线段数。默认为 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、y1 | float | 起点,相对实体的偏移。 |
x2、y2 | float | 终点。 |
stroke | 元组 | 线条颜色。 |
width | float | 线宽。注意是 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 | 元组 | 线条颜色。 |
width | float | 线宽。注意是 width,不是 stroke_width。 |
closed | bool | 为 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))